Broken Multithreading With Core Data - cocoa

This is a better-focused version of an earlier question that touches upon an entirely different subject from before.
I am working on a Cocoa Core Data application with multiple threads. There is a Song and Artist; every Song has an Artist relation. There is a delegate code file not cited here; it more or less looks like the template XCode generates.
I am far better working with the former technology than the latter, and any multithreading capability came from a Core Data template. When I'm doing all my ManagedObjectContext work in one method, I am fine. When I put fetch-or-insert-then-return-object work into a separate method, the application halts (but does not crash) at the new method's return statement, seen below. The new method even gets its own MOC to be safe, and it has not helped any. The result is one addition to Song and a halt after generating an Artist.
I get no errors or exceptions, and I don't know why. I've debugged out the wazoo. My theory is that any errors occurring are in another thread, and the one I'm watching is waiting on something forever.
What did I do wrong with getArtistObject: , and how can I fix it? Thanks.
- (void)main
{
NSInteger songCount = 1;
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
[moc setPersistentStoreCoordinator:[[self delegate] persistentStoreCoordinator]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:moc];
/* songDict generated here */
for (id key in songDict)
{
NSManagedObject *song = [NSEntityDescription insertNewObjectForEntityForName:#"Song" inManagedObjectContext:moc];
[song setValue:[songDictItem objectForKey:#"Name"] forKey:#"title"];
[song setValue:[self getArtistObject:(NSString *) [songDictItem objectForKey:#"Artist"]] forKey:#"artist"];
[songDictItem release];
songCount++;
}
NSError *error;
if (![moc save:&error])
[NSApp presentError:error];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:moc];
[moc release], moc = nil;
[[self delegate] importDone];
}
- (NSManagedObject*) getArtistObject:(NSString*)theArtist
{
NSError *error = nil;
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
[moc setPersistentStoreCoordinator:[[self delegate] persistentStoreCoordinator]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:moc];
NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Artist" inManagedObjectContext:moc];
[fetch setEntity:entityDescription];
// object to be returned
NSManagedObject *artistObject = [[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc];
// set predicate (artist name)
NSPredicate *pred = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"name = \"%#\"", theArtist]];
[fetch setPredicate:pred];
NSArray *response = [moc executeFetchRequest:fetch error:&error];
if (error)
[NSApp presentError:error];
if ([response count] == 0) // empty resultset --> no artists with this name
{
[artistObject setValue:theArtist forKey:#"name"];
NSLog(#"%# not found. Adding.", theArtist);
return artistObject;
}
else
return [response objectAtIndex:0];
}
#end

Try locking the managed object context before you access it and unlocking it again after you are done with it:
- (void)main
{
NSInteger songCount = 1;
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
[moc lock];
[moc setPersistentStoreCoordinator:[[self delegate] persistentStoreCoordinator]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:moc];
[moc unlock];
/* songDict generated here */
for (id key in songDict)
{
[moc lock];
NSManagedObject *song = [NSEntityDescription insertNewObjectForEntityForName:#"Song" inManagedObjectContext:moc];
[moc unlock];
[song setValue:[songDictItem objectForKey:#"Name"] forKey:#"title"];
[song setValue:[self getArtistObject:(NSString *) [songDictItem objectForKey:#"Artist"]] forKey:#"artist"];
[songDictItem release];
songCount++;
}
NSError *error;
[moc lock];
if (![moc save:&error])
[NSApp presentError:error];
[moc unlock];
[moc lock];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:moc];
[moc unlock];
[moc release], moc = nil;
[[self delegate] importDone];
}
- (NSManagedObject*) getArtistObject:(NSString*)theArtist
{
NSError *error = nil;
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
[moc lock];
[moc setPersistentStoreCoordinator:[[self delegate] persistentStoreCoordinator]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:moc];
[moc unlock];
NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease];
[moc lock];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Artist" inManagedObjectContext:moc];
[moc unlock];
[fetch setEntity:entityDescription];
// object to be returned
[moc lock];
NSManagedObject *artistObject = [[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc];
[moc unlock];
// set predicate (artist name)
NSPredicate *pred = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"name = \"%#\"", theArtist]];
[fetch setPredicate:pred];
[moc lock];
NSArray *response = [moc executeFetchRequest:fetch error:&error];
[moc unlock];
if (error)
[NSApp presentError:error];
if ([response count] == 0) // empty resultset --> no artists with this name
{
[artistObject setValue:theArtist forKey:#"name"];
NSLog(#"%# not found. Adding.", theArtist);
return artistObject;
}
else
return [response objectAtIndex:0];
}
#end

You can not lock NSManagedObjects!

Related

An instance of class UITextField was deallocated while key value observers were still registered with it.

Hello i am getting this error
An instance 0x18872c0 of class UITextField was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger.
I am observing changes made on a textfield in ViewDidLoad
[textNumber addObserver:self forKeyPath:#"text" options:0 context:nil];
this responds at here
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context {
if (textNumber.text.length==0) {
[buttonMakeAudioCall setImage:[UIImage imageNamed:#"off_green_btn.png"] forState:UIControlStateNormal];
buttonMakeAudioCall.userInteractionEnabled=NO;
}else{
[buttonMakeAudioCall setImage:[UIImage imageNamed:#"green_btn.png"] forState:UIControlStateNormal];
buttonMakeAudioCall.userInteractionEnabled=YES;
}
}
Unfortunately app crashes inside the following method when response comes.
NSURL *url = [NSURL URLWithString:string];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError)
{
if (data.length > 0 && connectionError == nil)
{
NSDictionary *greeting = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
NSString *balance = [greeting objectForKey:#"balance"];
NSLog(#"balance is %#",balance);
labelStatus.text=[NSString stringWithFormat:#"%#€",balance];
}
}];
What i understood is textfield object/observer is released at some point and i need to handle it.But how?I am using ARC.If somebody who knows better could provide more information on the situation,i could handle it.
I found out the reason.It was a mistake from my side.Just before entering this view controller ,I'm calling a method. where I'm writing the following code.
NSURL *url = [NSURL URLWithString:string];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError)
{
if (data.length > 0 && connectionError == nil)
{
NSDictionary *greeting = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
NSString *sipserver = [greeting objectForKey:#"ip"];
NSString *port = [greeting objectForKey:#"port"];
NSString *control_url = [greeting objectForKey:#"control_url"];
NSString *version = [greeting objectForKey:#"version"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self.navigationController popViewControllerAnimated:YES];
[[NSUserDefaults standardUserDefaults]setBool:YES forKey:#"login"];
The problem is this line.
[self.navigationController popViewControllerAnimated:YES];
Im poping a parent view controller of the current view controller.Because i've used blocks,this happens like this.Anyhow i found out the solution.This had nothing to do with textfield or key value observer.Hope this answer helps some one .Thanks.

Crash Occurring on First Launch When populating core data database

I keep getting an error in the debugger for my application saying,
2013-06-23 16:07:15.826 collection view recipies[5681:c07] -[NSManagedObject length]: unrecognized selector sent to instance 0x9495280
2013-06-23 16:07:15.827 collection view recipies[5681:c07] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObject length]: unrecognized selector sent to instance 0x9495280'
* First throw call stack:
(0x26ac012 0x1517e7e 0x27374bd 0x269bbbc 0x269b94e 0x2b11c4 0x16d80a 0x4464 0x64f2da 0x6508f4 0x652b91 0x19c2dd 0x152b6b0 0x18eefc0 0x18e333c 0x18eeeaf 0x23b2bd 0x183b56 0x18266f 0x182589 0x1817e4 0x18161e 0x1823d9 0x1852d2 0x22f99c 0x17c574 0x17c76f 0x17c905 0x185917 0x14996c 0x14a94b 0x15bcb5 0x15cbeb 0x14e698 0x2c06df9 0x2c06ad0 0x2621bf5 0x2621962 0x2652bb6 0x2651f44 0x2651e1b 0x14a17a 0x14bffc 0x1e9d 0x1dc5)
libc++abi.dylib: terminate called throwing an exception
In My application delegate, if check to see if the application is being launched for the first time, and if it is, I then add several image paths to the core data structure.
In AppDelegate.m under ApplicationDidFinishLaunchingWithOptions,
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"])
{
// app already launched
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
// This is the first launch ever
NSArray *mainDishImages = [NSArray arrayWithObjects:#"egg_benedict.jpg", #"full_breakfast.jpg", #"ham_and_cheese_panini.jpg", #"ham_and_egg_sandwich.jpg", #"hamburger.jpg", #"instant_noodle_with_egg.jpg", #"japanese_noodle_with_pork.jpg", #"mushroom_risotto.jpg", #"noodle_with_bbq_pork.jpg", #"thai_shrimp_cake.jpg", #"vegetable_curry.jpg", nil];
NSArray *drinkDessertImages = [NSArray arrayWithObjects:#"angry_birds_cake.jpg", #"creme_brelee.jpg", #"green_tea.jpg", #"starbucks_coffee.jpg", #"white_chocolate_donut.jpg", nil];
for (NSString *imagePath in mainDishImages) {
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *newRecipe = [NSEntityDescription insertNewObjectForEntityForName:#"Recipe" inManagedObjectContext:context];
[newRecipe setValue:imagePath forKey:#"imageFilePath"];
}
for (NSString *imagePath in drinkDessertImages) {
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *newRecipe = [NSEntityDescription insertNewObjectForEntityForName:#"Deserts" inManagedObjectContext:context];
[newRecipe setValue:imagePath forKey:#"imageFilePath"];
}
}
And I access that data in my collectionViewController, I access that data.
- (NSManagedObjectContext *)managedObjectContext{
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Deserts"];
deserts = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
NSFetchRequest *fetchRequestTwo = [[NSFetchRequest alloc] initWithEntityName:#"Recipe"];
meals = [[managedObjectContext executeFetchRequest:fetchRequestTwo error:nil] mutableCopy];
recipeImages = [NSArray arrayWithObjects:meals, deserts, nil];
[self.collectionView reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Deserts"];
deserts = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
NSFetchRequest *fetchRequestTwo = [[NSFetchRequest alloc] initWithEntityName:#"Recipe"];
meals = [[managedObjectContext executeFetchRequest:fetchRequestTwo error:nil] mutableCopy];
recipeImages = [NSArray arrayWithObjects:meals, deserts, nil];
UICollectionViewFlowLayout *collectionViewLayout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
collectionViewLayout.sectionInset = UIEdgeInsetsMake(5, 0, 5, 0);
self.navigationController.navigationBar.translucent = YES;
self.collectionView.contentInset = (UIEdgeInsetsMake(44, 0, 0, 0));
selectedRecipes = [NSMutableArray array];
}
According to crashalytics, the error is in the line where it says
recipeImageView.image = [UIImage imageNamed:[recipeImages[indexPath.section] objectAtIndex:indexPath.row]];
In the method
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = [UIImage imageNamed:[recipeImages[indexPath.section] objectAtIndex:indexPath.row]];
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"photo-frame"]];
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"photo-frame-selected.png"]];
return cell;
}
I hope you can help. Thanks In Advance!
The UIImage method imageNamed takes an NSString as argument, but you pass a NSManagedObject to it.
You should get the image path from the managed object first. Try this:
id managedObject = [recipeImages[indexPath.section] objectAtIndex:indexPath.row];
NSString* imagePath = [managedObject valueForKey:#"imageFilePath"];
recipeImageView.image = [UIImage imageNamed:imagePath];

I'm not getting the NSPersistentStoreDidImportUbiquitousContentChangesNotification (with code sample)

I'm trying to learn how to use iCloud with coredata. My target is to sync a single database file on mac/ios. Both my mac and iOS apps seem to be updating iCloud as I can see it under System Preferences->iCloud->Manage ... There's an app named Unknown which everytime I change something on the ios/mac app is getting bigger and bigger. So that makes me think The apps are storing changes to the cloud. The problem is, I'm not getting the NSPersistentStoreDidImportUbiquitousContentChangesNotification when i change something on the other platform.
There's my code (mac app):
- (void)persistentStoreDidImportUbiquitousContentChangesNotification:(NSNotification *)notif
{
NSLog(#"%#", notif);
}
- (NSURL *)applicationFilesDirectory
{
NSString *identifier = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleIdentifier"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *libraryURL = [[[fileManager URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject] URLByAppendingPathComponent:identifier];
if(![fileManager fileExistsAtPath:[libraryURL path]])
{
[fileManager createDirectoryAtPath:[libraryURL path] withIntermediateDirectories:YES attributes:nil error:nil];
}
return libraryURL;
}
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel)
{
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"MyApp" withExtension:#"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator)
{
return __persistentStoreCoordinator;
}
NSManagedObjectModel *mom = [self managedObjectModel];
if (!mom)
{
NSLog(#"%#:%# No model to generate a store from", [self class], NSStringFromSelector(_cmd));
return nil;
}
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *applicationFilesDirectory = [self applicationFilesDirectory];
NSError *error = nil;
NSDictionary *properties = [applicationFilesDirectory resourceValuesForKeys:[NSArray arrayWithObject:NSURLIsDirectoryKey] error:&error];
if (!properties)
{
BOOL ok = NO;
if ([error code] == NSFileReadNoSuchFileError)
{
ok = [fileManager createDirectoryAtPath:[applicationFilesDirectory path] withIntermediateDirectories:YES attributes:nil error:&error];
}
if (!ok)
{
[[NSApplication sharedApplication] presentError:error];
return nil;
}
}
else
{
if ([[properties objectForKey:NSURLIsDirectoryKey] boolValue] != YES)
{
NSString *failureDescription = [NSString stringWithFormat:#"Expected a folder to store application data, found a file (%#).", [applicationFilesDirectory path]];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setValue:failureDescription forKey:NSLocalizedDescriptionKey];
error = [NSError errorWithDomain:#"YOUR_ERROR_DOMAIN" code:101 userInfo:dict];
[[NSApplication sharedApplication] presentError:error];
return nil;
}
}
NSString *appBundleID = [[NSBundle mainBundle] bundleIdentifier];
NSURL *storeURL = [applicationFilesDirectory URLByAppendingPathComponent:#"MyApp.sqlite"];
NSURL *cloudURL = [[fileManager URLForUbiquityContainerIdentifier:nil] URLByAppendingPathComponent:#"Database"];
NSPersistentStoreCoordinator *coordinator = [[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom] autorelease];
NSDictionary *optionsDict = [NSDictionary dictionaryWithObjectsAndKeys:appBundleID, NSPersistentStoreUbiquitousContentNameKey, cloudURL, NSPersistentStoreUbiquitousContentURLKey, [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,nil];
if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:optionsDict error:&error])
{
[[NSApplication sharedApplication] presentError:error];
return nil;
}
__persistentStoreCoordinator = [coordinator retain];
return __persistentStoreCoordinator;
}
- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext)
{
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator)
{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setValue:#"Failed to initialize the store" forKey:NSLocalizedDescriptionKey];
[dict setValue:#"There was an error building up the data file." forKey:NSLocalizedFailureReasonErrorKey];
NSError *error = [NSError errorWithDomain:#"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
[[NSApplication sharedApplication] presentError:error];
return nil;
}
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(persistentStoreDidImportUbiquitousContentChangesNotification:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:coordinator];
return __managedObjectContext;
}
I faced the same problem with iOS SDK.
To get "NSPersistentStoreDidImportUbiquitousContentChangesNotification" notification, you must call "- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject" from NSNotification center.
I added this line
[[NSNotificationCenter defaultCenter] addObserver:masterViewController selector:#selector(notifyiCloud:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:[self persistentStoreCoordinator]];
in the "didFinishLaunchingWithOptions" method of AppDelegate.
In my case, (iOS5) it worked perfectly, but I don't know if it will work in mac os, too.
I was having the same problem with CoreData stack running on both iOS and MacOS X. Between my iPhone and iPad, the NSPersistentStoreDidImportUbiquitousContentChangesNotification:s worked fine.
On the Mac I ended up periodically executing an NSFetchRequest (say every 5 seconds) and discarded the result. Only then did the notification arrive.

NSDistantObject enumeration

I was make communication for client-server application and have strange problem.
here is a code where i pickup objects.
- (byref NSArray*)objectsOfName:(bycopy NSString*)name
withPredicate:(bycopy NSPredicate*)predicate;
{
NSManagedObjectContext *context = [self managedObjectContext];
NSError *error = nil;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:name
inManagedObjectContext:context]];
[request setPredicate:predicate];
NSArray *results = [context executeFetchRequest:request error:&error];
[request release], request = nil;
if (error) {
NSLog(#"%#:%# Error on fetch %#", [self class], NSStringFromSelector(_cmd), error);
return nil;
}
//NSLog(#"%#:%# Result of fetch is %#", [self class], NSStringFromSelector(_cmd), results);
return results;
}
Here is pickup:
NSArray *destinations;
#ifdef SNOW_CLIENT
destinations = [server objectsOfName:#"DestinationsListWeBuy" withPredicate:predicate];
If i do
NSLog(#"Destination:%#\n",destinations);
i seen all objects in log.
If i try to do
NSLog(#"all:%#\n%#\n%#\n",[[destinations objectAtIndex:0] valueForKey:#"rate"],[[destinations objectAtIndex:0] valueForKey:#"lastUsedACD"],[[destinations objectAtIndex:0] valueForKey:#"lastUsedCallAttempts"]);
i seen attributes also.
But, if i try to do loop around objects:
for (NSManagedObject *dest in destinations)
{
NSLog(#"all:%#\n%#\n%#\n",[dest valueForKey:#"rate"],[dest valueForKey:#"lastUsedACD"],[dest valueForKey:#"lastUsedCallAttempts"]);
i have EXC_BAD_ACCESS in this part of code:
for (NSManagedObject *dest in destinations)
all debug technic, which i know, don't give me possibility to understand, what happened. (NSZombieEnabled = YES)
if i do loop at another manner:
for (NSUInteger count = 0;count < [destinations count]; count++)
NSLog(#"all:%#\n%#\n%#\n",[[destinations objectAtIndex:count] valueForKey:#"rate"],[[destinations objectAtIndex:count] valueForKey:#"lastUsedACD"],[[destinations objectAtIndex:count] valueForKey:#"lastUsedCallAttempts"]);
i seen all keys without exception. All nsmanagedobject's is subclassed.
If i need implement encodeWithCored method for all subclasses, examples is appreciated.
*UPDATE for Marcus *
This is how i receive objects from server side:
- (byref NSArray*)allObjects
{
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setValue:#"Failed to initialize the store" forKey:NSLocalizedDescriptionKey];
[dict setValue:#"There was an error building up the data file." forKey:NSLocalizedFailureReasonErrorKey];
NSError *error = [NSError errorWithDomain:#"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
[[NSApplication sharedApplication] presentError:error];
return nil;
}
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
[moc setPersistentStoreCoordinator:coordinator];
[moc setUndoManager:nil];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:#selector(mergeChangesForClient:)
name:NSManagedObjectContextDidSaveNotification
object:thirdMOC];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Carrier"
inManagedObjectContext:moc];
[request setEntity:entity];
[request setIncludesSubentities:YES];
NSError *error = nil;
NSArray *objects = [moc executeFetchRequest:request error:&error];
[request release], request = nil;
for (NSManagedObject *carrier in objects) {
NSSet *destinations = [carrier valueForKeyPath:#"destinationsListForSale"];
for (NSManagedObject *destination in destinations) [destination addObserver:self forKeyPath:#"rate" options:NSKeyValueObservingOptionNew context:nil];
}
if (error) {
NSLog(#"%#:%# error: %#", [self class], NSStringFromSelector(_cmd), error);
return nil;
}
return objects;
}
This is what i do with them on client side:
NSArray *allObjects = [server allObjects];
[carrierArrayController setContent:allObjects];
There is no serialization in this case. Any other ways (like send copy of server moc to client side doesn't work, it just generate exceptions on main.c).
p.s. many thanks to Marcus for his Core Data book.
unrecognized selector sent to class 0x1000a2ed8 2011-03-17 02:15:18.566 snowClient[19380:903] +[AppDelegate encodeWithCoder:]: unrecognized selector sent to class 0x1000a2ed8
That is not a core data problem. That is an error in your code where you are trying to call a method on an object that does not respond to that method. You need to track that down as it appears that you are trying to serialize your AppDelegate.
Update
What kind of class is 0x1000a2ed8? Break on the exception and print out the object to see what it is. Again, this is not a core data error directly, it is sending a messages to an object that does not respond to that message. It is possible that Core Data no longer allows you to send Managed objects across as distributed objects. It is possible that this is simply an issue with an over-released object. No way to know without further investigation.
Step one: Find out what object 0x1000a2ed8 is and see if the object changes from one run to the next.

View video in Landscape mode

I have a video in my application, but it's in portrait. I want to display it in landscape mode, but I don't have any idea how to do that.
I used this code to make my video:
- (IBAction)playMovie:(id)sender
{
NSString *filepath = [[NSBundle mainBundle] pathForResource:#"BAZO" ofType:#"m4v"];
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlaybackComplete:)name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayerController];
[self.view addSubview:moviePlayerController.view];
moviePlayerController.fullscreen = YES;
//Uncomment om beeld formaat aan te passen
//moviePlayerController.scalingMode = MPMovieScalingModeAspectFill;
[moviePlayerController play];
}
- (IBAction)playSecondMovie:(id)sender
{
NSString *filepath = [[NSBundle mainBundle] pathForResource:#"00 01. Welcome" ofType:#"mov"];
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlaybackComplete:)name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayerController];
[self.view addSubview:moviePlayerController.view];
moviePlayerController.fullscreen = YES;
//Uncomment om beeld formaat aan te passen
//moviePlayerController.scalingMode = MPMovieScalingModeAspectFill;
[moviePlayerController play];
}
- (void)moviePlaybackComplete:(NSNotification *)notification
{
MPMoviePlayerController *moviePlayerController = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayerController];
[moviePlayerController.view removeFromSuperview];
[moviePlayerController release];
}
-(void) tableView: (UITableView*) tableView
didSelectRowAtIndexPath: (NSIndexPath*) indexPath
{
NSString *filepath = [[NSBundle mainBundle] pathForResource:#"BAZO" ofType:#"m4v"];
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlaybackComplete:)name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayerController];
[self.view addSubview:moviePlayerController.view];
moviePlayerController.fullscreen = YES;
//Uncomment om beeld formaat aan te passen
//moviePlayerController.scalingMode = MPMovieScalingModeAspectFill;
[moviePlayerController play];
/*-(void)loadVideo:(NSString *)name ofType:(NSString *)type{
NSURL *url=[NSURL fileURLWithPath:[mainBundle pathForResource:#"BAZO" ofType:#"m4V"]]
if (!mp) mp = [[MPMoviePlayerController alloc] initWithContentURL:url];
[mp play];
}*/
}
Maybe somebody can give me a hint or a method so I can put this to landscape?
I used this code:
[MPMoviePlayerController setOrientation:UIDeviceOrientationLandscapeLeft animated:NO];
but it gives me the warning :
MPMoviePlayerController may not respond to -setOrientation:animated:
What's happening?
Had this problem as well,
I was running it in the appDelegate file, which meant I had to force the window to change to landscape so if the original is like this:
-(void)playMovie {
NSString *url = [[NSBundle mainBundle]
pathForResource:#"intro"
ofType:#"m4v"];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:url]];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
[player setFullscreen:YES animated:YES];
[player setControlStyle:MPMovieControlStyleNone];
[window addSubview:player.view];
[window bringSubviewToFront:player.view];
[player setFullscreen:YES animated:YES];
[player setControlStyle:MPMovieControlStyleNone];
[player play];
}
all that is needed is to add these lines:
[window setBounds:CGRectMake( 0, 0, 480, 320)];
[window setCenter:CGPointMake(160, 240];
[window setTransform:CGAffineTransformMakeRotation(M_PI/ 2)];
before the [player play], and at the movie finish call, add
struct CGRect rect = [[UIScreen mainScreen] bounds];
rect.origin.x = rect.origin.y = 0.0f;
window =[[UIWindow alloc] initWithFrame:rect];
[window makeKeyAndVisible];
to reset the view.
Not sure if it's the right way to do it, but it was the only thing worked for me.
Use MPMoviePlayerViewController instead of MPMoviePlayerController. It will handle orientation, control style, etc. I referred this answer for the same.
MPMoviePlayerViewController *playerView = [[[MPMoviePlayerViewController alloc] initWithContentURL:videoURL] autorelease];
[self presentMoviePlayerViewControllerAnimated:playerView];
and in the AppDelegate.m, declare the following function which will restrict the orientation to portrait in all cases and will only change when a video is playing
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if ([[self.window.rootViewController presentedViewController] isKindOfClass:[MPMoviePlayerViewController class]])
{
return UIInterfaceOrientationMaskAll;
}
else
{
//NSLog(#"orientation should change");
return UIInterfaceOrientationMaskPortrait;
}
}

Resources