iPhone: unrecognized selector error - iphone

I'm threeaing some tasks like this :
RootViewController
- (void)viewDidLoad {
[NSThread detachNewThreadSelector:#selector(findSomething) toTarget:self withObject:nil];
}
- (void) findSomething {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
doMoreThings
[pool release];
}
- (void) doMoreThings {
doMoreMoreMoreThings on different objects
}
- (void) foundSomething:(NSFoundThing*)foundObj {
do your stuff
}
oneObject
- (void) doMoreMoreMoreThings {
do things
[self performSelectorOnMainThread:#selector(foundSomething:) withObject:thingFound waitUntilDone:NO];
}
gives
-[KMLParser foundSomething:]: unrecognized selector sent to instance 0x5888080
What is the problem ?

The threading is irrelevant. Some of the code you're not showing us is making it so you are sending the foundSomething: selector to an object that doesn't handle that message. Route the message to an object that does handle it, and your problem will go away.
See also "Unrecognized selector sent to instance".

Related

Thread 1 signal sigabrt error

When I launch my app the build succeeds, but when almost right in the beginning it crashes and highlights the following:
return UIApplicationMain(argc, argv, nil, NSStringFromClass([yes_or_no_AppDelegate class]));
and says:
Thread 1: signal SIGABRT
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([yes_or_no_AppDelegate class]));
}
}
Error message in console:
[GADObjectPrivate changeState:]: unrecognized selector sent to instance
I found out that this is the part that is causing the error. If I delete it I'm able to launch the app.
[self.bannerView setRootViewController:self];
But when i launch the app i don't receive a banner and receive error message in console:
Must set the rootViewController property of GADBannerView before calling loadRequest:
This is my .h file and the code I've used is from googles demo app on banners:
#class GADBannerView, GADRequest;
#interface MainViewController : UIViewController <GADBannerViewDelegate> {
GADBannerView *adBanner_;
}
#property(nonatomic, strong) GADBannerView *adBanner;
and my .m file also from google demo app:
#synthesize adBanner = adBanner_;
#pragma mark init/dealloc
// Implement viewDidLoad to do additional setup after loading the view,
// typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
// Initialize the banner at the bottom of the screen.
CGPoint origin = CGPointMake(0.0,
self.view.frame.size.height -
CGSizeFromGADAdSize(kGADAdSizeBanner).height);
// Use predefined GADAdSize constants to define the GADBannerView.
self.adBanner = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner
origin:origin]
;
// Note: Edit SampleConstants.h to provide a definition for kSampleAdUnitID
// before compiling.
self.adBanner.adUnitID = kSampleAdUnitID;
self.adBanner.delegate = self;
[self.bannerView setRootViewController:self];
[self.view addSubview:self.adBanner];
self.adBanner.center =
CGPointMake(self.view.center.x, self.adBanner.center.y);
[self.adBanner loadRequest:[self createRequest]];
}
- (void)dealloc {
adBanner_.delegate = nil;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
#pragma mark GADRequest generation
// Here we're creating a simple GADRequest and whitelisting the application
// for test ads. You should request test ads during development to avoid
// generating invalid impressions and clicks.
- (GADRequest *)createRequest {
GADRequest *request = [GADRequest request];
// Make the request for a test ad. Put in an identifier for the simulator as
// well as any devices you want to receive test ads.
request.testDevices =
[NSArray arrayWithObjects:
// TODO: Add your device/simulator test identifiers here. They are
// printed to the console when the app is launched.
nil];
return request;
}
#pragma mark GADBannerViewDelegate impl
// We've received an ad successfully.
- (void)adViewDidReceiveAd:(GADBannerView *)adView {
NSLog(#"Received ad successfully");
}
- (void)adView:(GADBannerView *)view
didFailToReceiveAdWithError:(GADRequestError *)error {
NSLog(#"Failed to receive ad with error: %#", [error localizedFailureReason]);
}
Here's your problem:
[GADObjectPrivate changeState:]: unrecognized selector sent to instance
Did you type the method name correctly? This means the method you are calling does not exist. More specifically the GADObjectPrivate class does not contain this method.
The crash when calling changeState: has been asked before. See this question:
AdMob crashes with [GADObjectPrivate changeState:]: unrecognized selector

Memory crash updating UIActivityIndicatorView

Whenever I am trying to update the UIActivityIndicatorView from a thread, the app is getting crashed by throwing an exception
modifying layer that is being finalized - 0x7e177fd0
-[CALayer removeAnimationForKey:]: message sent to deallocated instance 0x7e177fd0
When I try tracking the memory leaks form the mallocDebugger tool, this crash is not happening at all the time happening 1 out of 10
please help me out from this memory issue
Thread implementation:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
[autoRechargeCell addSubview:activityIndicator];
[self.activityIndicator startAnimating];
if( [PennyTalkAPI getBalanceInfoForAccount:appDelegate.accountNumber withPIN:appDelegate.pinNumber])
{
[autoRechargeCell.switchField setOn:[[NSUserDefaults standardUserDefaults] boolForKey:#"AutoRecharge"]];
[self.activityIndicator stopAnimating]; <<<<<<<<<<<<<<<<<<<<<<
}
else
{
[self.activityIndicator stopAnimating];
}
[pool release];
This is the code I have written.
See this.
add [[NSNotificationCenter defaultCenter] removeObserver:self]; to UIActivityIndicatorView+AFNetworking.m dealloc
https://github.com/AFNetworking/AFNetworking/issues/2748
You are updating it from secondary thread that why it is crashing call this on main thread like
[self.activityIndicator performSelectorOnMainThread:#selector(stopAnimating) withObject:nil waitUntilDone:NO];
I think it may help you ....

Why is My Application Crashing When I Call a Method in self.parentViewController?

In my code I'm doing the following:
-(void)pushCropImageViewControllerWithDictionary:(NSDictionary *)dictionary {
civc = [[CropImageViewController alloc] init];
[self presentModalViewController:civc animated:YES];
civc.myImage.image = [dictionary objectForKey:UIImagePickerControllerOriginalImage];
}
So I have a modal view in my app. When this modal view dismisses, I want to call a method from the parent view (the view that called pushCropImageViewControllerWithDictionary), like this:
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillAppear:animated];
[(AddNewItemViewController *)self.parentViewController addCroppedPicture:screenshot];
}
But it keeps crashing with the following message:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITabBarController addCroppedPicture:]: unrecognized selector sent to instance 0x4d15930'
Can someone tell me what am I doing wrong? I am including the header for AddNewItemViewController so the selector should be recognized. Can someone give me a hand on how can I do this properly? Thanks.
EDIT: Declaration of addCroppedPicture:
-(void)addCroppedPicture:(UIImage *)image;
The implementation itself is empty so far.
Apparently, self.parentViewController isn't an instance of AddNewItemViewController but the tab bar controller. Hence the crash.
The proper solution is to make a delegate:
-(void)pushCropImageViewControllerWithDictionary:(NSDictionary *)dictionary
{
civc = [[CropImageViewController alloc] init];
civc.delegate = self;
[self presentModalViewController:civc animated:YES];
...
}
To send a message back to the delegate:
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.delegate addCroppedPicture:screenshot];
}
It's up to you do declare the delegate protocol:
#protocol CropImageDelegate <NSObject>
- (void)addCroppedPicture:(UIImage*)image;
#end
And add a property for the delegate to CropImageViewController:
#property (nonatomic, assign) id<CropImageDelegate> delegate;
And finally, make your view controller conform to this delegate protocol.

How to set up an autorelease pool when using [NSThread detachNewThreadSelector:toTarget:withObject:]

Hi I'm usuing [NSThread detachNewThreadSelector:toTarget:withObject:] and I'm getting a lot of memory leaks because I have no autorelease pool set up for the detached thread. I'm just wondering where I actualy do this? Is it before I call
[NSThread detachNewThreadSelector:toTarget:withObject:]
or in the method that is being ran in the other thread?
Any help would be appreciated, some sample code would be great.
Thanks.
in the method you call with the thread... i.e. given this...
[NSThread detachNewThreadSelector:#selector(doStuff) toTarget:self withObject:nil];
Your method would be...
- (void)doStuff {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//Do stuff
[pool release];
}
You have to set up an autorelease pool in the method you call and that will be executed in the new detached thread.
For example:
// Create a new thread, to execute the method myMethod
[NSThread detachNewThreadSelector:#selector(myMethod) toTarget:self withObject:nil];
and
- (void) myMethod {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Here, add your own code
// ...
[pool drain];
}
Note that we use drain and not release on the autoreleasepool. On iOS, it has no difference. On Mac OS X, if your app is garbage collected, it will triggers garbage collection. This allows you to write code that you can re-use more easily.
Create the new thread:
[NSThread detachNewThreadSelector:#selector(myMethod) toTarget:self withObject:nil];
Create the method that is called by the new thread.
- (void)myMethod
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Your Code
[pool release];
}
What if you need to do something to the main thread from inside your new thread (for example, show a loading symbol)? Use performSelectorOnMainThread.
[self performSelectorOnMainThread:#selector(myMethod) withObject:nil waitUntilDone:false];
Refer :- iPhone SDK Examples
Do it in the method you call. Essentially, you should set up the method that gets called as a self-contained work unit (in fact, it will then be compatible with being called through either [NSOperation][1] or Grand Central Dispatch, too: both better ways of organising concurrent work).
But what if I can't change the implementation of the method I'm calling on a new thread?
In that case, you would go from doing this:
[NSThread detachNewThreadSelector: #selector(blah:) toTarget: obj withObject: arg]
to doing this:
[NSThread detachNewThreadSelector: #selector(invokeBlah:) toTarget: self withObject: dict]
- (void)invokeBlah: (id)dict {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id obj = [dict objectForKey: #"target"];
id arg = [dict objectForKey: #"argument"];
[obj blah: arg];
[pool release];
}
rather than using the dictionary, you could also create an NSInvocation that encapsulates the remote object call. I just chose a dictionary because it's the quickest way to show the situation in a SO answer. Either would work.
The documentation states that the method run in the thread must create and destroy its own autorelease pool. So if your code has
[NSThread detachNewThreadSelector:#selector(doThings) toTarget:self withObject:nil];
The method should be
- (void)doThings {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//Do your things here
[pool release];
}

Warning: UIKit should not be called from a secondary thread

In my iPhone app I need to connect to a web server as this can take some time I'm using threads like this:
[NSThread detachNewThreadSelector:#selector(sendStuff) toTarget:self withObject:nil];
- (void)sendStuff {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//Need to get the string from the textField to send to server
NSString *myString = self.textField.text;
//Do some stuff here, connect to web server etc..
[pool release];
}
On the row where I use self.textField I get a warning in console saying:
void _WebThreadLockFromAnyThread(bool), 0x5d306b0: Obtaining the web lock from a thread other than the main thread or the web thread. UIKit should not be called from a secondary thread.
How can I use the textField without getting this error?
It depends a little bit on what you want to do with the textField. If reading the value is the only thing, you can do:
[NSThread detachNewThreadSelector:#selector(sendStuff) toTarget:self withObject:self.textField.text];
- (void)sendStuff:(NSString*)myString {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//Do someting with myString
[pool release];
}
If you want to change a value on the textField you could:
[self.textField performSelectorOnMainThread:#selector(setText:) withObject:#"new Text"];
Perform any selectors that handle UI updates on the main thread. You can do this with the NSObject method -performSelectorOnMainThread:withObject:waitUntilDone:
Why not:
[NSThread detachNewThreadSelector: #selector(sendStuff:) toTarget: self withObject: self.textField.text];
?
This is indeed unsafe behaviour. The MainThread is the only one that should interface the UI. Have your thread return for instance a string to the mainthread and have a method there update the UI. You can do for instance do this by passing a selector to the other thread method, and then have the other thread call the selector on the mainthread.
[self performSelectorOnMainThread:#selector(myMethod) withObject:nil waitUntilDone:NO];
will work