Во-первых, заранее спасибо за ваше время, глядя на этот вопрос.
Я пытаюсь создать очень простой пример UIViewController, где я загружаю данные в поток. Поток вызывается, но из этого потока я не могу вернуться к основному потоку.
Тестовый пример, приведенный ниже, предельно прост: я создал приложение на основе View в XCode и просто добавил код NSOperationQueue. Надеюсь, кто-то может быстро обнаружить мою ошибку школьника:)
Делегат очень прост, .h это:
#import<UIKit/UIKit.h>
@class ViewbasedViewController;
@interface ViewbasedAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
ViewbasedViewController *viewController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet ViewbasedViewController *viewController;
@end
И .m одинаково прост:
#import "ViewbasedAppDelegate.h"
#import "ViewbasedViewController.h"
@implementation ViewbasedAppDelegate
@synthesize window;
@synthesize viewController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Set the view controller as the window's root view controller and display.
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
Теперь к вопросу. Я хочу запустить поток, когда представление загружено.
Я определил NSOperationQueue в моем файле viewcontroller.h:
@interface ViewbasedViewController : UIViewController {
NSOperationQueue *folderQueue;
}
И в моем view controller.m я хочу запустить некоторый код в потоке после загрузки представления. Поэтому внутри viewDidLoad я добавляю в очередь операцию:
- (void)viewDidLoad {
[super viewDidLoad];
// create a thread and run it
folderQueue = [[NSOperationQueue alloc] init];
folderQueue.maxConcurrentOperationCount = 1;
NSLog(@"about to run thread");
[folderQueue addOperation:[[[NSInvocationOperation alloc]
initWithTarget:self selector:@selector(MyThreadedCode)
object:nil] autorelease]];
}
Функция "MyThreadedCode" вызывается нормально, я вижу отладку в консоли.
-(void)MyThreadedCode
{
NSLog(@"Start of thread");
[self performSelectorOnMainThread:@selector(reloadMyData) withObject:nil WaitUntilDone:YES];
// [self reloadMyData];
NSLog(@"CALLED REFRESH");
}
-(void)reloadMyData
{
NSLog(@"Request to reloadData");
}
НО ... если из моего потока я пытаюсь вызвать селектор в основном потоке (например, я могу захотеть перезагрузить данные в виде таблицы), я получаю исключение. Я получаю это, только если я запускаю его с помощью performanceSelectorOnMainThread.
Если я бегу
[self reloadMyData];
Консоль выглядит хорошо:
[Session started at 2011-09-06 13:56:50 +0100.]
2011-09-06 13:56:52.258 Viewbased[1618:207] about to run thread
2011-09-06 13:56:52.266 Viewbased[1618:5d03] Start of thread
2011-09-06 13:56:52.270 Viewbased[1618:5d03] Request to reloadData
2011-09-06 13:56:52.272 Viewbased[1618:5d03] CALLED REFRESH
Если я использую
[self performSelectorOnMainThread:@selector(reloadMyData) withObject:nil WaitUntilDone:YES];
Я получаю нераспознанный селектор:
[Session started at 2011-09-06 13:29:14 +0100.]
2011-09-06 13:29:26.216 Viewbased[1581:207] about to run thread
2011-09-06 13:29:26.224 Viewbased[1581:5d03] Start of thread
2011-09-06 13:29:26.228 Viewbased[1581:5d03] -[ViewbasedViewController performSelectorOnMainThread:withObject:WaitUntilDone:]: unrecognized selector sent to instance 0x4e43060
2011-09-06 13:29:26.235 Viewbased[1581:5d03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ViewbasedViewController performSelectorOnMainThread:withObject:WaitUntilDone:]: unrecognized selector sent to instance 0x4e43060'
*** Call stack at first throw:
(
0 CoreFoundation 0x00eab5a9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x00cda313 objc_exception_throw + 44
2 CoreFoundation 0x00ead0bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x00e1c966 ___forwarding___ + 966
4 CoreFoundation 0x00e1c522 _CF_forwarding_prep_0 + 50
5 Viewbased 0x000024c3 -[ViewbasedViewController MyThreadedCode] + 78
6 CoreFoundation 0x00e1bc7d __invoking___ + 29
7 CoreFoundation 0x00e1bb51 -[NSInvocation invoke] + 145
8 Foundation 0x000d9495 -[NSInvocationOperation main] + 51
9 Foundation 0x00047b76 -[__NSOperationInternal start] + 747
10 Foundation 0x000477ca ____startOperations_block_invoke_2 + 106
11 libdispatch_sim.dylib 0x01628289 _dispatch_call_block_and_release + 16
12 libdispatch_sim.dylib 0x0162b58a _dispatch_worker_thread2 + 252
13 libSystem.B.dylib 0x9557e781 _pthread_wqthread + 390
14 libSystem.B.dylib 0x9557e5c6 start_wqthread + 30
)
terminate called after throwing an instance of 'NSException'
Я уверен, что это что-то глупое, я ошибся, но не вижу, как я смотрю !!