Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.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 目标C-与NSArray控制器刷新的NSCollection不一致_Objective C_Macos_Delegates_Nscollectionview - Fatal编程技术网

Objective c 目标C-与NSArray控制器刷新的NSCollection不一致

Objective c 目标C-与NSArray控制器刷新的NSCollection不一致,objective-c,macos,delegates,nscollectionview,Objective C,Macos,Delegates,Nscollectionview,我编写了一个程序,它播放一个歌曲队列,这些歌曲在后台任务中使用代理进行处理。我将响应发送回AppController,以移动NSSlider以显示正在播放的歌曲的进度,并删除刚刚播放的歌曲的NSCollection视图实体。大多数时候作品都很棒,但是在两三首歌之后;实体消失,但剩余的对象不会重新排列并在屏幕上向上移动,直到我使用鼠标或键盘使主屏幕聚焦。我对其他类似的问题提出了一些建议,通常得到了相同的回答。我现在使用的代码是: -(void) songPlayer:(SongPlayer *)p

我编写了一个程序,它播放一个歌曲队列,这些歌曲在后台任务中使用代理进行处理。我将响应发送回AppController,以移动NSSlider以显示正在播放的歌曲的进度,并删除刚刚播放的歌曲的NSCollection视图实体。大多数时候作品都很棒,但是在两三首歌之后;实体消失,但剩余的对象不会重新排列并在屏幕上向上移动,直到我使用鼠标或键盘使主屏幕聚焦。我对其他类似的问题提出了一些建议,通常得到了相同的回答。我现在使用的代码是:

-(void) songPlayer:(SongPlayer *)player removeEntity:(DesktopEntity *)entity {
    int i = 0;
    NSIndexSet *indexes;
    indexes = [NSIndexSet indexSetWithIndex:i];
    NSLog(@"about to try");
    @try {

    //    [_arrayController removeObjectAtArrangedObjectIndex:0];
        [_seqFile removeObjectAtIndex:0];
        [_songs removeObjectAtIndex:0];

        [_myCollectionView setContent:_songs];
        [_arrayController rearrangeObjects];
        [_myCollectionView setNeedsDisplay:YES];
    //    [_arrayController rearrangeObjects];
    //    [_window makeKeyAndOrderFront:self];
    //    [_myCollectionView setNeedsDisplay:YES];
    //    [self.seqFile reloadData];

    }
    @catch (NSException *exception) {
        NSLog(@"Ugly Ending Caught");

    }
    @finally {
        NSLog(@"Each Time");
        }
  }
我留下了注释代码,以显示我尝试实现相同结果的其他内容。我相信它必须与NSView一起使用,但不确定如何使用

我的线程设置如下:

歌手

@protocol SongPlayerDelegate;
@interface SongPlayer : NSObject <SliderDelegate> {
    id<SongPlayerDelegate> __unsafe_unretained delegate;
}
@property (nonatomic, assign) id<SongPlayerDelegate> delegate;
…
@end
@protocol SongPlayerDelegate <NSObject>
- (void)songPlayer:(SongPlayer *)player removeEntity:(id)enity;
@end
appController.h

#import "SongPlayer.h"
@interface AppController : NSObject <SongPlayerDelegate>
@property (weak) IBOutlet NSCollectionView *myCollectionView;
@property IBOutlet NSArrayController *arrayController;
@property (strong) NSMutableArray *songs;

@property SongPlayer *myPlayer;

- (void)songPlayer:(SongPlayer *)player removeEntity:(id)enity;
在-previewSong:method中,您可以执行以下操作:

        [_myPlayer performSelectorInBackground:@selector(playMyQueue:)
            withObject:activeQueue];
所以,-playMyQueue:在后台线程上运行。然后它会:

[self.delegate songPlayer:self removeEntity:entity];
由于您没有做任何事情将此工作分流到另一个线程,因此它与-playMyQueue:的其余部分发生在同一个后台线程上。类似地,在-songPlayer:removeEntity:中完成的数组控制器的操作在后台线程上完成,并且由于GUI绑定到该数组控制器,这是从后台线程更新GUI,这将无法可靠地工作

您可以通过执行以下操作来解决此问题:

dispatch_async(dispatch_get_main_queue(), ^{
    [self.delegate songPlayer:self removeEntity:entity];
});
除了从后台线程更新GUI的问题外,还有一般线程安全的问题。必须同步多个线程对共享数据结构的访问。例如,如果任何线程可能变异可变数组的内容,那么它必须在变异期间以独占方式访问该数组。甚至连其他线程都无法读取数组,因为它们可能在修改时处于不确定状态。让多个线程同时从一个数组中读取数据是安全的,只要它们中没有一个会改变数组


这适用于数组控制器的内容数组和_seq文件数组。

您不得尝试从后台线程更新GUI,包括修改绑定到GUI的任何模型或控制器属性。所有这些修改都必须在主线程上完成。感谢您的回复。这就是我使用代理的原因。removeEntity方法位于主线程的AppController中。当后台程序通知歌曲已完成时,它将执行。代理不会解决任何线程问题。AppController不属于主线程。对象不存在于特定线程上。如果您有在后台线程上运行的代码,并且它在调用方法时没有使用特定于线程的API,例如-performSelectorOnMainThread:。。。或者GCD和dispatch_get_main_queue一起在主线程上具体执行,然后该方法调用也在后台线程上发生。Ken,对不起,这个术语,我对Objective C Cocoa不太熟悉。我正在执行performSelectorOnMainThread。。。代码设置如下:您使用的是-performSelector InBackground:,而不是OnMainThread。这和我说的正好相反。您可以在后台运行一些工作,只要它不与GUI交互就可以了。如果需要更新GUI,那么您需要将其分流到主线程;我不知道的事情有多可怕。我更改了slider和collection视图的命令,两个视图都在进行初始测试。我已经开始在Apple.com上阅读OSX上的线程,以便更好地掌握。再次感谢你的帮助。
[self.delegate songPlayer:self removeEntity:entity];
dispatch_async(dispatch_get_main_queue(), ^{
    [self.delegate songPlayer:self removeEntity:entity];
});