Changing Core Data Items crashes App - iphone

I am running into another problem with my Iphone App which I just can't solve myself.
I implemented a kind of organizer functionality in my latest app.
There one can create appointments which are displayed in a tableview and persisted in a CoreDataStore. I use 4 classes:
an overview where appointments are displayed
a view with textfields to put in Values for place and name of appointment (create/edit view)
a view with DatePicker to define start- and enddate
a controller which handles creation and deletion of items using this methods:
The code:
-(void)createAppointmentObjectWithDate:(NSDate *)
appointmentDate name:(NSString *)appointmentName
description:(NSString *)appointmentDescription
eDate:(NSDate *)appointmentEndDate
{
NSManagedObjectContext *managedObjectContext = [[CoreDataManager sharedManager] managedObjectContext];
AppointmentObject *newAppointmentObject = [NSEntityDescription insertNewObjectForEntityForName:AppointmentObjectEntityName
inManagedObjectContext:managedObjectContext];
newAppointmentObject.appointmentName = appointmentName;
newAppointmentObject.appointmentDescription = appointmentDescription;
newAppointmentObject.appointmentDate = [appointmentDate earlierDate:appointmentEndDate];
newAppointmentObject.appointmentEndDate = [appointmentEndDate laterDate:appointmentDate];
}
-(void)deleteAppointmentObject:(AppointmentObject *)appointmentObject triggeredByUser:(BOOL)byUser{
NSManagedObjectContext *managedObjectContext = [[CoreDataManager sharedManager] managedObjectContext];
[managedObjectContext deleteObject:appointmentObject];
}
But all kind of crazy stuff is happening which makes my app crash with "SICBART" message:
2010-10-13 17:35:04.630 didacta[109:307] Serious application error. Exception was caught during Core Data change processing.
This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.
-[CALayer controllerWillChangeContent:]: unrecognized selector sent to instance 0x19f150 with userInfo (null)
2010-10-13 17:35:05.118 didacta[109:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CALayer controllerWillChangeContent:]: unrecognized selector sent to instance 0x19f150'
errors appear while doing this:
creating new Appointment and pressing "Done" (should trigger creation and pop overview)
changing appointments and pressing "Done" (should send changes and pop overview)
tapping on an appointment in overview ( should pop create/edit view and hand over values)
deleting an item
sometimes I can even delete an appointment but then the order of the items in the tableview is somehow gotten twisted so the index of the tableview isn't pointing to the index of the appointment anymore.

Right.
-[CALayer controllerWillChangeContent:]: unrecognized selector sent to instance 0x19f150 with userInfo (null)
That's your error. You have an NSFetchedResultsController whose delegate is a CALayer. This sounds like the original delegate was deallocated and a CALayer was allocated using the same region of memory. The fix is to find the offending -dealloc and add something like self.myFetchedResultsController.delegate = nil; self.myFetchedResultsController = nil; assuming you're using properties.
You can sometimes help debugging things like this by enabling zombies (go to Project → Edit Current Executable or so, select Environment, add the NSZombieEnabled environment variable, and set its value to "YES" or so; uncheck the checkbox when you've finished debugging). Zombies cause an exception when a message is sent to a deallocated object. (Zombies are not deallocated by default, so your application will effectively leak; remember to uncheck the checkbox!).

"unrecognized selector" makes it sound like maybe your data model doesn't contain some of the Entity attributes that you're trying to use. For example, maybe you're trying to set an attribute of the object that doesn't exist.
Try creating a breakpoint at newAppointmentObject.appointmentName = appointmentName; and step through it to see at what point the error occurs.

Related

reload table view : indexPath isn't reset ios 6

I'm making an iOS 6 program which downloads JSON data from a website and displays it in a table view. I added a pull to refresh method witch works fine. I can go in the settings view controller (secondViewController) and change the address, everything works. Then, I use the pull to refresh method and my tableView is reloaded. But if I reload 3 times AFTER changing the address, my app crashes. I get this error :
*** Terminating app due to uncaught exception 'NSRangeException',
reason: '*** -[__NSArrayM objectAtIndex:]: index 10 beyond bounds for empty array'
*** First throw call stack:
(0x1ca1012 0x10dee7e 0x1c430b4 0x3084 0xdd8fb 0xdd9cf 0xc61bb 0xd6b4b 0x732dd 0x10f26b0 0x229dfc0 0x229233c 0x2292150 0x22100bc 0x2211227 0x22bb333 0x22bb75f 0x1c60376 0x1c5fe06 0x1c47a82 0x1c46f44 0x1c46e1b 0x1bfb7e3 0x1bfb668 0x22ffc 0x1fbd 0x1ee5)
libc++abi.dylib: terminate called throwing an exception
What am I doing wrong ? And how can I fix that problem ? Thanks for your help !
The key design consideration that leaps out is that your retreiveData method is clearly updating the model (the citiesArray) asynchronously, which means that any interaction with the tableview while this is taking place may fail. You should never asynchronously update the actual citiesArray itself. The update to that array should happen in the main queue.
You should change retrieveData to not touch the existing citiesArray, but rather create and return a new array, and then, in the code you dispatch back to the main queue, only then replace the existing citiesArray and call reloadData, something like:
- (void)refresh:(UIRefreshControl *)refreshControl {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSArray *newCitiesArray = [self retreiveData];
dispatch_async(dispatch_get_main_queue(), ^{
if (newCitiesArray) {
// you presumably only want to reload the data if `retrieveData` was successful
citiesArray = newCitiesArray
[myTableView reloadData];
}
[refreshControl endRefreshing];
});
});
}
Clearly, this will involve some changes to retrieveData, too, but hopefully that's self explanatory. If not, update your question with that code, and we can make further suggestions. But we really shouldn't need to go there, as I suspect you understand the change that needs to take place there.
There are other, more subtle issues you might want to tackle, too, such as thinking about whether you really want to use a global queue, which is concurrent (e.g. if you hit refresh while the previous refresh going, do you really want two queries going on concurrently with your server ... because you dispatch the updates back to the main queue you won't crash, but it's inefficient, you're not guaranteed the order that they'll complete, etc.). You might also want to use NSOperationQueue in which you can write code to permit the cancellation of previous requests, etc.
But all of this is a little complicated and is of secondary concern to your main issue, the crashing. Refactoring the retrieveData code to ensure you don't touch citiesArray, itself, as outlined above, should address that.

Synchronizing issues of MBO in SUP 2.1.3

I am trying to run an iOS application which is migrated from SUP2.1.2 to SUP2.1.3. An application is working fine with device registration and connection, but the problem arises when i try to synchronize 3 MBO synchronization group. The synchronization is working fine for the first time, but when i click over different item to synchronize its detail i am getting following error:
*** -[CFString retain]: message sent to deallocated instance 0x6465650
I think problem is coming under the following MBO method
+ (ITEMSSynchronizationParameters*)getSynchronizationParameters
{
return (ITEMSSynchronizationParameters*)[(SUPSyncParamEntityDelegate*)([[ITEMDATABASE delegate] getDelegate:#"ITEMSSynchronizationParameters"]) getSynchronizationParameters];
}
and i am calling this method while synchronizing app details as follows
ITEMSynchronizationParameters *syncParam = [ITEMSynchronizationParameters getSynchronizationParameters];
[syncParam setSYNC_NO:#"101"];
[syncParam save];
While It also not allowing me to delete sync parameter so that on each items click i should get different information details as [syncParam delete] is causing the same * -[CFString retain]: message sent to deallocated instance 0x6465650 error. I have used patch 01 and 02 but the problem is still present. Any help would be appreciated.
we had the same Problem.
In my case the answer for this problem was to create a locale property for the SynchronizationParameters and work with the Property. I don't know why but now the delicate error is gone.
#property (nonatomic, retain) ITEMSynchronizationParameters *item_sp;
item_sp = [Item getSynchronizationParameters];
item_sp.syncparam = #"XXXXX";
[item_sp save];

Passing UISearchBar.text to another function

It's my first time working with a UISearchBar and so far it went fine, but now after clicking "search" I'm trying to pass the text to another function that handles the search.
[_searchModel searchIssueForTerm:searchBar.text inIssue:_dataModel.currentIssue];
This just throws me an error, saying:
-[CFString copyWithZone:]: message sent to deallocated instance 0x7dee900
But when I use this, it just works
[_searchModel searchIssueForTerm:#"test" inIssue:_dataModel.currentIssue];
Why is this hapenning? In my - (void)searchIssueForTerm:(NSString *)searchTerm inIssue:(Issue *)issue I store the NSString in another variable, why would it get deallocated then?
After searching for a while I managed to fix it by just saving the variable somewhere else, seems it was getting lost along the way.
_currentSearchTerm = [[NSString alloc] initWithString:searchTerm];

Problem with NSManagedObjectContext crashing app

I have a navigation based app that uses Core Data for storage. The schema for this particular section is as follows:
Scene hasMany Tasks hasMany DeviceCommands
Tasks also have many other objects besides DeviceCommands (like DelayCommands etc), but this is beyond the scope of the problem (I think).
DeviceCommands also link to a parent object as follows:
Device hasMany DeviceCommands
Now, the user can create a new Task, which pops up a modal view to select the Device. When you select a device, a tableview is pushed with the DeviceCommands that belong to the Device. When you select a DeviceCommand, it assigns it to the Task with task.deviceCommand = device.deviceCommand. For some reason, and this only happens in this section of the app, the app crashes with the following output in the console:
2010-10-26 15:37:33.337 livOS4[47226:207] Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. * -[NSMutableArray objectAtIndex:]: index 35 beyond bounds [0 .. 0] with userInfo (null)
Index 35 refers to the index of the DeviceCommand in the UITableView and NSFetchedResultsController. Through a process of trial and error I've discovered that the NSMutableArray is the array with the Devices. If I add a new Device to the app, the array bounds are [0 .. 1].
I added an observer for NSManagedObjectContextObjectsDidChangeNotifications but it crashes before the observer receives anything.
Can anyone help or offer any advice for fixing this?
I have the same problems with NSFetchedResultsController.
Problem disappear then I add this to my viewController
- (void)dealloc
{
self.fetchedResultsController.delegate = nil;
self.fetchedResultsController = nil;
}
Fixed it this morning. Turned out to be a problem with how I was assigning the NSFetchedResultsController delegate.

Multiple UITableViews displaying the same data

I am working on an app that has several views selected using a tab bar. One tab displays a list of data using a table view. Another tab uses a table view (and a navigation controller) so the user can add items to/delete items from the list.
If the user switches to the first tab after adding or deleting items on the other tab, the app crashes. (I'm still working on trying to glean anything useful from the debugger output).
New (as of 22 Aug) info:
In light of some of the comments below, I've been doing some exploring and I think I must not be allocating objects correctly. Below is a stack trace, but note I am not always getting the same error. Eg, sometimes I get an uncaught exception, sometimes just the debugger steps in; when it is an uncaught exception, it's not always the same one.
2009-08-22 15:20:34.254 Mexico[29531:20b] * -[_NSIndexPathUniqueTreeNode isEqualToString:]: unrecognized selector sent to instance 0x562ff0
2009-08-22 15:20:34.255 Mexico[29531:20b] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[_NSIndexPathUniqueTreeNode isEqualToString:]: unrecognized selector sent to instance 0x562ff0'
2009-08-22 15:20:34.257 Mexico[29531:20b] Stack: (
2504683691,
2423127611,
2504712874,
2504706220,
2504706418,
817812590,
19892,
816386359,
816387412,
816468754,
816411067,
836579268,
836579060,
836577406,
836576671,
2504177986,
2504184740,
2504187000,
827745792,
827745989,
816114848,
816160924
)
[Session started at 2009-08-22 15:20:34 -0400.]
Loading program into debugger…
GNU gdb 6.3.50-20050815 (Apple version gdb-962) (Sat Jul 26 08:14:40 UTC 2008)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin".warning: Unable to read symbols for "/System/Library/Frameworks/UIKit.framework/UIKit" (file not found).
warning: Unable to read symbols from "UIKit" (not yet mapped into memory).
warning: Unable to read symbols for "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics" (file not found).
warning: Unable to read symbols from "CoreGraphics" (not yet mapped into memory).
Program loaded.
sharedlibrary apply-load-rules all
Attaching to program: `/Users/matt/Library/Application Support/iPhone Simulator/User/Applications/0F9033CE-39BB-4589-B791-5E473D991789/Mexico.app/Mexico', process 29531.
(gdb) bt
#0 0x954a6f54 in ___TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION___ ()
#1 0x906dfe3b in objc_exception_throw ()
#2 0x9542da53 in CFRunLoopRunSpecific ()
#3 0x9542dc78 in CFRunLoopRunInMode ()
#4 0x31566600 in GSEventRunModal ()
#5 0x315666c5 in GSEventRun ()
#6 0x30a4eca0 in -[UIApplication _run] ()
#7 0x30a5a09c in UIApplicationMain ()
#8 0x00001ffc in main (argc=1, argv=0xbfffe108) at /Users/matt/Coding/iPhone/Mexico/main.m:13
(gdb)
Here is some (I think) relevent code. First, the function that invokes a view to add a new entry:
- (IBAction)addButtonWasPressed {
AddPlayerViewController *apvController;
apvController = [[AddPlayerViewController alloc]
initWithNibName:#"AddPlayerView" bundle:nil];
apvController.rvController = self;
[self.navigationController pushViewController:apvController animated:YES];
[apvController release];
}
Then in the add player view:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[rvController addPlayerNamed:textField.text];
[textField resignFirstResponder];
[self.navigationController popViewControllerAnimated:YES];
return YES;
}
Finally RosterViewController is a subclass of UITableViewController and has the following method:
- (void)addPlayerNamed:(NSString *)name {
Player *player = [[Player alloc] initWithName:name];
[players addObject:player];
// insert NSLogS
NSIndexPath *indexPath;
indexPath = [NSIndexPath indexPathForRow:[players indexOfObject:player] inSection:0];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:NO];
}
If I iterate over players and print out the names using NSLog statements (see commented spot above), then the app crashes after I add a second entry. If I take the NSLog statements out, then it won't crash until later.
If i had to guess, i would say you are probably sharing the data objects (data sources) in your two table views and deleting from one is affecting the other, and you try to do something with the released object in the other view which is causing the app to crash, or something along those lines.
Here's how I'd do it:
Create a class that implements the UITableViewDataStore delegate methods. Assign it to something accessible from both viewcontrollers. A good place is up at the UIApplication level so you can get to it via something like:
MyDataStore* store = ((MyApplication *)[UIApplication sharedApplication]).{myDataStore}
For backing store this class would keep the actual values in an array, a dictionary, a SQLite database, or something like that.
Assign this class to each table's dataSource property. Since it's owned by the app it shouldn't be released until the app is finished. So you'll want to make sure the object is accessible via a property with a "retain" attribute.
Each time the user adds something you'll want to add it to this object then call reloadData on the table to refresh the table.
For each of those views implement the viewWillAppear method. This gets called whenever that view comes into view. Inside it make a call to the table reloadData as well. This way when the user switches from one view to another, before the new view is shown, it will have refreshed itself with the new data.
If you assign the datastore object to the application then it owns it for the lifetime of the app so you probably don't want to set it to autorelease. If memory becomes an issue then you'll want to save the backing stuff to SQLite or CoreData.
You're probably already doing all this but this is the general pattern for creating shared data between views. Maybe it'll help jog something.