MPMediaLibraryDidChangeNotification called twice? - iphone

My app uses the iPodMusicPlayer and, when suspended, the user might go out and make changes in Apple's Music App, for example creating or modifying a Playlist, then return to my App.
I receive the expected MPMediaLibraryDidChangeNotification, which is fine and I deal with it updating my references etc., but I receive a second MPMediaLibraryDidChangeNotification about 2 minutes later which I really don't need.
Any ideas on avoiding this second notification?
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(notification_iPodLibraryDidChange:) name: MPMediaLibraryDidChangeNotification object:nil];
[[MPMediaLibrary defaultMediaLibrary] beginGeneratingLibraryChangeNotifications];

The notification can be called multiple times depending on what's going on. For example, if you add an album to your phone with 12 songs in it, the notification gets called 12 times. Basically it gets called every time the library changes and not just when the sync has finished (at least on iOS 5.1, not sure about older iOS versions).

Where are you adding he observer? For example, if you add in the viewWillAppear and only remove observers in dealloc, you may have multiple observers which is causing a problem. At least, when I encountered a problem like this it was because I had inadvertently added a second observer without removing all the previous.
2 minutes seems like a long lag time (mine was a few seconds), but still may be worth checking out.

Probably the best way to avoid multiple launches of update procedures after multiple notifications is to set a timer and wait some seconds before performing the actual update.

if( !self.lastModifiedDate ) self.lastModifiedDate = [[NSDate alloc] init];
if( [self.lastModifiedDate compare:[[MPMediaLibrary defaultMediaLibrary] lastModifiedDate]] == NSOrderedSame ) return;
self.lastModifiedDate = [[MPMediaLibrary defaultMediaLibrary] lastModifiedDate];
The above lines in my notification handler method deal with the extra call. Still no idea why I'm getting it.

Remove the beginGeneratingLibraryChangeNotifications command, and it will fix it. :) You just get every notification for changed, one from the notification center, and one from the default library.

Related

IOS Background task with specific time interval

I wanted to call a service with some interval like 24 hour. So if my app is in background also at that time also it should call for that service. I am supporting location updates, so my app will run in background. But i want to know how can i execute some task with time interval without informing user.
Thanks
The best thing I can think of would be to integrate with Parse. There you can set up cloud code that runs in the background at a specific time. You can also schedule push notifications as needed. Otherwise, this is a fairly difficult situation.
You can use NSThread methods to call your service in background after some time interval.
You can follow this link1 or link2 for understanding of thread management.
Hope this will help..
You can use this code in your app delegate didfinishlaunching method
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationDidTimeout:) name:kApplicationDidTimeoutNotification object:nil];
and set timer according to that to perform your task at a particular time

Notify app when iPad date time settings changed

I would like to get notified when ipad's date-time settings is changed. Is there any way for that?.
I am using NSDateFormatter to find whether iPad/iphone time mode is 12 or 24 hr format. NSDateFormatter is seems to take lots of time( seen in time profiling). So I would like to check use it only when settings is changed.
You can do it using two ways:
Implement - (void)applicationSignificantTimeChange:(UIApplication *)application in your app delegate.
Add a observer for UIApplicationSignificantTimeChangeNotification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(timeChanged:) name:UIApplicationSignificantTimeChangeNotification object:nil];
applicationSignificantTimeChange:
Tells the delegate when there is a significant change in the time.
- (void)applicationSignificantTimeChange:(UIApplication *)application
Parameters
application
The delegating application object.
Discussion
Examples of significant time changes include the arrival of midnight,
an update of the time by a carrier, and the change to daylight savings
time. The delegate can implement this method to adjust any object of
the application that displays time or is sensitive to time changes.
Prior to calling this method, the application also posts a
UIApplicationSignificantTimeChangeNotification notification to give
interested objects a chance to respond to the change.
If your application is currently suspended, this message is queued
until your application returns to the foreground, at which point it is
delivered. If multiple time changes occur, only the most recent one is
delivered. Availability
Available in iOS 2.0 and later.
Declared In UIApplication.h
For more check UIApplicationDelegate_Protocol
How about adding an observer for NSCurrentLocaleDidChangeNotification ? Per Apple, "Re-create any cached date and number formatter objects whenever the current locale information changes."
You may also want to listen to this notification:
NSSystemTimeZoneDidChangeNotification

UIApplicationDidBecomeActiveNotification is called any time?

I use UIApplicationDidBecomeActiveNotification/UIApplicationWillResignActiveNotification pair to compute app running time. in callback of UIApplicationDidBecomeActiveNotification, I record the startTime, and in callback of UIApplicationWillResignActiveNotification, I record endTime.
in most case, I find the running time is correct. but there are some special case in server's log, I find the running time is strange. like the end time is less than start time, or the end time is much more than the start time. so I suspect the UIApplicationDidBecomeActiveNotification is not called in some times. if some one meet such kind of case, and give me some suggestion.
If you are listening for UIApplicationDidBecomeActiveNotification in a view controller, then viewDidLoad is not called until after UIApplicationDidBecomeActiveNotification is posted. So if you register for the notification in viewDidLoad, you'll miss the first notification, which happened before the view gets loaded. So every time your application launches, you'll miss one such notification. All subsequent notifications will be caught though, including returning from background etc.
UIApplicationDidBecomeActiveNotification will be called everytime your application is coming from background to forgnound.means everytime your application is becoming active from a nonactive state.I think that is the reason for the changing time.

viewWillAppear and UIApplicationDidBecomeActiveNotification

I am using the UIApplicationDidBecomeActiveNotification to refresh my tableview when the app becomes active. My problem is that in my ViewWillAppear, I am also calling a method to refresh this table's data.
This is causing the table to be refreshed twice upon application launch. How can I get one of them not to fire when the app is initially launched? Refreshing the table has some intensive processing of network and local data.. so I would really like o only perform this action once.
Thanks.
You need to use UIApplicationWillEnterForegroundNotification instead of UIApplicationDidBecomeActiveNotification.
The latter is posted every time your app becomes active (initial launch, back to app after call/sms interruption, etc.). But the former is posted only in case of wake up from background. Note that in this case viewWillAppear is not called (as it should seems to be at the first sight).
One way to do it would be with a flag, that you can set up in didFinishLaunching, since that is only executed once per launch.

iPhone 4: when to save data?

I have an app (a game) which saves data: game state, high scores, achievements, etc. Currently the app delegate does this on applicationWillTerminate:. After playing around with iPhone 4 for a bit, it seems that applications pretty much never terminate: they just run in the background forever, unless the user goes out of their way to quit them, or restart the phone.
So my question is, should I find another place to save my data, and if so, when?
To minimize the amount of time spent in the delegate method call, you should find a place that makes sense to save during the game (level completion, checkpoints, etc). You can also add a new delegate method to your application delegate which will be called when your application transitions to the background where you can duplicate some of the things you may have done previously in applicationWillTerminate:. The new delegate method to implement is -applicationDidEnterBackground:.
You will also receive a notification that the user switched back to your app as applicationWillEnterForeground:.
you can do so in the views diddisappear delegate method
-(void)viewDidDisappear:(BOOL)animated
{
//CODE FOR SAVING
}
There are 2 App delegate methods you can use
applicationDidResignActive: //pausing the app, used when a msg comes up. if multitasking this wont help
applicationDidEnterBackground: // called in iOS 4 for when the app is in the background
you can see when it loads into the foreground using
applicationWillEnterForeground:
check out the reference for more info
You should save in applicationDidEnterBackground. Make sure to wrap your saving code with – beginBackgroundTaskWithExpirationHandler: and endBackgroundTask, since without that, you have less than a second (or something like that) before execution suspends.