Refresh values when application enters foreground - iphone

My application is using 'ALAssetsGroup' to keep track of the users albums
and i display these albums in my application
the user can click on the albums and see the images as well.
Now the problem arises when the user downloads images through safari or he alters the albums in any way .
my application still holds reference to the old albums instead of the new one
so i tried to refresh the albums using the
- (void)applicationWillEnterForeground:(UIApplication *)application
but the albums still seem to have the old value,
if i refresh them once more 'within' the application they get the correct values.
is there something else i can use to resolve this issue .. ?
maybe a notification .. ?

//This Registers a Notification for any changes
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didChangeLibrary:)
name:ALAssetsLibraryChangedNotification
object:[AGImagePickerController defaultAssetsLibrary]];
- (void)didChangeLibrary:(NSNotification *)notification
{
//Enter some code here to deal with the album changing
}
Edit: It seems like this does not work on iOS 5 (A radar has been opened for Apple, because this is a bug).
Here is a work around to use in the meantime:
Call
[self.assetsLibrary writeImageToSavedPhotosAlbum:nil metadata:nil
completionBlock:^(NSURL *assetURL, NSError *error) { }];
immediately after creating instance of ALAssetsLibrary Observe
ALAssetsLibraryChangedNotification (not
NSManagedObjectContextObjectsDidChangeNotification)

Use the applicationDidBecomeActive method in the ApplicationDelegate
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}

Related

Prevent NSDocument-based app from reopening documents after a crash

I have a read-only music player app for macOS that uses NSDocument to get all the file-handling logic for free.
The problem that I now have is that every time the app crashes (or is stopped by the debugger) while one or more player windows are open, they automatically get reopened when the app is restarted. I don't want that, since it interferes with debugging and legitimate crashes don't really happen with this app.
Apple's NSDocument documentation contains nothing regarding the reopening of files, so I'm out of luck there. Is there a proper way to do this?
First create a subclass of NSDocumentController and make sure you create an instance of it in - (void)applicationWillFinishLaunching:(NSNotification *)notification so it becomes the sharedDocumentController. (see this question)
Then in you subclass override the restore method:
+ (void)restoreWindowWithIdentifier:(NSString *)identifier state:(NSCoder *)state completionHandler:(void (^)(NSWindow *, NSError *))completionHandler
{
if (_preventDocumentRestoration) { // you need to decide when this var is true
completionHandler(nil, [NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]);
}
else {
[super restoreWindowWithIdentifier:identifier state:state completionHandler:completionHandler];
}
}

How to know if a task is executing in background

In my app I'm downloading lots of images on a method.
I'm using a
downloadTask = [[UIApplication sharedApplication]
beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:downloadTask];
downloadTask = UIBackgroundTaskInvalid;
}];
This is working fine, if I press the home or sleep button, the images continue downloading.
I'm showing the progress in a UIProgressView inside an UIAlertView, and when the percent is 100% the alertView is dissmised and I change the viewController to other where I show the donwloaded images.
But I only want this to happen if the app is really active at the moment the download finish.
I have been looking at the app state and while it's downloading with the screen off.
[UIApplication sharedApplication].applicationState
the state is UIApplicationStateActive during all the donwload
How can I can know if the downloading is happening with the screen off or on?
EDITED AFTER ACCEPTING THE ANSWER:
I just discovered, if I tap the home button, the app enters in UIApplicationStateBackground, if I tap the wake/sleep it enters in UIApplicationStateInactive
Following the approach of the correct answer, my app contines donwloading in both cases.
The screen is off in two states (apart from when the app has not been even opened):
suspended : in this case you don't have to worry because the download won't procede until the app gets active again; It will enter this state on
background : it's in this state for a limited amount of time before going in suspend, and the screen is already off in this moment. Here you may want to check then whether to do all the things you said or not, because in this state code can be still executed. In this state the app status is UIApplicationStateBackground, so you could just perform a check like this:
You probably want to check whether the app is in background execution in order to achieve the result. Just like this:
if([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground) {
// Do stuff
}
If it's in background, so the screen is off.
UPDATE: after few test, what I figured out is that the behaviour you are expieriencing is probably due to the execution of the download on the main thread.
You should send the download on (for instance) the global queue. This way the application will enter the background state as expected:
....
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:self.bti];
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self doBackgroundStuff];
});
....
This way, if the app is put on background while the download is in progress, the application state will turn into UIApplicationStateBackground, and then you can check it as I wrote initially. If you are doing UI updates during the progress remember to send them back to the main thread (because the download is now on a different one).
You can check whether your app is running in the background or not by setting a flag in the designated application delegate methodsapplicationDidEnterBackground: and applicationWillEnterForeground:. Example:
- (void)applicationDidEnterBackground:(UIApplication *)application
_applicationRunsInForeground = NO;
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
_applicationRunsInForeground = YES;
}
If you don't want to have this _applicationRunsInForeground flag inside your application delegate, you could observe the delegate's NSNotifications in your viewcontroller class instead (UIApplicationWillEnterForegroundNotification and UIApplicationDidEnterBackgroundNotification).

iPhone iOS do apps running in backgrounds generate and process notifications?

My app is downloading JSON objects in when the app enters background mode. The app converts them to core data entities. The issue that I'm running in is that I need to merge the managed object contexts for these core data entities with the main managed object context.
The way to merge these changes is through notifications:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(contextHasChanged:) name:NSManagedObjectContextDidSaveNotification object:nil];
- (void)contextHasChanged:(NSNotification*)notification
{
NSLog(#"received notification with object: %#",[[notification object] description]);
if ([notification object] == [AppUser managedObjectContext]) return;
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:#selector(contextHasChanged:) withObject:notification waitUntilDone:YES];
return;
}
[[AppUser managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
}
For some reason my code does not receive these notifications while running in background. Does the app continue to generate notifications while it is running in background mode? Or is it something with the location of where/when I register for such notifications that's wrong?
Thank you for the clarification!
app continues to send notifications either in main or background. you need to take care of
the observer should not be released during add observer and posting notification. i thnk there may some mistak in implementaion read this
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectContext_Class/NSManagedObjectContext.html
Once you press the Home button, your app goes into suspended mode. It won't process the above notifications until you "wake" it up by tapping on its icon.
To ensure that your app continues to do its task, you need to request background task completion. The OS will then give you up to 600 seconds (10 minutes) to complete whatever task your app is doing before suspending it.
You can read more about it here: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW3
Specifically, look for "Background Execution and Multitasking" in the above link.
There are limitations to what type of notifications you can receive while in the background. Also the sending of notifications is something you schedule before entering the background.
If you need to continue doing work when the app enters thebackground you should call beginBackgroundTaskWithExpirationHandler as well.
Main documentation is here:
http://developer.apple.com/library/ios/ipad/#DOCUMENTATION/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
Scroll down to the section in Background Execution and Multitasking

iOS 5 banner push notification disappear, user tap on app icon to start the app

With iOS 5, push notifications can appear as banner and disappear after a few seconds.
I understand that didReceiveRemoteNotification will be called when user taps on the banner.
My question is, if the banner has disappeared and my user sees that there is a badge number on the app, they will tap on the app icon to start the app. Now if the app is running in the background, how do I check that the app is brought to foreground and there has been a notification, and do the necessary?
The purpose of my notification is basically to inform user there has been an update to the app content and encourage them to run the app to get the latest contents. My app only checks for latest contents at launch time and doesn't check for updates periodically.
This question is a bit old, but I'll pop what I've found in here anyway.
There are two methods you need to implement in your app delegate to check if your app was either launched from the remote notification (From when the app is not running on your device), or received the remote notification while running (in the background or foreground).
First is a method that is already in your App Delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
To check if this was launched from a remote notification, have some code similar to this:
// Check to see if launched from notification
if (launchOptions != nil)
{
NSDictionary* dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary != nil)
{
NSLog(#"Launched from push notification: %#", dictionary);
// DO SOMETHING HERE
}
}
The other method you will need to implement is specifically for the case that your application for when your application is running:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(#"Received notification: %#", userInfo);
}
How you handle the notification from there is up to you, but that's how your app knows about it!
In this second method, you can check the UIApplicationState of the passed application to find out if you were in the foreground or background.

Is there a way to get notified when the user drags a file into iTunes File Sharing and Sync is complete?

When I plug in the iPhone to iTunes and drag a file into the File Sharing section of my app, the app on the screen goes away for a moment and then comes back. It seems that none of the app delegate methods are triggered at this time, not even something like "went to background, went to foreground".
As soon as my app comes back after a sync where the user added or removed files, I want to update the screen.
Maybe there is a notification beeing sent?
Also, <MediaPlayer/MediaPlayer.h> framework's [MPMediaLibary defaultMediaLibrary] can post notification MPMediaLibraryDidChangeNotification, which is fired especially when your media library is updated while your device is syncing with iTunes.
You can let your object to observe this notification by adding:
#import <MediaPlayer/MediaPlayer.h>
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(<#selector#>:) name:MPMediaLibraryDidChangeNotification object:[MPMediaLibrary defaultMediaLibrary]];
Also make sure to activate this notification by using - (void)beginGeneratingLibraryChangeNotifications
- (void)applicationWillResignActive:(UIApplication *)application is called when the sync starts and - (void)applicationDidBecomeActive:(UIApplication *)application after the sync is complete
applicationWillResignActive does not work starting with iOS 5.0.
You can use the DirectoryWatcher class in the DocInteraction sample app.