Cocoa Development - Having trouble loading local XML files when running from device - iphone

I have a program that runs perfectly fine when I run on the simulator, but it won't run from the device at all. Part of the initial run involves loading a few XML files into core data and it seems that these files are not being found when running on the device.
Here is the beginning of the routine that loads the file. Any help is much appreciated.
- (BOOL) checkForUpdate:(NSString *)entityName {
NSArray *thisObjectArray = nil;
NSDate *thisEntityDate = nil;
BOOL returnVal = NO;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"AppData" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *appDataArray = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
AppData *thisAppData = [appDataArray objectAtIndex:0];
if ([entityName isEqualToString:#"Features"]) {
thisEntityDate = thisAppData.FeaturesUpdated;
}
else if ([entityName isEqualToString:#"DisplayTypes"]) {
thisEntityDate = thisAppData.DisplayTypesUpdated;
}
else if ([entityName isEqualToString:#"Sections"]) {
thisEntityDate = thisAppData.SectionsUpdated;
}
NSString *filePath = [[NSBundle mainBundle] pathForResource:entityName ofType:#"xml"];
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfFile:filePath];
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
if (doc != nil) {
// process information - this code is not being called because doc is returning nil
}
[xmlData release];
[doc release];
return returnVal;
}

Mind the case sensitivity. The device is case sensitive, whilst the simulator is not.

Related

Table view and Predicates

I have a table view with 40 objects. I have to filter them by gender when Click in a UISegment (male, female and both). It seems to be working, but table view does not refresh. Please any help would be appreciatte.
-(void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = #"People";
[self loadall];
[[NSBundle mainBundle] loadNibNamed:#"FilterSortView" owner:self options:nil];
self.filterControl.selectedSegmentIndex = -1;
[self.filterControl addTarget:self action:#selector( changeSegge ) forControlEvents:UIControlEventValueChanged];
}
#
My second method to filter by gender
- (void)changeSegge
{
NSEntityDescription *personEntity = [NSEntityDescription entityForName:#"Person"
inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:personEntity];
NSError *error = nil;
self.people = [self.managedObjectContext executeFetchRequest:request error:&error];
if (error)
{
[NSException raise:NSInternalInconsistencyException format:#"Could not fetch Core Data records: %#",error];
}
if(filterControl.selectedSegmentIndex == 0){
NSPredicate *predicatem =[NSPredicate predicateWithFormat:#"gender == %#", #"m" ];
request.predicate=predicatem;
[self.tableView reloadData];
[request release];
NSLog(#"button 1");
}
Thanks a lot.
You forgot to fill people array after predicate set to fetch request.
Here is updated changeSegge method:
- (void)changeSegge
{
NSEntityDescription *personEntity = [NSEntityDescription entityForName:#"Person"
inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:personEntity];
NSError *error = nil;
self.people = [self.managedObjectContext executeFetchRequest:request error:&error];
if (error)
{
[NSException raise:NSInternalInconsistencyException format:#"Could not fetch Core Data >records: %#",error];
}
if(filterControl.selectedSegmentIndex == 0){
NSPredicate *predicatem =[NSPredicate predicateWithFormat:#"gender == %#", #"m" ];
request.predicate=predicatem;
self.people = [self.managedObjectContext executeFetchRequest:request error:&error];
[self.tableView reloadData];
[request release];
NSLog(#"button 1");
}

How to convert binary data to NSData

I have converted the UIImageview into NSData and stored it as binary data. but i don't know how to retrieve the binary data to NSData and convert that to UIImageview
my code is below
image save as binary data----
-(void) save
{
UIImage *img = [UIImage imageNamed:#"back2.png"];
NSData *dataObj =UIImagePNGRepresentation(img);
NotesDetails *notesDetails = (NotesDetails *) [NSEntityDescription insertNewObjectForEntityForName:#"NotesDetails" inManagedObjectContext:managedObjectContext];
notesDetails.imageData=dataObj;
NSLog(#"NotesDetails: %#",notesDetails);
NSError *error;
if (![managedObjectContext save:&error])
{
}
}
Image Retreive------
-(void)viewDidLoad
{
NSFetchRequest *fectchreq = [[NSFetchRequest alloc] init];
NSEntityDescription *entitydes = [NSEntityDescription entityForName:#"NotesDetails"
inManagedObjectContext:self.managedObjectContext];
[fectchreq setEntity:entitydes];
NSSortDescriptor *sortdes = [[NSSortDescriptor alloc] initWithKey:#"notesTime" ascending:YES];
NSArray *sortdesarray = [[NSArray alloc] initWithObjects:sortdes, nil];
[fectchreq setSortDescriptors:sortdesarray];
NSError *error;
NSMutableArray *storeddata = [[self.managedObjectContext executeFetchRequest:fectchreq error:&error] mutableCopy];
if ([storeddata count] > 0)
{
for (NotesDetails *sc in storeddata)
{
imgFromDb=[NSData dataWithData:[#"%#",sc.imageData]];
}
}
NSLog(#"Image : %#",imgFromDb);
UIImageView *dbImage=[[UIImageView alloc]initWithFrame:CGRectMake(80,20,90,90)];
dbImage.image=[UIImage imageWithData:imgFromDb];
[NoteDetails addSubview:dbImage];
}
You can use NSKeyedUnarchiver:
imgFromDb= [NSKeyedUnarchiver unarchiveObjectWithData: sc.imageData];
And you can do the opposite (object to data) with NSKeyedArchiver if you prefer it vs UIImagePNGRepresentation().
And there are other ways to do this, for example:
imgFromDb= [UIImage imageWithData: sc.imageData];

Core Data to SQL not working

I have been trying like hell to figure out how to establish a connection between my Core Data & my SQL database. The database isn't pre-populated, but it will be used amongst many different users when it's launched.
I have gone through the Core Data & iCloud classes provided by Stanford three times to no avail. I have also looked throughly into SQLite/SQL relational databases in iOS to no avail. The only other option I have is to come on here, post all the code I can, and pray that somebody will have an answer for me. So here it goes...
AppDelegate.m
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
#pragma mark - Core Data stack
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [self applicationDocumentsDirectory];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"shindy.sqlite"];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
#pragma mark - Application's Documents directory
- (NSURL *)applicationDocumentsDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"shindy.sqlite"];
return [NSURL fileURLWithPath:path];
}
HomeViewController.m
- (void)setupFetchedResultsController
{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Shindy"];
request.sortDescriptors = [NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"dateAndTime" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"photo" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"details" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"timePosted" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"location" ascending:YES],
nil];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.shindyDatabase.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
}
- (void)fetchShindyDataIntoDocument:(UIManagedDocument *)document
{
dispatch_queue_t fetchQ = dispatch_queue_create("Shindy Fetcher", nil);
dispatch_async(fetchQ, ^{
NSArray *shindys = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSLog(#"shindys = %#", shindys);
[document.managedObjectContext performBlock:^{
for (NSDictionary *shindyInfo in shindys) {
[Shindy shindyWithShindyDBInfo:shindyInfo inManagedObjectContext:document.managedObjectContext];
NSLog(#"fire");
}
}];
});
}
- (void)useDocument
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"shindy.sqlite"];
if (![[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil]) {
[self.shindyDatabase saveToURL:self.shindyDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
[self setupFetchedResultsController];
[self fetchShindyDataIntoDocument:self.shindyDatabase];
}];
} else if (self.shindyDatabase.documentState == UIDocumentStateClosed) {
[self.shindyDatabase openWithCompletionHandler:^(BOOL success) {
[self setupFetchedResultsController];
}];
} else if (self.shindyDatabase.documentState == UIDocumentStateNormal) {
[self setupFetchedResultsController];
}
}
- (void)setShindyDatabase:(UIManagedDocument *)shindyDatabase
{
[self useDocument];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self fetchShindyDataIntoDocument:self.shindyDatabase];
if (!self.shindyDatabase) {
[self setShindyDatabase:self.shindyDatabase];
}
}
Shindy+ShindyDB.m
+ (Shindy *)shindyWithShindyDBInfo:(NSDictionary *)shindyInfo
inManagedObjectContext:(NSManagedObjectContext *)context
{
Shindy *shindy = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Shindy"];
NSSortDescriptor *dateAndTimeSort = [NSSortDescriptor sortDescriptorWithKey:#"dateAndTime" ascending:YES];
NSSortDescriptor *detailsSort = [NSSortDescriptor sortDescriptorWithKey:#"details" ascending:YES];
NSSortDescriptor *locationSort = [NSSortDescriptor sortDescriptorWithKey:#"location" ascending:YES];
NSSortDescriptor *nameSort = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
NSSortDescriptor *photoSort = [NSSortDescriptor sortDescriptorWithKey:#"photo" ascending:YES];
NSSortDescriptor *timePostedSort = [NSSortDescriptor sortDescriptorWithKey:#"timePosted" ascending:YES];
// title
request.sortDescriptors = [NSArray arrayWithObjects:dateAndTimeSort, detailsSort, locationSort, nameSort, photoSort, timePostedSort, nil];
NSError *error = nil;
NSArray *matches = [context executeFetchRequest:request error:&error];
if (!matches || ([matches count] > 1)) {
// handle error
} else if ([matches count] == 0) {
shindy = [NSEntityDescription insertNewObjectForEntityForName:#"Shindy" inManagedObjectContext:context];
shindy.dateAndTime = [shindyInfo objectForKey:#"dateAndTime"];
shindy.details = [shindyInfo objectForKey:#"details"];
shindy.location = [shindyInfo objectForKey:#"location"];
shindy.name = [shindyInfo objectForKey:#"name"];
shindy.photo = [shindyInfo objectForKey:#"photo"];
shindy.timePosted = [shindyInfo objectForKey:#"timePosted"];
// title
// Guestlist? The rest?
// Use below for reference
shindy.whoseShindy = [User userWithName:[shindyInfo objectForKey:#"whoseShindy"] inManagedObjectContext:context];
} else {
shindy = [matches lastObject];
}
shindy = [NSEntityDescription insertNewObjectForEntityForName:#"Shindy" inManagedObjectContext:context];
shindy.dateAndTime = [shindyInfo objectForKey:#"dateAndTime"];
shindy.details = [shindyInfo objectForKey:#"details"];
shindy.location = [shindyInfo objectForKey:#"location"];
shindy.name = [shindyInfo objectForKey:#"name"];
shindy.photo = [shindyInfo objectForKey:#"photo"];
shindy.timePosted = [shindyInfo objectForKey:#"timePosted"];
return shindy;
}
AddShindyViewController.m
- (void)saveShindyToDatabase
{
NSArray *shindys = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
[self.shindyDatabase.managedObjectContext performBlock:^{
for (NSDictionary *shindyInfo in shindys) {
[Shindy shindyWithShindyDBInfo:shindyInfo inManagedObjectContext:self.shindyDatabase.managedObjectContext];
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
// url = [url URLByAppendingPathComponent:#"Default Shindy Database"];
self.shindyDatabase = [[UIManagedDocument alloc] initWithFileURL:url];
[self.shindyDatabase setValue:self.detailView.text forKey:#"details"];
if (FBSession.activeSession.isOpen) {
[[FBRequest requestForMe] startWithCompletionHandler:
^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (!error) {
self.name = user.name;
self.photo.profileID = user.id;
self.username = user.username;
}
}];
}
[self.shindyDatabase setValue:self.name forKey:#"name"];
[self.shindyDatabase setValue:self.photo forKey:#"photo"];
[self.shindyDatabase setValue:self.username forKey:#"username"];
// [Guest guestWithName:self.name username:self.username photo:self.photo inManagedObjectContext:self.shindyDatabase.managedObjectContext];
[self.shindyDatabase setValue:self.locationManager.location forKey:#"location"];
[self.shindyDatabase setValue:self.dateAndTimePicker.date forKey:#"dateAndTime"];
}
}];
}
I know what I'm asking for is a hell of a lot, but I have exhausted every single resource I have at my disposal. If anybody can even just point me in the right direction, I would be eternally grateful!
If you plan to map an existing database with CoreData you will be unsuccessful.
There's infact no way you can map any database with CoreData.
Core Data infact is a graph object management, with different storage option, and sqllite is just one of the possibility. At startup, if you choose sqllite as option, your application is going to create a database with a specific tables structure. If you try to connect to a database not created by CoreData framework you will get an error.
What you can do is get rid of CoreData, and build your NSObject to act like entities. But then, you will have to implement all the logic to save, update, versioning, concurrency ecc... and it's a long (and buggy) way, especially in a multi user environment.
Otherwise, tell me if I misunderstood your question. Maybe, you can post an error stack trace.

get NSString from NSFetchRequest issue

I'm using Core Data and I need to loop thru the result of the request, create several custom objects in the loop and store them in a NSMUtableArray, so I can send it to another view to feed a UI component. This is what I'm doing:
NSMutableArray *persons = [[NSMutableArray alloc] init];
NSError *error = nil;
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Person" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *info in fetchedObjects) {
ToggleButtonInfo *btn = [[ToggleButtonInfo alloc] init];
NSString *personName = [NSString stringWithFormat:#"ww %#", [info valueForKey:#"name"]];
NSLog(#"pn: %#", personName);
[btn setButtonInfo:personName];
[persons addObject:btn];
}
[fetchRequest release];
return persons;
The loop is working just fine, the information is there. The problem is that I get a "EXC_BAD_ACCESS" in my component if I use:
[info valueForKey:#"name"]
if I do something like this:
[btn setButtonInfo:#"something else here"];
everything works fine. So it looks like info is been de-allocated and that is causing the error, right? I try creating the scring using stringWithFormat but it doesn't work, same error.
An ideas?
Where do you get the EXC_BAD_ACCESS? I assume it's later when you're displaying the button? -setButtonInfo: probably isn't retaining, or you're over-releasing somewhere else.
Note that you're leaking btn in this code.

Core Data Import Failure

I'm trying to import a large data set (~6,000) in to my core data application. I've read the Apple document "Efficiently Importing Data" and I think I set it up correctly. The weird thing is the application isn't crashing in the simulator, although it does if I run it with the Leaks instrument, but it isn't saving all the data. Sometimes it will only save 3-4 hundred other times it will save 3-4 thousand and rarely the whole data set. I think it's probably memory leak related and I'm pretty new to using NSAutoReleasePool, any help would be much appreciated.
NSURL *url = [NSURL URLWithString:#""];
NSString *responseString = [NSString stringWithContentsOfURL:url encoding:NSASCIIStringEncoding error:nil];
if (responseString) {
NSArray *players = [responseString componentsSeparatedByString:#";"];
NSUInteger LOOP_LIMIT = 100, count = 0;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSManagedObjectContext *context = [[AppController sharedAppController] managedObjectContext];
[context setUndoManager:nil];
for (int i=0; i<([players count] - 1); i++) {
NSArray *info = [[players objectAtIndex:i] componentsSeparatedByString:#","];
NSString *dateInfo = [info objectAtIndex:10];
NSLocale *usLocale = [[[NSLocale alloc] initWithLocaleIdentifier:#"en_US"] autorelease];
NSDateFormatter *fo = [[[NSDateFormatter alloc] init] autorelease];
[fo setDateFormat:#"MM/dd/yyyy"];
[fo setLocale:usLocale];
[fo setTimeZone:[NSTimeZone systemTimeZone]];
NSDate *dob = [fo dateFromString:dateInfo];
Players *player = [NSEntityDescription insertNewObjectForEntityForName:#"Players"
inManagedObjectContext:context];
NSNumberFormatter *f = [[[NSNumberFormatter alloc] init] autorelease];
[f setNumberStyle:NSNumberFormatterNoStyle];
player.playerID = [f numberFromString:[info objectAtIndex:0]];
player.lastName = [info objectAtIndex:1];
player.firstName = [info objectAtIndex:2];
player.position = [info objectAtIndex:4];
NSString *teamName = [info objectAtIndex:3];
NSFetchRequest *req = [[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription *ent = [NSEntityDescription entityForName:#"Teams" inManagedObjectContext:context];
[req setEntity:ent];
[req setIncludesPropertyValues:NO];
NSPredicate *pre = [NSPredicate predicateWithFormat:#"team=%#", teamName];
[req setPredicate:pre];
NSArray *list = [context executeFetchRequest:req error:nil];
if ([list count]) {
Teams *team = [list objectAtIndex:0];
player.team_Players_Teams = team;
}
count++;
if (count == LOOP_LIMIT) {
[context save:nil];
[context reset];
[pool drain];
pool = [[NSAutoreleasePool alloc] init];
count = 0;
}
}
if (count != 0) {
NSLog(#"In Save Remaining");
[context save:nil];
[context reset];[pool drain];
}
I can't see anything dodgy in the code either. Definitely no errors appearing in the log?
Btw one other optimisation tip covered in the Core Data pdf for importing data is to move the predicate creation outside the loop and use substitution variables.
I can't see any obvious leaks but:
You could minimise the amount of memory used by alloc init retain-ing the NSLocale, NSDateFormatter, NSNumberFormatter and then release-ing them after the loop is complete. These don't seem to change between runs of the loop.
I don't know Core Data but where does the NSManagedObject/Player *player object get released? Is this autoreleased through Core Data?
As an aside, you can use [list lastObject] rather than [list count] and [list objectAtIndex:0] as the last two will crash if list is nil
Update based on response:
If nothing appears to make a difference then the next step is to simplify the code so as to remove any error sources.
Carry out my suggestions in #1 above to minimise the amount of code in the loop.
Check you're releasing the list object somewhere or that it is allocated as autorelease.
Remove the intermediate saving (all that code inside count == LOOP_LIMIT) and only save and drain the pool once all the arrays have been processed. You also should not need the code following on inside the if (count != 0)
Replace the error:nil statements with proper error:&&error and log errors. To log the errors do the following (apologies but the code formatting doesn't seem to work - no idea why):
NSError *error = nil; //Declared upfront
// Your streamlined code
// ....
error = nil; //Just before a fetchRequest or context:save
/* After looping through all your code now attempt to save */
if(![context save:&error]) {
NSLog(#"Failed to save to data store: %#", [error localizedDescription]);
NSArray *detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
if(detailedErrors != nil && [detailedErrors count] > 0) {
for(NSError *detailedError in detailedErrors) {
NSLog(#"DetailedError: %#", [detailedError userInfo]);
}
} else {
NSLog(#" %#", [error userInfo]);
}
}
Then check the log to see if you're getting any odd messages. You can also use similar code anywhere in Core Data that you need to check for errors (i.e. executeFetchRequest). It's worth a shot to find out what the error is here.