2010-09-29 39 views
1

我有一些麻烦传递一个NSNumber对象到不同的线程。 我在viewDidload上调用了一个从核心数据中加载一些对象作为后台进程的函数。它调用另一个函数,通过加载的对象进行循环,以查看是否有任何与其相关的图像被下载。如果它不存在,请异步下载图像并将其保存在本地。事情是我需要在主线程上执行startDownloadFor:atIndex:。但是应用程序因传递的NSNumber对象而崩溃。这里是代码..Iphone:传递对象和多线程

- (void)viewDidLoad { 
    ... 
    ... 
    [self performSelectorInBackground:@selector(loadImages) withObject:nil]; 
} 

-(void)loadImages{ 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
... 
     ... 
[self fillInImages]; 
[pool release]; 
} 

-(void)fillInImages{ 

NSString *imageURL; 
for (int i=0; i < [dataManager.objectList count]; i++) { 
    ... 
    if ([dataManager.RelatedImages Image] == nil) { 
    //[self startDownloadFor:imageURL atIndex:[NSNumber numberWithInt:i]; // << WORKS FINE 
    [self performSelectorOnMainThread:@selector(startDownloadFor:atIndex:) withObject:(imageURL, [NSNumber numberWithInt:i]) waitUntilDone:YES]; // << CRASHES 
    ... 
    }else { 
    ... 
    } 
    ... 
} 
... 
} 

-(void)startDownloadFor:(NSString*)imageUrl atIndex:(int)indexPath{ 

NSString *indexKey = [NSString stringWithFormat:@"key%d",indexPath]; 
... 
} 

这样做的正确方法是什么?

感谢

回答

1

我从来没有见过这种语法传递多个对象的选择 - 是有效的Objective-C代码?另外,在你的startDownloadFor:atIndex:你正在传递一个NSNumber,但是在那个选择器上的第二个参数的类型是(int) - 这是不好的;)

performSelectorOnMainThread的文档:选择器应该只带有一个id类型的参数。你传递了一个无效的选择器,所以我认为它对NSNumber的位置感到非常困惑。

为了解决这个问题,通过一个NSDictionary conatining数量和图像URL即

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:imageURL, @"imageURL", [NSNumber numberWithInt:i], @"number", nil]; 
[self performSelectorOnMainThread:@selector(startDownload:) withObject:dict waitUntilDone:YES]; 

//-(void)startDownloadFor:(NSString*)imageUrl atIndex:(int)indexPath{ 
- (void)startdownload:(NSDictionary *)dict { 
    NSURL *imageURL = [dict objectForKey:@"imageURL"]; 
    int indexPath = [[dict objectforKey:@"number"] intValue]; 
1

您正在尝试2个参数传递到performSelectorOnMainThread:withObject:waitUntilDone:,而该方法仅支持通过一个论据。

你需要使用NSInvocation来发送更多的参数(或者使用像dean推荐的NSDictionary)。

SEL theSelector; 
NSMethodSignature *aSignature; 
NSInvocation *anInvocation; 

theSelector = @selector(startDownloadFor:atIndex:); 
aSignature = [self instanceMethodSignatureForSelector:theSelector]; 
anInvocation = [NSInvocation invocationWithMethodSignature:aSignature]; 
[anInvocation setSelector:theSelector]; 
[anInvocation setTarget:self]; 
// indexes for arguments start at 2, 0 = self, 1 = _cmd 
[anInvocation setArgument:&imageUrl atIndex:2]; 
[anInvocation setArgument:&i atIndex:3]; 

[anInvocation performSelectorOnMainThread:@selector(invoke) withObject:NULL waitUntilDone:YES];