2

Firstly thanks in advance for your time looking at this question.

I'm trying to create a very simple UIViewController example, where I load the data in a thread. The thread is getting called but from that thread, I can't get back to the main thread. The test case below is extremely simple, I create a View based application in XCode and just added the NSOperationQueue code. Hopefully someone can quickly spot my schoolboy error :)

The delegate is very simple, .h is:

#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

And the .m is equally simple:

#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;
}

Now to the question. I want to run a thread when the view is loaded. I've defined an NSOperationQueue in my viewcontroller.h file:

@interface ViewbasedViewController : UIViewController {
NSOperationQueue *folderQueue;
}

And in my view controller.m, I want to run some code in a thread once the view is loaded. So inside viewDidLoad I add an operation to a queue:

- (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]];

}

The function "MyThreadedCode" gets called ok, I can see the debug in the console.

-(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");
}

BUT...if, from my thread, I try and call a selector on the main thread (for instance I may want to reload data in a tableview), I get an exception. I only get this if I run it using performanceSelectorOnMainThread. If I run

[self reloadMyData];

The console looks good:

[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

If I use

[self performSelectorOnMainThread:@selector(reloadMyData) withObject:nil WaitUntilDone:YES];

I get an unrecognized selector:

[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'

I'm sure its something stupid I've got wrong but I can't see it for looking!!

一二三
  • 21,059
  • 11
  • 65
  • 74
user930731
  • 145
  • 1
  • 3
  • 5

2 Answers2

9

Capitalization is important.

[self performSelectorOnMainThread:@selector(reloadMyData)
                       withObject:nil
                    WaitUntilDone:YES];

WaitUntilDone: should be waitUntilDone: :

[self performSelectorOnMainThread:@selector(reloadMyData)
                       withObject:nil
                    waitUntilDone:YES];
NSGod
  • 22,699
  • 3
  • 58
  • 66
-1

Try below line with @selector:

[self performSelectorOnMainThread:@selector(reloadMyData:) withObject:nil WaitUntilDone:YES];
Mat
  • 202,337
  • 40
  • 393
  • 406
Nikunj Jadav
  • 3,417
  • 7
  • 38
  • 54
  • NSGod answer looks to be the correct one. Also reloadMyData doesnt take any data. – Praveen S Sep 06 '11 at 14:00
  • That being said, if you *do* have withObject set to send data, and forget that colon, you will get the same "unrecognized selector" error. While it didn't help the asker, it did help me. – Digital_Utopia Sep 11 '13 at 08:08