Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c NSTextView在写入USB设备时未在循环中更新_Objective C_Cocoa_User Interface - Fatal编程技术网

Objective c NSTextView在写入USB设备时未在循环中更新

Objective c NSTextView在写入USB设备时未在循环中更新,objective-c,cocoa,user-interface,Objective C,Cocoa,User Interface,我正在编写一个Objective-C应用程序,它与USB设备通信。应用程序将某些数据连续写入设备,并在textView(NSTextView的对象)中显示写入操作的状态。当我从设备获取写操作状态时,我调用循环中的-[NSTextView insertText::方法 问题在于,每次调用-insertText:时,NSTextView不会得到更新。只有在执行整个循环之后,我才能获得NSTextView的全部内容 我没有看到NSTextView类的适当刷新或更新方法。如何接收操作状态并同时更新NST

我正在编写一个Objective-C应用程序,它与USB设备通信。应用程序将某些数据连续写入设备,并在textView(NSTextView的对象)中显示写入操作的状态。当我从设备获取写操作状态时,我调用循环中的
-[NSTextView insertText::
方法

问题在于,每次调用
-insertText:
时,NSTextView不会得到更新。只有在执行整个循环之后,我才能获得NSTextView的全部内容

我没有看到NSTextView类的适当刷新或更新方法。如何接收操作状态并同时更新NSTextView

- (IBAction)notifyContentHasChanged:(NSInteger) block {
    NSString *str;
    str = [NSString stringWithFormat:@"Block Written Successfully: %d\n", block];
    [data insertText:str];
}

- (IBAction)func {
    while(USB_SUCCESS(status))
    {
        printf("\nBlocks Written Successfully: %d",BlockCnt);
        [refToSelf notifyContentHasChanged:BlockCnt];
    }
}

请注意,控制台上的
printf
会及时更新,但NSTextView不会更新。

Mac OS X不会立即将视图更改刷新到屏幕上,以避免在这种情况下常见的闪烁和撕裂。这意味着您不能在更新视图时只是坐在循环中执行阻塞操作;如果执行此操作,则应用程序的人机界面中的视图或任何其他内容都不会更新,应用程序将显示为挂起,并最终获得旋转光标

(当应用程序在一小段时间后没有与Windows服务器通信时,会出现旋转光标;从设计上说,没有办法抑制这种情况。它不是指“等待”,而是指“此应用程序已陷入困境”,您应该努力确保它永远不会出现在用户面前。)

要管理Cocoa中的阻塞操作,可以执行以下两种操作之一:

  • 您可以在后台线程中执行阻塞操作,并将结果传递给主线程以更新人机界面。例如,您可以使用
    select(2)
    和标准UNIX文件I/O调用以这种方式进行I/O或套接字通信

  • 如果兼容版本可用,您可以在运行循环(如主运行循环)上安排操作;这通常会为您管理阻止版本操作的后台线程。例如,NSFileHandle在文件描述符上提供了与运行循环兼容的抽象;NSStream也为套接字通信执行此操作


  • Mac OS X不会立即将视图更改刷新到屏幕上,以避免这种情况下常见的闪烁和撕裂。这意味着您不能在更新视图时只是坐在循环中执行阻塞操作;如果执行此操作,则应用程序的人机界面中的视图或任何其他内容都不会更新,应用程序将显示为挂起,并最终获得旋转光标

    (当应用程序在一小段时间后没有与Windows服务器通信时,会出现旋转光标;从设计上说,没有办法抑制这种情况。它不是指“等待”,而是指“此应用程序已陷入困境”,您应该努力确保它永远不会出现在用户面前。)

    要管理Cocoa中的阻塞操作,可以执行以下两种操作之一:

  • 您可以在后台线程中执行阻塞操作,并将结果传递给主线程以更新人机界面。例如,您可以使用
    select(2)
    和标准UNIX文件I/O调用以这种方式进行I/O或套接字通信

  • 如果兼容版本可用,您可以在运行循环(如主运行循环)上安排操作;这通常会为您管理阻止版本操作的后台线程。例如,NSFileHandle在文件描述符上提供了与运行循环兼容的抽象;NSStream也为套接字通信执行此操作


  • 您应该能够通过-setNeedsDisplay:方法刷新NSTextView。

    您应该能够通过-setNeedsDisplay:方法刷新NSTextView。

    我有一个从“网络”访问数据并将其填充到数据库的循环。在处理过程中,我想要一个类似控制台的窗口(不是Xcode中的窗口,因为这是一个编译过的应用程序)

    所以我有一个NSTextView,每次循环时我都会更改它的文本存储并滚动到底部。不幸的是,只有在循环完成时(尽管正确),才会发生可见的更改


    是否有一种简单的“确定,立即更新屏幕”方法,而不必获取低级别或编写更多代码?

    我有一个循环,它从“网络”访问数据并将其填充到数据库中。在处理过程中,我想要一个类似控制台的窗口(不是Xcode中的窗口,因为这是一个编译过的应用程序)

    所以我有一个NSTextView,每次循环时我都会更改它的文本存储并滚动到底部。不幸的是,只有在循环完成时(尽管正确),才会发生可见的更改

    是否有一种简单的“确定,立即更新屏幕”方法,而无需获得较低级别或编写更多代码?

    您必须使用:

    //Creates the background thread.
    dispatch_queue_t backgroundQueue = dispatch_queue_create("Network", nil);
    
    创建一个新线程。 然后,将代码包装为:

    //Runs code in background thread.
    dispatch_async(backgroundQueue, ^(void){
        //Code Here.
    });
    
    更新到UI的内容应包装在:

    //Sends code within the background thread to the main thread.
    dispatch_async(dispatch_get_main_queue(), ^(void){
        //Code Here.
    });
    
    因此,在您的代码中:

    - (IBAction)notifyContentHasChanged:(NSInteger) block {
        NSString *str;
        str = [NSString stringWithFormat:@"Block Written Successfully: %d\n", block];
        [data insertText:str];
    }
    
    - (IBAction)func {
        dispatch_queue_t backgroundQueue = dispatch_queue_create("Network", nil);
        dispatch_async(backgroundQueue, ^(void){
            while(USB_SUCCESS(status))
            {
                printf("\nBlocks Written Successfully: %d",BlockCnt);
                dispatch_async(dispatch_get_main_queue(), ^(void){
                    [refToSelf notifyContentHasChanged:BlockCnt];
                });
            }
        });
    }
    
    您必须使用:

    //Creates the background thread.
    dispatch_queue_t backgroundQueue = dispatch_queue_create("Network", nil);
    
    创建一个新线程。 然后,将代码包装为:

    //Runs code in background thread.
    dispatch_async(backgroundQueue, ^(void){
        //Code Here.
    });
    
    更新到UI的内容应封装在:

    //Sends code within the background thread to the main thread.
    dispatch_async(dispatch_get_main_queue(), ^(void){
        //Code Here.
    });
    
    因此,在您的代码中:

    - (IBAction)notifyContentHasChanged:(NSInteger) block {
        NSString *str;
        str = [NSString stringWithFormat:@"Block Written Successfully: %d\n", block];
        [data insertText:str];
    }
    
    - (IBAction)func {
        dispatch_queue_t backgroundQueue = dispatch_queue_create("Network", nil);
        dispatch_async(backgroundQueue, ^(void){
            while(USB_SUCCESS(status))
            {
                printf("\nBlocks Written Successfully: %d",BlockCnt);
                dispatch_async(dispatch_get_main_queue(), ^(void){
                    [refToSelf notifyContentHasChanged:BlockCnt];
                });
            }
        });
    }
    

    通常,当视图的某个属性更改时,您不会告诉视图-setNeedsDisplay:从外部-视图会告诉自己-setNeedsDisplay:。此外,任何重新显示都将在运行循环的下一个过程中发生,而不是立即发生,这正是提问者所看到的。你能提供更多的信息说明为什么应该避免这样做,或者我误解了你的意思吗?谢谢。通常,您不会告诉视图-setNeedsDisplay:从外部-视图告诉自己-setNeedsDi