ios-App crashes unexpectedly when re Enters to the app - ios

When I enter the app it is working fine but when I re-enter the app it will not shown the particular page or starting page of the app but it is again displaying the Launcher image and crashes and after crash again it is working fine.
[NSThread sleepForTimeInterval:1.0];
UILocalNotification *locationNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (locationNotification) {
// Set icon badge number to zero
NSLog(#"Recieved Notification %#",locationNotification);
}
return YES;
please give the solution I am new bee to iOS.

Anupma
From seeing the problem which is described here I suspect some methods or notifications are calling in applicationDidEnterBackground. Please check it and if it is you can find the solution to solve it.
Hope this helps.

-(void)applicationDidEnterBackground:(UIApplication *)application
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[self Backgroundmethods];
dispatch_async(dispatch_get_main_queue(), ^{
//your code to update UI if any goes here
});
});
}
I worte the all my background methods in seperate method and calling that method with in applicationdidEnterbackground in seperate thread.

Related

how to set array of date to fireDate in local notification at a time

Actually in my app I'm starting more than two timers at different times. After certain time intervals I want notifications to fire. It's working fine when the app is on foreground but not in the background. How can I solve this?
Please help. Thanks!
You need to do following...
You need to turn on background mode.
In AppDelegate, Add this code to run app in background
Create a property
#property (nonatomic, assign) UIBackgroundTaskIdentifier backgroundTask;
and then do following...
- (void)applicationDidEnterBackground:(UIApplication *)application {
self.backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
DLOG(#"End of tolerate time. Application should be suspended now if we do not ask more 'tolerance'");
}];
if (self.backgroundTask == UIBackgroundTaskInvalid) {
DLOG(#"This application does not support background mode");
} else {
//if application supports background mode, we'll see this log.
DLOG(#"Application will continue to run in background");
}
}
I hope it will help you.
you can handle with both timer into this appdelgate method
- (void)applicationDidEnterBackground:(UIApplication *)application {
}
when app going to background that time this method is called and your code still execute into this method, Hope this will help you.
Note : first enable background mode into Project Target -> Availability Tab -> Background Modes -> ON

Notifications in Multiple Thread iOS

I have found that when I want to deliver Notifications to particular threads, there is a sample from Apple.
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Notifications/Articles/Threading.html#//apple_ref/doc/uid/20001289-CEGJFDFG
In this article, Apple suggests that using a machport to monitor the thread which we want to process the notification.
- (void)processNotification:(NSNotification *)notification {
if ([NSThread currentThread] != notificationThread) {
// Forward the notification to the correct thread.
[self.notificationLock lock];
[self.notifications addObject:notification];
[self.notificationLock unlock];
[self.notificationPort sendBeforeDate:[NSDate date]
components:nil
from:nil
reserved:0];
}
else {
// Process the notification here;
}
}
My question is: if I get the notification and I use dispatch_async to process the notification, does it has a different appearance?
dispatch_async(dispatch_get_main_queue(), ^{
// Process the notification here;
});
the simple answer is : no difference
I also noticed the apple suggested link is Updated: 2009-08-18. it seems to already outdated. GCD is a more powerful and convenient way to achieve multi-thread work.

UILocalNotification doesn't trigger didReceiveLocalNotification when tapping from Notification Center

I'm using Objective-c to create a UILocalNotification in my iPhone app. I'm targeting iOS 8 and using XCode 6.
My problem relates to handling UILocalNotification when app is not running and it's opened by tapping on a notification. When the user taps the notification and opens the app I use didReceiveLocalNotification in AppDelegate.m to show a particular View Controller and send the VC some data (a date).
This works fine when tapping the notification from the lockscreen. When tapping the notification in the Notification Center didReceiveLocalNotification is never called. I used a UIAlertView to test this on my device. didFinishLaunchingWithOptions is called, but when I include the code to show the particular View Controller in that method it never works (though another UIAlertView showed me it was running that part of the code, just never completing the showViewController method).
Here's my didFinishLaunchingWithOptions code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([UIApplication sharedApplication].scheduledLocalNotifications.count >= 1) {
// Handle local notification received if app wasn't running in background
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if ([[notification.userInfo objectForKey:#"notification"] isEqual:#"mood rating"]) {
// Create reportVC
NSLog(#"launched app and about to show reportvc");
ReportViewController *reportVC = (ReportViewController *)[self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"reportVC"];
// Date stuff goes here - code removed
// show the reportVC
[self.window.rootViewController showViewController:reportVC sender:self];
}
} else {
[self createLocalNotification];
}
return YES;
}
And here is my didReceiveLocalNotification code:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
// Create report view
ReportViewController *reportVC = (ReportViewController *)[self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"reportVC"];
// Same date stuff goes here as in didFinishLaunchingWithOptions
// Show report vc
[self.window.rootViewController showViewController:reportVC sender:self];
}
The date stuff that I've take out is just checking if it's after 9pm or not, and either creating today's date or yesterday's, and then setting the result as a property of the reportVC. Let me know if that's relevant and I'll add it back in.
So here's some stuff I've tried to fix this:
I've tried using presentViewController:animated:completion: instead of showViewController:sender: but I want to use showViewController so I can have the navbar show up, and that didn't fix the problem anyway.
I've tried adding this line to my didFinishLaunchingWithOptions method:
[self application:application didReceiveLocalNotification:notification];
which did kind of fix the problem—when tapping from Notification Center it opened the right view, but it ruined lockscreen notifications. With this line added, when tapping a notification from the lockscreen I got the reportVC presented twice: the first one was a black screen apart from the navbar, and the one on top of that was correct.
I tried replacing my current showViewController line of code with this instead:
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
[topController showViewController:reportVC sender:self];
but that didn't fix the problem either.
I tried taking the code I've doubled up on out of my didFinishLaunchingWithOptions method, because I realised didReceiveLocalNotification seems to be run anyway once didFinishLaunchingWithOptions is done. That does seem to be the case, but it doesn't fix my problem with Notification Center notifications.
And in case this is screwing it up, here's how I'm testing this at the moment:
I add these two lines to the didFinishLaunchingWithOptions method:
[[UIApplication sharedApplication] cancelAllLocalNotifications];
[self createLocalNotification];
I change the scheduled time for the notification to be about 3 minutes into the future. It's normally set to go off at 9pm every night using date components like this:
dateComponents.hour = 21;
dateComponents.minute = 0;
And I change the notification's repeatInterval to be NSCalendarUnitMinute instead of NSCalendarUnitDay which is what it's set to for release builds.
Then I run the app on my device using XCode, and stop it once it's run and scheduled the notification. I run it again without these two lines:
[[UIApplication sharedApplication] cancelAllLocalNotifications];
[self createLocalNotification];
And then stop the app from XCode, open multitasking on my device, swipe the app up to close it, and wait for a notification to arrive. After tapping each test notification I multitask and close the app again so I can test from a totally closed app each time.
You may want to try this (present your view controller asynchronously with the dispatch_async()):
if ([[notification.userInfo objectForKey:#"notification"] isEqual:#"mood rating"]) {
dispatch_async(dispatch_get_main_queue(), ^{
// Create reportVC
NSLog(#"launched app and about to show reportvc");
ReportViewController *reportVC = (ReportViewController *)[self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"reportVC"];
// Date stuff goes here - code removed
// show the reportVC
[self.window.rootViewController showViewController:reportVC sender:self];
});
}
or this (call [self.window makeKeyAndVisible] before presenting your view controller):
if ([[notification.userInfo objectForKey:#"notification"] isEqual:#"mood rating"]) {
// Create reportVC
NSLog(#"launched app and about to show reportvc");
ReportViewController *reportVC = (ReportViewController *)[self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"reportVC"];
// Date stuff goes here - code removed
// show the reportVC
[self.window makeKeyAndVisible];
[self.window.rootViewController showViewController:reportVC sender:self];
}

When retrieving data from the server in dispatch queue, how to handle application going to background?

I am creating an application where I am retrieving data from the server like below:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
[self retrievedatafromserver];
dispatch_async(dispatch_get_main_queue(), ^{
//UIUpdation, fetch the image/data from DB and update into your UI
});
});
How do I retrieve data from the server even if application goes to background?
Thanks & Regards
sumana
If Your scope of project is in only iOS 7 then you can use A new background mode which comes in the iOS 7 and onwards. You can fetch the data in background mode without any extra efforts of coding.
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
Now that your app already knows to initiate background fetch, let’s tell it what to do. The method -(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler will assist in doing so. This method is called every time that a background fetch is performed, and should be included in the AppDelegate.m file. The complete version is provided below:
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
UINavigationController *navigationController = (UINavigationController*)self.window.rootViewController;
id topViewController = navigationController.topViewController;
if ([topViewController isKindOfClass:[ViewController class]]) {
[(ViewController*)topViewController insertNewObjectForFetchWithCompletionHandler:completionHandler];
} else {
NSLog(#"Not the right class %#.", [topViewController class]);
completionHandler(UIBackgroundFetchResultFailed);
}
}
Now in your controller. Do like that
- (void)insertNewObjectForFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSLog(#"Update the tableview.");
self.numberOfnewPosts = [self getRandomNumberBetween:0 to:4];
NSLog(#"%d new fetched objects",self.numberOfnewPosts);
for(int i = 0; i < self.numberOfnewPosts; i++){
int addPost = [self getRandomNumberBetween:0 to:(int)([self.possibleTableData count]-1)];
[self insertObject:[self.possibleTableData objectAtIndex:addPost]];
}
/*
At the end of the fetch, invoke the completion handler.
*/
completionHandler(UIBackgroundFetchResultNewData);
}
Note :- If you have to give supportability on iOS 6 and below then avoid this approach. Because it's not available.
When your app enters background mode. you can access code for couple of seconds. Suppose the background queue is still performing and you entered background. then you might need to recall the method when app entered foreground. (take a bool variable and check whether the process is completed or not, if process is completed no issues. if not call the method again.).
If you want to make app run in background mode also then you need to request for background run mode in plist. See this link for reference only for these features we can active background run mode and you can active any of them according to you usage http://blogs.innovationm.com/support-for-applications-running-in-background-ios/

Dealing with two screens and one activity indicator in iOS

I have 3 screens on my app.First is login. Second is search and third is process the task.
On login i retrieve data from a web service. It returns data in XML format. So the data is considerably large. So i am doing that task on a background thread like this to stop Mainthread freezing up on me:
-(BOOL)loginEmp
{
.....some computation
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
(unsigned long)NULL), ^(void) {
[self getAllCustomerValues];
});
}
-(void)getAllCustomerValues
{
....more computation.Bring the data,parse it and save it to CoreData DB.
//notification - EDIT
NSNotification *notification =[NSNotification notificationWithName:#"reloadRequest"
object:self];
[[NSNotificationCenter defaultCenter] postNotification : notification];
}
//EDIT
//SearchScreenVC.m
- (void)viewDidLoad
{
....some computation
[self.customerActIndicator startAnimating];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(stopActivityIndicator)
name:#"reloadRequest"
object:nil];
}
- (void)stopActivityIndicator
{
[self.customerActIndicator stopAnimating];
self.customerActIndicator.hidesWhenStopped = YES;
self.customerActIndicator.hidden =YES;
NSLog(#"HIt this at 127");
}
So on condition that login was successful, i move to screen 2. But the background thread is still in process( i know because i have logs logging values) . I want an activity indicator showing up here (2nd screen)telling user to wait before he starts searching. So how do i do it?How can i make my activity indicator listen/wait for background thread. Please let me know if you need more info.Thanks
EDIT: so I edited accordingly but the notification never gets called. I put a notification at the end of getAllCustomerValues and in viewDidLoad of SearchScreen i used it. That notification on 2nd screen to stop animating never gets called. What is the mistake i am doing.?Thanks
EDIT 2: So it finally hits the method. I dont know what made it to hit that method. I put a break point. I wrote to stop animating but it wouldn't. I wrote hidesWhenStoppped and hidden both to YES. But it still keeps animating.How do i get it to stop?
Ok, if it is not the main thread, put the following in and that should fix it.
- (void)stopActivityIndicator
{
if(![NSThread isMainThread]){
[self performSelectorOnMainThread:#selector(stopActivityIndicator) withObject:nil waitUntilDone:NO];
return;
}
[self.customerActIndicator stopAnimating];
self.customerActIndicator.hidesWhenStopped = YES;
self.customerActIndicator.hidden =YES;
NSLog(#"HIt this at 127");
}
Could you put your background operation into a separate class and then set a delegate on it so you can alert the delegate once the operation has completed?
I havent tried this, its just an idea :)
You could use a delegate pointing to your view controller & a method in your view controller like:
- (void) updateProgress:(NSNumber*)percentageComplete {
}
And then in the background thread:
float percentComplete = 0.5; // for example
NSNumber *percentComplete = [NSNumber numberWithFloat:percentComplete];
[delegate performSelectorOnMainThread:#selector(updateProgress:) withObject:percentageComplete waitUntilDone:NO];

Resources