ios - signal function with SIGPIPE and SIG_IGN - ios

I have joined in a old project and I found this line
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
signal(SIGPIPE, SIG_IGN);
....
}
I have found in docs this:
/*
* For historical reasons; programs expect signal's return value to be
* defined by <sys/signal.h>.
*/
But I'm still confused as to what the purpose of that line is.

From Apple's documentation:
When a connection closes, by default, your process receives a SIGPIPE signal. If your program does not handle or ignore this signal, your program will quit immediately.
Ignore the signal globally with the following line of code:
signal(SIGPIPE, SIG_IGN);

Related

How to understand Objective-C AppDelegate method application:didFInishLauchingWithOptions?

I am new in iOS development, I saw the function
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
As I know, to declare a function is
-/+(return type)function_name: (param type)param
So what is the function name of the function mentioned above?
Here name of the function is application but its mostly called application didFinishLaunchingWithOptions. Its called first when the app is launched.

isRegisteredForRemoteNotifications locking UI with semaphore_wait_trap

There's a strange situation happening in my iOS application when it receive push notification. The UI stay locked and nothing works. When I pause the debugger I see semaphore_wait_trap in my thread.
Debbuging the code I can see it is related to two things:
the value type in push notification (because when I change Number to String the problem disappear);
the isRegisteredForRemoteNotifications method (because when I remove it the problem disappear);
I'm receiving a push notification as follow
{aps:
{alert: { loc-args: [Fiat, Bravo, 501],
loc-key: SOME_TEXT
},
badge: 0,
sound: default.aiff
}
}
I made a new and simple project in Xcode to prove what I'm saying. I'm using the previous bundle identifier to receive the same push.
Follow the code in AppDelegate that shows the problem:
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(#"My token is: %#", deviceToken);
}
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
// [DefaultMethods saveInUserDefaults:#(1) forKey:kUserWasAskedForNotificationKey];
NSLog(#"Failed to get token, error: %#", error);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
if( [[UIApplication sharedApplication] isRegisteredForRemoteNotifications] ){
NSLog(#"Success");
}
}
#end
Thank you for any help!
I was dealing with this problem too and have found this error in my device's logs:
com.apple.usernotifications.usernotificationservice: Exception caught
during decoding of received message, dropping incoming message.
Exception: Exception while decoding argument 0 (#2 of invocation):
Exception: value for key 'NS.objects' was of unexpected class
'NSNumber'. Allowed classes are '{(
NSString,
NSArray )}'.
After calling isRegisteredForRemoteNotifications the application has stopped.
We have fixed this issue on our server and problem went off. Good luck.
I was having the same stall issue.
It turns out that I was also getting a push notification parsing error on the console (like the one mentioned above by #CFIFOK).
"NSXPCConnection: ---" connection to service named com.apple.usernotifications.usernotificationservice:
Exception caught during decoding of received message, dropping incoming message.
Exception: Exception while decoding argument 0 (#2 of invocation):
Exception: value for key 'NS.objects' was of unexpected class 'NSNumber'.
Allowed classes are '{(
NSString,
NSArray
)}'.
This was due to the "title-loc-args" : [3333] not accepting 3333 literally but accepting it as a string "title-loc-args" : ["3333"]. This little thing made my entire interface stall after I accessed the mentioned method isRegisteredForRemoteNotifications.
One thing to take into account is that this stall only happens on iOS 11. It works perfectly fine on iOS 12.0 (16A5366a).
In order to debug the error I used Pusher app (https://github.com/noodlewerk/NWPusher) and traced down the argument that was giving me the parsing error.
Hope this helps!

iOS saving data if app crash

I have got requirement in one of my projects where user is asking to save data locally in case of sudden app crashes. Its form based app so user fill lots of data in form and if app crashes suddenly then user lost all data entered.
App is using Core Data to save data locally.
There is a point where we save entered data in core data but not during every second user fills data.
Also if app crashes core data also vanishes.
In fact, if your app crash, the callback :
- (void)applicationWillTerminate:(UIApplication *)application
will not be called. This one is only called if for some reasons the system need to shutdown your app (usually because resources are rare or because your background job is still doing work after the maximum time allowed) or if you are on < iOs 4. You don't have any way to know when your app will crash (but when you relaunch the app, you can know if it had crashed).
So for your particular case you have two solutions :
Use either a NSTimer with a quick firing rate, or call a fonction each time you edit a field and update the core-data context then save it on disk.
NSError *error = nil;
[managedObjectContext save:&error]
Did you set a persistentStoreCoordinator on your context ? If no, core-data will never persist your data on disk.
Crashes don't appear out of nowhere, find the place(s) where crashes might happen and fix it or if you can't, use a try-catch to keep your app running (but please, try not to do that...).
Hope this help
You can implement a HandleException to catch all exceptions that crash your application.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//for uncaughted exceptions
NSSetUncaughtExceptionHandler(&HandleException);
struct sigaction signalAction;
memset(&signalAction, 0, sizeof(signalAction));
signalAction.sa_handler = &HandleSignal;
sigaction(SIGABRT, &signalAction, NULL);
sigaction(SIGILL, &signalAction, NULL);
sigaction(SIGBUS, &signalAction, NULL);
//and more if you need to handle more signals
//another setup ...
return YES
}
#pragma mark crash management
void HandleException(NSException *exception) {
NSLog(#"[FALTAL] App crashing with exception: %#", exception);
//try to save your DB here.
}
void HandleSignal(int signal) {
//try to save your DB here.
}
#pragma -
However, I don't know about how many time you will have before application exits. But I suppose that you will have enough time to do the DB-backup task.
In particular case you can should use, try catch block, (but not) everywhere.
try {
//write your code
}catch(NSException *e){
//See what's the error
}finally{
//Save your context
}
This it the best solution in my thinking. However you can create a NSTimer which executes a method at some reasonable seconds where you can hold and save your context.
You can also save your context in AppDelegate's method like (if you're targeting iOS 4.0 and above and if your app was exit by iOS it self for some reason),
- (void)applicationWillTerminate:(UIApplication *)application{};
below method will always call when your app goes in background,
- (void)applicationDidEnterBackground:(UIApplication *)application{};
Use
(void)applicationWillTerminate:(UIApplication *)application
delegate method of AppDelgate to save your data in core data.

Starting point of ios application

if write something in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"Starting point 1");
}
main.m
int main(int argc,char * argv[])
{
......
NSLog(#"Starting point 0");
}
Which one is more useful main.m or appDelegate.m one and in which scenerio.
This is an interesting article that explains the app launch sequence.
http://oleb.net/blog/2011/06/app-launch-sequence-ios/
As a resume of the article the conclusion is:
Besides application:didFinishLaunchingWithOptions:, there are several more entry points for custom code during the launch sequence (none of which are usually needed):
Directly in main() before UIApplicationMain() is called.
The init method of a custom UIApplication subclass.
The initWithCoder: or awakeFromNib methods of our application delegate if it is created from a NIB file (the default).
The +initialize methods of our application delegate class or a custom UIApplication subclass. Any class receives an +initialize message before it is sent its first message from within the program.
Note that this sequence only happens at the actual launch of an app. If the app is already running and simply brought back from the background, none of this occurs.
You should use your UIApplicationDelegate, not the main.m.
The didFinishedLaunching method is a good (but not the only) starting point.
Only there your are sure all the iOS specific code is loaded correctly.
In the main the load could have had an error, the line would be executed in the main but not in the didFinishedLaunching method.
The main() method is the very first thing that is called in terms of iOS applications however it is a general rule never to touch the main() function in iOS programming.
The
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions
occurs after a successful launch of the app and should be used for any processes you need to do at the start of the application.

Do I initialize the viewController when I receive UIApplicationLaunchOptionsLocationKey in app didFinishLaunchingWithOptions?

I'm creating an app which listens to significant location change events and in case the app gets terminated then the iOS launches the app with UIApplicationLaunchOptionsLocationKey set.
So, the documentation says to create a new location manager and register for location updates again. However, doesn't mention if I'm supposed to initialize my viewController (as I do in normal app launch as well)? My view controllers initialize in viewDidLoad but are created in appDidFinishLaunchingWithOptions.
Any idea how much time does OS provides to the App for location update handling? My app needs to make a webservice request if the location change indicates an interested location for the app.
Thanks
You should consider moving your initialization code to a new method, something like initializeViews. This method would check to make sure the views haven't been initialized and then initialize them. You would call this method from application:didFinishLaunchingWithOptions: and applicationWillEnterForeground:, but the call in application:didFinishLaunchingWithOptions: would only occur if the application wasn't going to the background.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
if([UIApplication sharedApplication].applicationState != UIApplicationStateBackground)
[self initializeViews];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[self initializeViews];
}
- (void)initializeViews {
if(!viewsAreInitialized) {
...
viewsAreInitialized = YES;
}
}

Resources