2010-09-29 72 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];