ios nsnotificationcenter program abort - ios

I have gone down quite a few paths and wondered if someone could spot this right off:
I want to display a button when a text field is selected (hence the keyboard is loaded).
From what i've read NSNotificationCenter is one way to do this:
So in viewWillAppear I placed the following
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidAppear:) name:UIKeyboardWillShowNotification object:self.view.window];
for the destination (selector) i have:
-(void)keyboardDidAppear{
_button2.hidden = FALSE;
}
the program aborts to a crash dump (sure seems like there should be a better debugging path than this)
if I comment out the only line in keyboardDidAppear
// _button2.hidden = FALSE;
the program still aborts
so evidently the NSNotificationCenter is firing and is not tolerated for some reason
Any simplified help would be appreciated.
Seriously, the crash dump is all you get when theres an execution error? Is it all you need?

The problem is simple. You register the method keyboardDidAppear: but you supply a method named keyboardDidAppear. These are not the same (notice the colon).
Change one or the other (but not both).
Another solution would be to implement the UITextFieldDelegate method textFieldDidBeginEditing: and show the button when this is called.

You are trying to send a message to keyboardDidAppear: but you implemented keyboardDidAppear. The first method is a method taking a parameter, but you supplied a method taking no parameters, which of course is different.
Change either your method definition to
-(void)keyboardDidAppear:(NSNotification *)n {
_button2.hidden = NO; //Please stick to Obj-C semantics and use NO, as opposed to FALSE.
}
or the call to
#selector(keyboardDidAppear)

Related

NSNotificationCenter crashes my app

I've added a NSNotificationCenter observer that calls 2 selectors with the same name on two different view controllers.
It works, but when I run the app sometimes it crashes with this error message:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x18)
or
Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
Anyone has an idea why it crashes? Thank you!
.
My code:
fetchFromParse:
-(void)sendAllStores
{
[[NSNotificationCenter defaultCenter]postNotificationName:#"getStoresArrays" object:nil userInfo:self.storesDict];
}
firstVC.m:
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(getStoresArrays:) name:#"getStoresArrays" object:nil];
}
-(void)getStoresArrays:(NSNotification*)notification
{
NSLog(#“Working”);
}
secondVC.m:
-(void)prepareArrays
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(getStoresArrays:) name:#"getStoresArrays" object:nil];
}
-(void)getStoresArrays:(NSNotification*)notification
{
NSLog(#“Working”);
}
AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.secVC=[[secondVC alloc] init];
[self.secVC prepareArrays];
fetchFromParse *fetchFromParseObj=[[fetchFromParse alloc] init];
[fetchFromParseObj getStoresFromParse];
Return YES;
}
Notification Crashes
Typically you might see a crash of this nature if you attempt to close a view controller without removing the observer. So that part of the answer provided by Mr. Patil, is absolutely required. Your use-case will vary about where and how you remove the observer. If you remove it too soon you might end up crashing if you try to reference any related objects.
So you might want to remove the self.storesDict object or at least verify that it is not nil before using it.
Debugging
Here's a quick tutorial on debugging with Xcode. It's for an older version but it should get you up to speed quickly. You can also review Apple docs for more on collecting crash logs.
Logs
You should go to the reports navigator and copy a bit more of your log so that we can determine a more precise cause of the issue. You can add a breakpoint right before the faulty code and then step through the issue. Copy the debug console if nothing else.
Getting the crash log
You can open Xcode go the Window menu select Devices. Select your attached device (iPhone/iPad) and click the View Device Logs button. From the list select your app name/crash date. Copy the data to the question.
More Information
The more information you provide on crashes the more likely we can help you. I suspect that the answer is you are either trying to access something that is nil or not releasing the observer at the right time. It might not be appropriate to release the observer when your view disappears but you have not provided enough information to make that obvious.
How do the different view controllers work together? Are you certain that the Notifications is causing the crash?? Put a breakpoint at the post notification and in each selector and then debug the app until it crashes. You will need to identify the conditions that precede the crash. I'll refine this answer if you let me know when you update the question.
First thing I would do is do a global search and make sure no other classes are listening to that notification. Then I would make sure that in the classes that you have added an observer for that notification you do the following:
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Add this
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//Has to be unregistered always, otherwise nav controllers down the line will call this method
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
hope it helps.
Are you sure that 'addObserver', 'postNotification' and 'removeObserver' are always called on the main thread?
Please doublecheck with:
if ([NSThread isMainThread])

NSNotificationCenter callback while app in background

One question and one issue:
I have the following code:
- (void) registerForLocalCalendarChanges
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(localCalendarStoreChanged) name:EKEventStoreChangedNotification object:store ];
}
- (void) localCalendarStoreChanged
{
// This gets call when an event in store changes
// you have to go through the calendar to look for changes
[self getCalendarEvents];
}
These methods are in a class/object called CalendarEventReporter which contains the method getCalendarEvents (in the callback).
Two things:
1) If the app is in the background the callback does not run. Is there a way to make it do that?
2) When I bring the app back into the foreground (after having changed the calendar on the device) the app crashes without any error message in the debug window or on the device. My guess is that the CalendarEventReporter object that contains the callback is being garbage-collected. Is that possible? Any other thoughts on what might be causing the crash? Or how to see any error messages?
1) In order for the app to run in the background you should be using one of the modes mentioned in the "Background Execution and Multitasking section here:
uses location services
records or plays audio
provides VOIP
services
background refresh
connection to external devices
like through BLE
If you are not using any of the above, it is not possible to get asynchronous events in the background.
2) In order to see the crash logs/call stack place an exception breakpoint or look into the "Device Logs" section here: Window->Organizer->Devices->"Device Name" on left->Device Logs on Xcode.
To answer your first question, take a look at https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
What I did to get code running in the background is to do something like
In the .h file
UIBackgroundTaskIdentifier backgroundUploadTask;
In the .m file
-(void) functionYouWantToRunInTheBackground
{
self.backgroundUploadTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];
}];
//code to do something
}
-(void) endBackgroundUpdateTask
{
[[UIApplication sharedApplication] endBackgroundTask: self.backgroundUploadTask];
self.backgroundUploadTask = UIBackgroundTaskInvalid;
}
The code above I pretty much learned from objective c - Proper use of beginBackgroundTaskWithExpirationHandler
As for your second question, you should set a breakpoint where code is supposed to run when you bring the app back to the foreground. No one can figure out why an app crashes if not given enough code or information.
The solution to the second part of the question was to raise the scope of the object containing the callback code. I raised it to the level of the containing ViewController. This seems to work. I still can't figure out how to raise the Notification (i.e. execute the call back) if the notification comes while the app is in the background/suspended. This prevented the object containing the callback from being cleaned up.

Objective c Thread 1 signal SIGSTOP app crashes

I'm trying to track down an error that appears to be definitely a timing issue. I have an application that uses a Universal Framework. When the process is complete in the framework an NSNotification is sent back to the application. We have recently added a third party framework to our framework. Now, while the methods for the third party framework are being executed, as execution returns to our framework I receive the following error in the Console Output:
Assertion failed: (exclusive), function assert_locked, file ../dep/include/boost/boost_1_55_0/boost/thread/pthread/shared_mutex.hpp, line 51.
But I'm not sure that is the ultimate issue, because our framework continues to execute and the NSNotification is sent back to the application. Right after the Notification is sent and execution returns to the calling method (or the method call) in our framework I see a warning on the executing thread. Then, execution continues back to the original calling method and the warning goes away.
Here's the weird part. If I step through the code very slowly, it might just work. If I'm not slow enough I get the SIGSTOP and the code never returns to the UI. If I'm too fast, I get a SIGABRT.
I've been trying to find the exact issue using Instuments. This answer to a similar question backed up my suspicion that this is a timing issue. I think the boost assert_locked Assertion might have something to do with this.
My code is pretty boring but I know you want to see it, so here it is:
- (void)generateImageTemplates:(UIImage *)src
{
int result = 0;
cv::Mat image = *(cv::Mat*)[self cvMatFromUIImage:src];
user = IEngine_InitUser();
int userID=0;
result = IEngine_AddFingerprintRAW(user, UNKNOWN, image.data, image.size().width, image.size().height);
result = IEngine_RegisterUser(user, &userID);
[[NSNotificationCenter defaultCenter] postNotificationName:#"InnovatricsComplete" object:self];
}
If you're wondering what result is, it's an error code. So far these have all come back equal to 0. Meaning no errors. I'll work on handling these errors once I can get a successful return to the UI without crashing.
Control returns to the method call:
- (void)generateImageTemplates:(UIImage *)processedImage
{
[self.captureCommand generateImageTemplates:processedImage];
}
Control returns to the method call in the application View Controller:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0){
[self clearPressed:self.clearButton];
} else {
[self.cameraVC generateImageTemplates:self.processedImage];
}
}
Finally, the NSNotification callback code:
- (void)onInnovatricsComplete:(NSNotification *)note
{
[self.cameraVC willMoveToParentViewController:nil];
[self.cameraVC.view removeFromSuperview];
[self.cameraVC removeFromParentViewController];
}
I warned you it was pretty boring!
I'm completely stumped! Though I continue to surf the internet for clues, is there anybody out there who can help me resolve this issue?
Thank you.
Here are some screenshots (in reverse order):
look at NSUinteger’s answer in How to know where crash for postNotificationName:object:userInfo
the listener might be deallocated before it recieves the notification.

iOS DidMoveToWindow Infinite Loop

I was looking into iOS NUI Framework source code. I spotted the following line of codes but I couldn't figured out how it worked
- (void)override_didMoveToWindow
{
if (!self.isNUIApplied) {
[self applyNUI];
}
[self override_didMoveToWindow];
}
Just to be clear, they swizzled out the original implementation of DidMoveToWindow with this method in order to apply the class/style at run time. What confused me was that the function above never caused any infinite loop.
This may help: http://darkdust.net/writings/objective-c/method-swizzling
The swizzled method is actually exchanged with the original. So when the original method is called the swizzled method has already exchanged the implementation. And calling the "swizzled method" override_didMoveToWindow method will call the original function.
Comment the line
//[self override_didMoveToWindow];
works for me
It looks like not a loop because it appears the author assumes that [self applyNUI] always changes the state so that self.isNUIApplied becomes == YES

When to use a colon with a #selector

Just getting going with iPhone development and Objective-C.
Yesterday I was trying to addObserver for a notification in a view of mine, and I kept getting this error:
unrecognized selector sent to instance
I tracked it down to the fact that I needed to include the trailing colon to my selector argument:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(nameOfMySelector:) name:#"BBLocationServicesAreDisabled" object:nil];
Today, I thought I was clever because when setting up the action argument to a button, I remembered my mistake yesterday, and added the colon to the action argument. The action argument takes a #selector, just like the selector argument while setting up an observer for an NSNotification, so I figured I was doing the right thing.
However, with the following code:
[self.callToActionButton addTarget:self action:#selector(nameOfMySelector:) forControlEvents:UIControlEventTouchUpInside];
I get the exact same error:
unrecognized selector sent to instance
What gives? Why does one #selector require a trailing colon, and the other doesn't? What are the rules I should follow for when it should be included and when it should be left off, and why I can't I always just do one or the other?
Thanks!
As mentioned by boltClock, the character you are referring to is actually a colon. The difference between #selector(method) and #selector(method:) is the method signature. The 2nd variant expects a parameter to be passed.
#selector(method) would expect the method: -(void)method
#selector(method:) would expect the method: -(void)method:(id)someParameter
You seem to be missing one concept here: colon is, in some way, a part of the method name. E.g., method
-(IBAction) doIt:(id)sender;
has name doIt:. Thus, colon should be used to reference this method.
But this method doesn't have a colon at the end
-(IBAction) doItWithoutParameter;
Same goes for methods accepting multiple arguments, they have names like doItWithParam1:andParam2:
A selector represents a method name, and the number of colons in a selector matches the number of arguments in the corresponding method:
mySelector — no colon, no arguments, e.g. - (void)mySelector;, [self mySelector];
mySelectorWithFoo: — one colon, a single argument, e.g. - (void)mySelectorWithFoo:(Foo *)foo;, [self mySelectorWithFoo:someFoo];
mySelectorWithFoo:withBar: — two colons, two arguments, e.g. - (void)mySelectorWithFoo:(Foo *)foo bar:(Bar *)bar;, [self mySelectorWithFoo:someFoo bar:someBar];
and so forth.
It is also possible to have a selector without ‘naming’ the parameters. It’s not recommended since it’s not immediately clear what the parameters are:
mySelector:: — two colons, two arguments, e.g. - (void)mySelector:(Foo *)foo :(Bar *)bar;, [self mySelector:someFoo :someBar];
mySelector::: — three colons, three arguments, e.g. - (void)mySelector:(int)x :(int)y :(int)z;, [self mySelector:2 :3 :5];
The colon indicates that the method takes a parameter.
[someObject performSelector:#selector(doSomething:)] means that doSomething is expecting a parameter.
[someObject performSelector:#selector(doSomething)] means that doSomething doesn't need any parameters.
In your case:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(nameOfMySelector:) name:#"BBLocationServicesAreDisabled" object:nil];
- (void) nameOfMySelector: (NSNotification *) notification {
/* this method would require the semi-colon */
}
or in this case:
[self.callToActionButton addTarget:self action:#selector(nameOfMySelector:) forControlEvents:UIControlEventTouchUpInside];
- (void) nameOfMySelector: (id) sender {
/* this method would also require the semi-colon */
}
I think the problem is the missing parameter.
See this post: Objective-C: Calling selectors with multiple arguments (Great answers!)

Resources