gpt4 book ai didi

iphone - 为什么我的completionBlock永远不会在NSOperation中被调用?

转载 作者:行者123 更新时间:2023-12-03 18:28:25 25 4
gpt4 key购买 nike

我已经继承了 NSOperation 并设置了完成 block ,但即使操作完成,它似乎也永远不会进入。这是我的代码:

目录 Controller 类设置 NSOperation:

- (void)setupOperation {
...

ImportWordOperation *importWordOperation = [[ImportWordOperation alloc] initWithCatalog:words];
[importWordOperation setMainObjectContext:[app managedObjectContext]];
[importWordOperation setCompletionBlock:^{
[(ViewController *)[[app window] rootViewController] fetchResults];
}];
[[NSOperationQueue mainQueue] addOperation:importWordOperation];
[importWordOperation release];
...
}

如您所见,我正在设置完成 block 以在其他 Controller 的主线程上执行方法。

然后,在 main 我的子类 NSOperation 类:ImportWordOperation.m 中,我启动了后台操作。我什至覆盖了 isFinished iVar 以便触发完成方法:

- (void)setFinished:(BOOL)_finished {
finished = _finished;
}

- (BOOL)isFinished {
return (self.isCancelled ? YES: finished);
}

- (void)addWords:(NSDictionary *)userInfo {
NSError *error = nil;

AppDelegate *app = [AppDelegate sharedInstance];

NSManagedObjectContext *localMOC = [userInfo valueForKey:@"localMOC"];
NSEntityDescription *ent = [NSEntityDescription entityForName:@"Word" inManagedObjectContext:localMOC];
for (NSDictionary *dictWord in [userInfo objectForKey:@"words"]) {
Word *wordN = [[Word alloc] initWithEntity:ent insertIntoManagedObjectContext:localMOC];

[wordN setValuesForKeysWithDictionary:dictWord];
[wordN release];
}

if (![[userInfo valueForKey:@"localMOC"] save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
[localMOC reset];

[self setFinished:YES];
}


- (void)main {

finished = NO;

NSManagedObjectContext *localMOC = nil;
NSUInteger type = NSConfinementConcurrencyType;
localMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:type];
[localMOC setUndoManager:nil];
[localMOC setParentContext:[self mainObjectContext]];

if (![self isCancelled]) {
if ([self.words count] > 0) {
[self performSelectorInBackground:@selector(addWords:) withObject:@{@"words":self.words, @"localMOC":localMOC}];
}
}
}

如果我删除 isFinished 访问器方法,则会在 ImportWordOperation 完成之前调用完成 block 。

我读过代码,发现它使用自己的完成 block ,但是 NSOperation 子类中的完成 block 有什么用呢?

任何想法或指向类似解决情况的点将不胜感激。

最佳答案

你有点陷入了并发和非并发之间的奇怪空间 NSOperation这里的子类。通常,当您实现main时,您的操作是非并发的,并且 isFinished更改为YES尽快main退出。

但是,您已经提供了自己的 isFinished 实现,并将其编码为 isFinished不返回YES直到main之后已退出。这使得您的操作在很多方面开始像并发操作一样 - 至少包括需要手动发出 KVO 通知。

解决您的问题的快速方法是实现 setFinished:使用(will|did)ChangeValueForKey:来电。 (我还更改了 ivar 名称以反射(reflect)流行的命名约定)。以下是 NSOperation我相信它可以准确地模拟您的操作的运作,以并发方式完成。

@implementation TestOperation {
BOOL _isFinished;
}

- (void)setFinished:(BOOL)isFinished
{
[self willChangeValueForKey:@"isFinished"];
// Instance variable has the underscore prefix rather than the local
_isFinished = isFinished;
[self didChangeValueForKey:@"isFinished"];
}

- (BOOL)isFinished
{
return ([self isCancelled] ? YES : _isFinished);
}

- (void)main
{
NSLog(@"%@ is in main.",self);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
[self setFinished:YES];
});
}

@end

我不熟悉您的要求,所以也许您有迫切的需求,但您的操作似乎更适合使用 start 的并发操作。而不是main 。我已经实现了一个看起来工作正常的小示例。

@implementation TestOperation {
BOOL _isFinished;
BOOL _isExecuting;
}

- (void)setFinished:(BOOL)isFinished
{
if (isFinished != _isFinished) {
[self willChangeValueForKey:@"isFinished"];
// Instance variable has the underscore prefix rather than the local
_isFinished = isFinished;
[self didChangeValueForKey:@"isFinished"];
}
}

- (BOOL)isFinished
{
return _isFinished || [self isCancelled];
}

- (void)cancel
{
[super cancel];
if ([self isExecuting]) {
[self setExecuting:NO];
[self setFinished:YES];
}
}

- (void)setExecuting:(BOOL)isExecuting {
if (isExecuting != _isExecuting) {
[self willChangeValueForKey:@"isExecuting"];
_isExecuting = isExecuting;
[self didChangeValueForKey:@"isExecuting"];
}
}

- (BOOL)isExecuting
{
return _isExecuting;
}

- (void)start
{
NSLog(@"%@ is in start. isCancelled = %@", self, [self isCancelled] ? @"YES" : @"NO");
if (![self isCancelled]) {
[self setFinished:NO];
[self setExecuting:YES];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ {
sleep(1);
[self setExecuting:NO];
[self setFinished:YES];
});
}
}
@end

关于iphone - 为什么我的completionBlock永远不会在NSOperation中被调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15629696/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com