Changing music files auto next giving error and crashes the application? - objective-c

I have set the songs array to play one by one.And I call a method
described below.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerPlaybackStateChanged:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:player];
-(void) moviePlayerPlaybackStateChanged:(NSNotification*) sender
{
NSLog(#"in state changed = %d and isPause = %d", player.playbackState, isPause);
if (player.playbackState == MPMoviePlaybackStatePlaying) {
[activityIndicator stopAnimating];
}
if (player.playbackState == MPMoviePlaybackStateInterrupted) {
isPause =YES;
}
}
playing 5 or 6 songs the app get crashed and last log values are as follows:
2012-04-18 15:54:45.026 SymphonyProject[2896:207] in state changed = 1 and isPause = 0
2012-04-18 15:54:45.027 SymphonyProject[2896:207] in state changed = 2 and isPause = 0
[Switching to process 2896 thread 0x603b]
[Switching to process 2896 thread 0x603b]
sharedlibrary apply-load-rules all
and go to the file objc_mesgSend and pointing the line:
0x0164a09b <+0015> mov 0x8(%edx),%edi
I m not getting the error whatever it is? Please help me.

One question, you access player object in moviePlayerPlaybackStateChanged direct - is it class property? Because you send the object with this notification, so you should get the player object by retrieving it from sender.userInfo dictionary.

Related

iOS App UI freeze when coming from background

I'm facing a strange issue and I have no clue why this is happening.My app works fine when it is active, but the app UI is freezing when it comes from background (by pressing the home button and by locking the device).
NOTE:This behaviour is only observed on devices but not in simulator.
And the console is throwing the messages:
Jul 5 13:28:55 Tejas-iPhone backboardd[7234] <Warning>: BKSendHIDEvent: IOHIDEventSystemConnectionDispatchEvent error:0xE00002E8 -- Unknown event dropped
along with too many logs of :
Jul 5 14:41:40 Tejas-iPhone boostApp[7913] <Error>: CoreLocation: Discarding message for event 0 because of too many unprocessed messages
Jul 5 14:41:42 Tejas-iPhone boostApp[7913] <Error>: CoreLocation: Discarding message for event 12 because of too many unprocessed messages
Jul 5 14:44:56 Tejas-iPhone boostApp[7913] <Error>: CoreLocation: Discarding message for event 1 because of too many unprocessed messages
Jul 5 14:44:56 Tejas-iPhone boostApp[7913] <Error>: CoreLocation: Discarding message for event 27 because of too many unprocessed messages
I found out that CoreLocation will log the above message if the locationManager is not running on main thread.
Here is how I initialise the CLLocationManager:
-(id)init {
if ( self = [super init] ) {
[self runLocationManagerOnMainThread];
}
return self;
}
-(void)runLocationManagerOnMainThread{
if (![NSThread mainThread]) {
[self performSelectorOnMainThread:#selector(runLocationManagerOnMainThread) withObject:nil waitUntilDone:NO];
}
self.locationManager = [[LocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.distanceFilter = 1;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.buildings = [[NSMutableArray alloc] init];
}
+ (id)sharedInstance {
static LocationMonitor *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
Please let me know if I need to mention any specific details.I tried this but it doesn't have any valid answers.
This is wierd . I integrated NSLogger to my project a while ago and I started to see that xcode terminal stopped logging logs and I have to always rely on apple configurator and NSLogger to see my logs.
After I delete the NSLogger from pods and from my project, my app started to work more faster and the UI is not freezing anymore irrespective of how many times the app is opened from background.

Object keeps receiving notification

I have a Book object that listens to a notifications. When I'm trying to remove the book from the view I have this piece of code:
BookItem *book = [books objectAtIndex:bookIndex];
[book removeFromSuperview];
[books removeObject:book];
book = nil;
After I'm done removing books I send a "rearrange" notification and I'm getting an error in the BookItem object, where I'm accessing nulls ...
What could be the problem? how can I stop listening to notifications after I'm removing the object?
You need to stop observing:
[[NSNotificationCenter defaultCenter] removeObserver:book];

Managed Object Context not saving to persistant store

I have a threaded operation that creates a new managed object, saves it to the persistant store, then passes the objectID of the new objected via NSNotification to the main thread for further processing
However, when I try to access the newly created managed object from the main thread all the values that I set on the background thread return as empty.
** background thread
// create a new managed object context for this thread
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:[appDelegate persistentStoreCoordinator]];
[context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
// create the object
MyObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:#"MyObject" inManagedObjectContext:context];
[newManagedObject setAValue:#"A"];
[newManagedObject setBValue:#"B"];
[newManagedObject setCValue:#"C"];
// save it on the main thread
[context performSelectorOnMainThread:#selector(save:) withObject:nil waitUntilDone:NO];
// post notification to main thread, pass the objectID
NSMutableDictionary *userInfo = [NSDictionary dictionaryWithObject:[newManagedObject objectID] forKey:#"objectID"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"doneInsertingObject" object:userInfo];
[context release];
** main thread
...
// register notification for background thread
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(mergeContextChanges:) name:NSManagedObjectContextDidSaveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doSomethingWithObject:) name:#"doneInsertingObject" object:nil];
...
- (void)doSomethingWithObject:(NSNotification*)noif
{
if([NSThread isMainThread] == NO)
{
// run this on the main thread
[self performSelectorOnMainThread:_cmd withObject:noif waitUntilDone:NO];
return;
}
// get managed object from objectID
NSDictionary *userInfo = [noif userInfo];
MyObject *object = (MyObject*)[appDelegate.managedObjectContext objectWithID:[userInfo valueForKey:#"objectID"]];
[appDelegate.managedObjectContext refreshObject:object mergeChanges:YES];
// these should return 'A, B, C' but all three return 'nil'
NSLog(#"aValue: %#", object.aValue);
NSLog(#"bValue: %#", object.bValue);
NSLog(#"cValue: %#", object.cValue);
}
// merge background thread moc with main moc
- (void)mergeContextChanges:(NSNotification *)notification
{
if([NSThread isMainThread] == NO)
{
// run this on the main thread
[self performSelectorOnMainThread:_cmd withObject:notification waitUntilDone:NO];
return;
}
// fault all updated objects
NSSet *updated = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];
for(NSManagedObject *thing in updated)
{
[[appDelegate.managedObjectContext objectWithID:[thing objectID]] willAccessValueForKey:nil];
}
// merge changes to the main managed object context
[appDelegate.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
// force processing of any pending changes
[appDelegate.managedObjectContext processPendingChanges];
}
I've tried changing merge policies and there was no difference.
I've tried adding logging to the context merge method and I have confirmed receiving a "inserted" notification from the background thread before the doSomethingWithObject: method on the main thread is called.
Why is my data not being updated to the persistant store?
I can't see where you save the context for your background thread. If it's this line
// save it on the main thread
[context performSelectorOnMainThread:#selector(save:) withObject:nil waitUntilDone:NO];
I don't know if it is correct. You have save the context from the thread that has created it and not in the main thread.
[context save:&error];
For further info, I suggest you to read the articles by Marcus Zarra importing-and-displaying-large-data-sets-in-core-data. You can find the sample code at the end. In addition you can find further info in using-core-data-on-multiple-threads.
Hope it helps.
Your NSManagedObjectContext has to be saved on the thread it was created on (as #Flex_Addicted pondered).
After it has saved on the background thread, a notification will be posted telling you to merge changes from the background context to the main context.
Apples documents read "Saving in a Background Thread is Error-prone" - this isn't related to using another NSManagedObjectContext. They are saying that if you have 1 context, and you try to dispatch the save operation to the background - THAT is error prone. If you have multiple contexts, they should only be used within one thread at a time.

AppleEvent: how to debug `eventDidFail`?

I am getting this error from SIMBL in the console:
05.09.11 17:00:09,165 SIMBL Agent: eventDidFail:'tvea' error:Error Domain=NSOSStatusErrorDomain Code=-1708 "The operation couldn’t be completed. (OSStatus error -1708.)" (the AppleEvent was not handled by any handler ) UserInfo=0x400e485c0 {ErrorNumber=-1708} userInfo:{
ErrorNumber = "-1708";
}
I am trying to debug this; but as I haven't really worked with AppleEvent that much yet, I'm not really sure how to interpret that.
I think the related code in the SIMBL Agent is this:
AEEventID eventID = 'load';
// Find the process to target
pid_t pid = [[appInfo objectForKey:#"NSApplicationProcessIdentifier"] intValue];
SBApplication* app = [SBApplication applicationWithProcessIdentifier:pid];
[app setDelegate:self];
if (!app) {
SIMBLLogNotice(#"Can't find app with pid %d", pid);
return;
}
// Force AppleScript to initialize in the app, by getting the dictionary
// When initializing, you need to wait for the event reply, otherwise the
// event might get dropped on the floor. This is only seems to happen in 10.5
// but it shouldn't harm anything.
[app setSendMode:kAEWaitReply | kAENeverInteract | kAEDontRecord];
id initReply = [app sendEvent:kASAppleScriptSuite id:kGetAEUT parameters:0];
// the reply here is of some unknown type - it is not an Objective-C object
// as near as I can tell because trying to print it using "%#" or getting its
// class both cause the application to segfault. The pointer value always seems
// to be 0x10000 which is a bit fishy. It does not seem to be an AEDesc struct
// either.
// since we are waiting for a reply, it seems like this object might need to
// be released - but i don't know what it is or how to release it.
// NSLog(#"initReply: %p '%64.64s'", initReply, (char*)initReply);
// Inject!
[app setSendMode:kAENoReply | kAENeverInteract | kAEDontRecord];
id injectReply = [app sendEvent:'SIMe' id:eventID parameters:0];
if (injectReply != nil) {
SIMBLLogNotice(#"unexpected injectReply: %#", injectReply);
}
The eventDidFail message also comes from the SIMBL Agent itself. It is this code:
- (void) eventDidFail:(const AppleEvent*)event withError:(NSError*)error
{
NSDictionary* userInfo = [error userInfo];
NSNumber* errorNumber = [userInfo objectForKey:#"ErrorNumber"];
// this error seems more common on Leopard
if (errorNumber && [errorNumber intValue] == errAEEventNotHandled) {
SIMBLLogDebug(#"eventDidFail:'%4.4s' error:%# userInfo:%#", (char*)&(event->descriptorType), error, [error userInfo]);
}
else {
SIMBLLogNotice(#"eventDidFail:'%4.4s' error:%# userInfo:%#", (char*)&(event->descriptorType), error, [error userInfo]);
}
}
And the error disappears if I comment out this code:
[app setSendMode:kAEWaitReply | kAENeverInteract | kAEDontRecord];
id initReply = [app sendEvent:kASAppleScriptSuite id:kGetAEUT parameters:0];

iphone sdk communicate between thread

My application has a second running thread. I need to achieve the following :
Stop the separate thread gracefully from the main application thread
Call a function on the main thread from the second thread to signal a result has been found and pass it to the main one.
I've found the following for the first task : share a global variable between the 2 threads ?
No idea how to achieve the second task. (NSNotificationCenter doesn't allow to pass objects ...)
I'm lunching the second thread like this [NSThread detachNewThreadSelector:#selector(backGroudTask) toTarget:self withObject:nil];
Thanks
I'm still searching for the best answer to this, but here is what I do:
Use NSLock to create a lock that prevents me from accessing the same variable on both threads. Then use a BOOL to see if the main thread wants to initiate a stop.
in main thread do this
[myLock lock];
exitFlag = YES;
[myLock unlock];
in the other thread do this
endMe = NO;
while(!endMe)
{
// do your task stuff
[myLock lock];
endMe = exitFlag;
[myLock unlock];
}
For the second part of your question use the following:
[self performSelectorOnMainThread:#selector(your_selector_name) withObject:nil waitUntilDone:false];
This will cause the your selector routine to run on the main thread.
Hope this helps
(NSNotificationCenter doesn't allow to pass objects ...)
it does, but you have to add them to the userinfo of the notification
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:myObject forKey:#"object"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"myNotification" object:self userInfo:userInfo];
- (void)foo:(NSNotification *)notification {
id object = [[notification userInfo] objectForKey:#"object"];
}