Okay this is strange. I have a multi threaded app, thread calls back some method in the main view. I step through with the debugger, the lines are run, but nothing happens. Here is the flow:
I have AViewController, it invokes Wrapper class W with callbackTarget (AViewController self) and UpdateScreen Selector parameters. Class W opens the UIImagePickerController, grabs the image, and pass into an Image Processing (IP) class, passing along callbackTarget and Selector. IP class then spawns a thread to process the image. When this is done, the thread calls callbackTarget.Selector, which is to update the view with the results in AViewController.
I have a break point in UpdateScreen. All the lines are executed, but nothing happens on the screen. I am suspecting some variables are not visible across threads, but I don't know how to make it work. Help please?
EDIT adding sample code. It's messy that's why I didn't include it to begin with
CODE SNIPPET
// AViewController, this is entry point
-(IBAction) callCardScanner_tapped{
[testResultLabel setText:@"ocr started"]; // this is shown
CardScaner* scanner = [[CardScaner alloc] init] ;
[scanner scanWithCameraSendResultTo:self selector:@selector(updateScreenWithResultFromCardScanner:)];
[scanner release];
}
//this method is used to pass into the thread so it can call back
-(void) updateScreenWithResultFromCardScanner:(OCRResult *)result{
// ... update labels with result
// ...
[resultLabel setText: result.resultString]; // these lines seem to be executed by main thread according to debugger, but the screen remain blank
}
CardScanner wrapper class
-(void) scanWithCameraSendResultTo:(NSObject*) target selector :(SEL) selector{
// ...
UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
[rootViewController presentModalViewController:imagePicker animated:true];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
// ...
ImageProcessor* recognizer = [[ImageProcessoralloc] init];
[recognizer ocrImageInThread:img callbackTarget:callbackTarget selector:self.callbackMethod];
[imagePicker release];
}
Image Processor class
- (void) ocrImageInThread:(UIImage*) photo callbackTarget:(NSObject*) target selector:(SEL) selector{
NSArray* args = [NSArray arrayWithObjects:photo, target, NSStringFromSelector(selector), nil];
NSThread* ocrThread 开发者_运维百科= [[[NSThread alloc] initWithTarget:self selector: @selector(ocrImageThread_start:) object:args] autorelease];
[ocrThread start];
}
-(void) ocrImageThread_start:(NSArray*) args{
//.. do image processing to acquire result object, here in the end invoke the callback method
[callbackTarget performSelectorOnMainThread:NSSelectorFromString(selector) withObject:resultObject waitUntilDone:NO];
[resultObject release];
[pool release];
}
After your processing is finished, you must update your view on the main thread. Most of UIKit isn't thread safe and is only guaranteed to work if you handle it on the main thread.
You can use performSelectorOnMainThread
or the dispatch_async
functions family to transfer the work back to the main thread.
精彩评论