Before I begin, I should tell you that this only happens in iOS 5.1. Before the most recent update, this had never happened and it still does not happen on any other version. That said, here's what's going on.
When a user logs out of my app, one of the things that happens is that all of the NSUserDefaults get deleted. Rather than manually removing every key I might add to the user's defaults, I just completely delete all of the NSUserDefaults, using the method suggested in this SO question:
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
What seems to happen though, is that every time I try to create a UIWebView after having removed NSUserDefaults, I get an EXC_CRASH (SIGABRT). The crash happens when I call [[UIWebView alloc] initWithFrame:frame]. Strange right? Completely quitting and reopening the app allows UIWebViews to be created again.
So, I managed to figure out that removing the defaults would cause the UIWebView issue, but to be sure, I added a symbolic breakpoint for -[NSUserDefaults setObject:forKey:].
Creating a UIWebView does indeed trigger the breakpoint.
Poking through the crash logs gives me the exception reason:
-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: WebKitLocalStorageDatabasePathPreferenceKey)
And here's the beginning of the stack trace:
0 CoreFoundation 0x3340688f __exceptionPreprocess + 163
1 libobjc.A.dylib 0x37bd4259 objc_exception_throw + 33
2 CoreFoundation 0x33406789 +[NSException raise:format:] + 1
3 CoreFoundation 0x334067ab +[NSException raise:format:] + 35
4 CoreFoundation 0x3337368b -[__NSCFDictionary setObject:forKey:] + 235
5 WebKit 0x3541e043 -[WebPreferences _setStringValue:forKey:] + 151
6 UIKit 0x32841f8f -[UIWebView _webViewCommonInit:] + 1547
7 UIKit 0x328418d7 -[UIWebView initWithFrame:] + 75
8 MyApp 0x0007576f + 0
9 UIKit 0x326d4dbf -[UIViewController view] + 51
10 UIKit 0x327347e5 -[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:] + 93
11 UIKit 0x32734783 -[UITabBarController transitionFromViewController:toViewController:] + 31
12 UIKit 0x327340bd -[UITabBarController _setSelectedViewController:] + 301
13 UIKit 0x327bd5d9 -[UITabBarController _tabBarItemClicked:] + 345
What I'm doing for now, and what works, is just keeping track of the NSUserDefaults keys I have set and removing them all manually when I need to. But there's always a risk I might forget a sensitive key, so simply clearing all NSUserDefaults strikes me as more sensible. So, I would like to know why I can't do that. Is it a bug or am I doing something wrong?
If you want any more info, just let me know! Thanks.
EDIT: Doing [[NSUserDefaults standardUserDefaults] synchronize] after deleting all NSUserDefaults does not help.
I'm seeing this issue as well, I think you have to have created a UIWebView first before clearing user defaults for it to occur. A clean project with the following will cause the crash in iOS5.1, this works fine in iOS5.0 and earlier:
UIWebView *webView = [[UIWebView alloc] init];
[webView release];
[[NSUserDefaults standardUserDefaults] setPersistentDomain:[NSDictionary dictionary] forName:[[NSBundle mainBundle] bundleIdentifier]];
UIWebView *anotherWebView = [[UIWebView alloc] init];
[anotherWebView release];
I can work around the crash by doing this instead, which avoids having to remember all your settings keys:
id workaround51Crash = [[NSUserDefaults standardUserDefaults] objectForKey:#"WebKitLocalStorageDatabasePathPreferenceKey"];
NSDictionary *emptySettings = (workaround51Crash != nil)
? [NSDictionary dictionaryWithObject:workaround51Crash forKey:#"WebKitLocalStorageDatabasePathPreferenceKey"]
: [NSDictionary dictionary];
[[NSUserDefaults standardUserDefaults] setPersistentDomain:emptySettings forName:[[NSBundle mainBundle] bundleIdentifier]];
Anyone see any issues with doing it this way?
It sounds like you're removing some sort of private preference, which is probably a new bug, either with NSUserDefaults (you shouldnt be able to remove it) or UIWebView (it should cope with a missing entry).
Have you tried the method from the other answer (setting a blank dictionary?). Does that give the same results?
How about if you get the dictionary representation of NSUserDefaults, get all the keys, and iterate through those, removing the objects? (let me know if you need a code sample for that).
It works for me
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSDictionary *userDefaultsDictionary = [userDefaults dictionaryRepresentation];
NSString *strWebDatabaseDirectory = [userDefaultsDictionary objectForKey:#"WebDatabaseDirectory"];
NSString *strWebKitLocalStorageDatabasePathPreferenceKey = [userDefaultsDictionary objectForKey:#"WebKitLocalStorageDatabasePathPreferenceKey"];
[userDefaults removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
if (strWebDatabaseDirectory) {
[userDefaults setObject:strWebDatabaseDirectory forKey:#"WebDatabaseDirectory"];}
if (strWebKitLocalStorageDatabasePathPreferenceKey) {
[userDefaults setObject:strWebKitLocalStorageDatabasePathPreferenceKey forKey:#"WebKitLocalStorageDatabasePathPreferenceKey"];}
[userDefaults synchronize];
Simpler it will be to use the code below:
[self saveValue:#"" forKey:#"WebKitLocalStorageDatabasePathPreferenceKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
It is easier.
Related
I know that documentation says that it is, and i know that this subject was already under discussion but I have an interesting stack result and I cant conclude anything else but that [NSUserDefaults standardUserDefaults] is not threadsafe. So I will post my crash log and hope that somebody sees something that I can't...
Crashed Thread
...
libdispatch.dylib 0x3ab53d67 _dispatch_client_callout + 23
libdispatch.dylib 0x3ab65e73 _dispatch_barrier_sync_f_invoke + 27
CoreFoundation 0x302b470d CFPreferencesAppSynchronize + 265
Foundation 0x30151b01 -[NSUserDefaults(NSUserDefaults) synchronize] + 25
MyApp 0x0009df8b -[AppDelegate applicationDidEnterBackground:] (AppDelegate.m:178)
...
MyApp 0x0005344b main (main.m:17)
MyApp 0x000533f8 start + 40
some other thread
...
CoreFoundation 0x302bc13f _CFXPreferencesSetValue + 107
CoreFoundation 0x302bc039 CFPreferencesSetAppValue + 41
Foundation 0x30c76935 -[NSUserDefaults(NSUserDefaults) setObject:forKey:] + 61
MyApp 0x000b2e9d -[AppData parserDidEndDocument:] (AppData.m:1013)
...
Parts of the stack have been cut out and substituted with "..." cause its just too long and irrelevant for the subject. App crashes with message:
* Collection <__NSDictionaryM: 0x15a04ae0> was mutated while being enumerated.
....
Code:
AppDelegate: -> crached thread...
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[[NSUserDefaults standardUserDefaults] synchronize];
}
MyClass: ->second thread:
-(void)parserDidEndDocument:(NSXMLParser *)parser {
...
[[NSUserDefaults standardUserDefaults] setObject:arr forKey:#"savedStations"];
[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:#"lastUpdateDate"];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"alreadyLoaded"];
...
}
I have this crash in couple of other cases, it always includes some writing to user defaults in one thread and synchronizeing in other thread that crashes.. If anyone has some other explanation I would be very greatfull...
The NSUserDefaults class is thread-safe.
(c) https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/index.html
nsuserdefaults in not thread safe . Please check apple documentation if it not discuss about thread safe for any ios terms then it is not thread safe....
I'm occasionally getting this crash, which is very hard to reproduce:
0 CoreFoundation 0x39ff73e2 __exceptionPreprocess + 158
1 libobjc.A.dylib 0x3905095e objc_exception_throw + 26
2 CoreFoundation 0x39ffaf2c -[NSObject(NSObject) doesNotRecognizeSelector:] + 180
3 CoreFoundation 0x39ff9648 ___forwarding___ + 388
4 CoreFoundation 0x39f51204 _CF_forwarding_prep_0 + 20
5 Foundation 0x32914bec -[NSDictionary(NSKeyValueCoding) valueForKey:] + 28
6 MyAppName 0x00032112 -[myViewController stopPlayersWithVolume:] (myViewController.m:151)
From this code:
- (void)stopPlayersWithVolume:(double)volume
{
for (NSString *file in players)
{
AVAudioPlayer *player = [players valueForKey:file];
if (player.volume == volume || volume == 0)
[player stop];
}
}
players is an NSMutableDictionary property, accessed without self. because I don't believe it's needed with ARC. The keys are filenames (e.g. "mysound.mp3") and the values are AVAudioPlayer objects.
Is the stack trace saying that the parameter file I'm passing to [NSMutableDictionary valueForKey] is not actually an NSString, and hence the unrecognised selector? It is always an NSString in the debugger, as you'd expect as it comes from a fast enumeration through the dictionary, but the crash never occurs in the debugger.
My only thought is that there's a threading issue corrupting the dictionary. The code above is being fired by an NSTimer but that's just a message via the run loop, not a separate thread, so I believe there should be no need to worry about cross-thread access?
Any suggestions appreciated. Sorry to just dump this out but I'm stuck.
Edit:
The players dictionary is allocated in viewDidLoad thus:
players = [[NSMutableDictionary alloc] init];
And declared as follows:
#property (retain, nonatomic) NSMutableDictionary *players;
And synthesised as follows:
#synthesize players;
It's likely that your players dictionary or its contents are being deallocated while you're iterating through them. Can you turn on NSZombies and try to reproduce the crash in the debugger? It will give you more information about what object is being deallocated.
The code to allocate the dictionary (and set up the audio stuff) looked like this:
NSError *error = [[NSError alloc] init];
NSArray *names = [fm contentsOfDirectoryAtPath:resourcePath error:&error];
players = [[NSMutableDictionary alloc] init];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error];
[[AVAudioSession sharedInstance] setActive:YES error:&error];
I must have copied and pasted it from somewhere, because that use of NSError is wrong, as far as I know, though hardly likely to cause a problem. I changed the code to this:
NSArray *names = [fm contentsOfDirectoryAtPath:resourcePath error:nil];
players = [[NSMutableDictionary alloc] init];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
And the problem goes away, it appears. Can't be 100% sure but I can reproduce the crash within 10 attempts with the former code and never with the latter. No idea why.
I'm getting a EXC_BAD_ACCESS on NSUserDefaults :
NSUserDefaults *pref = [NSUserDefaults standardUserDefaults];
[pref setObject:oldLogin forKey:#"login"];
[pref setObject:oldMotdepasse forKey:#"pass"];
[pref setObject:#"OK" forKey:#"opening"];
Where oldLogin and oldMotdepasse are UITextField.
I didn't get this error before, it's very strange. The error appears on the first setObject.
Thanks to read me!
EDIT : now I've got another error argh :
-[NSCFString text]: unrecognized selector sent to instance 0x4b3b2d0
2012-01-16 10:32:02.601 emars[60602:b303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString text]: unrecognized selector sent to instance 0x4b3b2d0'
*** Call stack at first throw:
(
0 CoreFoundation 0x00fb75a9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x0110b313 objc_exception_throw + 44
2 CoreFoundation 0x00fb90bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x00f28966 ___forwarding___ + 966
4 CoreFoundation 0x00f28522 _CF_forwarding_prep_0 + 50
5 emars 0x00008ddf -[ThirdViewController connectionDidFinishLoading:] + 932
6 Foundation 0x0006a112 -[NSURLConnection(NSURLConnectionReallyInternal) sendDidFinishLoading] + 108
7 Foundation 0x0006a06b _NSURLConnectionDidFinishLoading + 133
EDIT :
Okay, I used oldLogin as a UITextfield. I just change its type to NSString and delete the .text...
You can't just put a UITextField into NSUserDefaults that won't work. You have to get the string value from the UITextField and put that into NSUserDefaults. [prefs setObject:oldLogion.text forKey:#"login"]
Are you trying to store the text in the text fields? If so then it should be
NSUserDefaults *pref = [NSUserDefaults standardUserDefaults];
[pref setObject:oldLogin.text forKey:#"login"];
[pref setObject:oldMotdepasse.text forKey:#"pass"];
[pref setObject:#"OK" forKey:#"opening"];
from NSUserDefault documentation.
The NSUserDefaults class provides convenience methods for accessing
common types such as floats, doubles, integers, Booleans, and URLs. A
default object must be a property list, that is, an instance of (or
for collections a combination of instances of): NSData, NSString,
NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any
other type of object, you should typically archive it to create an
instance of NSData.
you are trying to store the UITextField.. which is wrong .. So would suggest you to insert the text values of UITextField instead storing the whole object.
There are Two things need to fix in this
for text Field write oldMotdepasse.text and oldLogin.text
At the end also synchnorize it [pref synchronize]
E.g:
NSUserDefaults *pref = [NSUserDefaults standardUserDefaults];
[pref setObject:oldLogin.text forKey:#"login"];
[pref setObject:oldMotdepasse.text forKey:#"pass"];
[pref setObject:#"OK" forKey:#"opening"];
[pref synchronize];
My code is as follows:
NSMutableDictionary *configure = [[NSUserDefaults standardUserDefaults] objectForKey:#"configure"];
if (!configure){
configure = [NSMutableDictionary dictionary];
[configure setValue:[NSMutableDictionary dictionary] forKeyPath:#"select"] ;
[configure setValue:[NSMutableDictionary dictionary] forKeyPath:#"select.around"];
[configure setValue: #"All" forKeyPath:#"select.around.name"];
[[NSUserDefaults standardUserDefaults] setObject:configure forKey:#"configure"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
NSString *keyPath = #"configure.select.around";
NSMutableDictionary *aroundConfigure = [[[NSUserDefaults standardUserDefaults] valueForKeyPath:keyPath] mutableCopy];
[aroundConfigure setObject:#"" forKey:#"name"];
[[NSUserDefaults standardUserDefaults] setValue:aroundConfigure forKeyPath:keyPath];
It's crashing every time with the error below:
** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
*** Call stack at first throw:
(
0 CoreFoundation 0x00daebe9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x00f035c2 objc_exception_throw + 47
2 CoreFoundation 0x00d67628 +[NSException raise:format:arguments:] + 136
3 CoreFoundation 0x00d6759a +[NSException raise:format:] + 58
4 CoreFoundation 0x00dad401 -[__NSCFDictionary setObject:forKey:] + 209
5 Foundation 0x0004b34d -[NSObject(NSKeyValueCoding) setValue:forKeyPath:] + 399
6 Foundation 0x0004b34d -[NSObject(NSKeyValueCoding) setValue:forKeyPath:] + 399
7 Untitled 0x00002429 -[UntitledAppDelegate application:didFinishLaunchingWithOptions:] + 774
8 UIKit 0x002b81fa -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163
9 UIKit 0x002ba55e -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 439
10 UIKit 0x002c4db2 -[UIApplication handleEvent:withNewEvent:] + 1533
11 UIKit 0x002bd202 -[UIApplication sendEvent:] + 71
12 UIKit 0x002c2732 _UIApplicationHandleEvent + 7576
13 GraphicsServices 0x016e4a36 PurpleEventCallback + 1550
14 CoreFoundation 0x00d90064 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
15 CoreFoundation 0x00cf06f7 __CFRunLoopDoSource1 + 215
16 CoreFoundation 0x00ced983 __CFRunLoopRun + 979
17 CoreFoundation 0x00ced240 CFRunLoopRunSpecific + 208
18 CoreFoundation 0x00ced161 CFRunLoopRunInMode + 97
19 UIKit 0x002b9fa8 -[UIApplication _run] + 636
20 UIKit 0x002c642e UIApplicationMain + 1160
21 Untitled 0x00002100 main + 102
22 Untitled 0x00002091 start + 53
)
terminate called after throwing an instance of 'NSException'
I know that setObject:forKey: should used with a mutable dictonary . Is there any problem using KVO with NSUserDefaults? By the way, the platform I use is iPhone.
Your code isn't doing what you think it is doing:
NSMutableDictionary *configure = [[NSUserDefaults standardUserDefaults] objectForKey:#"configure"];
This sets configure to be the value of your standard defaults to the value of the key configure
configure = [NSMutableDictionary dictionary];
This sets configure to a new, empty dictionary, not the one you got from User defaults
[configure setValue:[NSMutableDictionary dictionary] forKeyPath:#"select"] ;
You now put an empty dictionary as the value for the key select
[configure setValue:[NSMutableDictionary dictionary] forKeyPath:#"select.around"];
You are adding another empty dictionary for this key path
[configure setValue: #"All" forKeyPath:#"select.around.name"];
And you are setting a string value for this key path
[[NSUserDefaults standardUserDefaults] setObject:configure forKey:#"configure"];
You are now putting this odd dictionary into NSUserDefaults
[[NSUserDefaults standardUserDefaults] synchronize];
NSString *keyPath = #"configure.select.around";
NSMutableDictionary *aroundConfigure = [[[NSUserDefaults standardUserDefaults] valueForKeyPath:keyPath] mutableCopy];
This is just an empty mutable dictionary
[aroundConfigure setObject:#"" forKey:#"name"];
You are setting an empty string for some key in this dictionary
[[NSUserDefaults standardUserDefaults] setValue:aroundConfigure forKeyPath:keyPath];
And then you set this odd dictionary into the the user defaults.
Which is all very confusing.
What is it that you are trying to do?
Edited to add
There's no point providing code if you've "simplified" it we can't see what it's supposed to do.
Your app is crashing because you are trying to change a key value pair of a NSDictionary which is immutable instead of a NSMutableDictionary. See line 6 of your trace.
Since you've provided "simplified" code - I don't know where you are doing this.
Today i also faced this problem because i am making data in dictionary like this
NSMutableDictionary *Dic =[myMutableAry objectAtIndex:0];
after getting data when i am updating my dic value then getting crash
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary
setObject:forKey:]: mutating method sent to immutable object'
Then i did got solution after a lot of research , so just do one thing
NSMutableDictionary *Dic = [NSMutableDictionary dictionaryWithDictionary:[myMutableAry objectAtIndex:0]];
The way you have used the NSUserDefaults is wrong, NSUserDefaults return a non mutable dictionary. That is the cause of this issue. Therefore, you have to request a mutable object explicitly from NSUserDefaults. Please use the code line below.
NSMutableDictionary *configure = [[[NSUserDefaults standardUserDefaults] objectForKey:#"configure"]mutableCopy];
This work with me.
Thanks Good luck :)
I created this awesome iPad game - clean and fun to play, and people that manage to play it more than once love it.
In some cases, however, it will not launch for the second time.
I can't debug it since it works perfect on my iPad, simulator and on all my friend's iPads.
One customer told me that it works on 32GB but not on 64GB iPads - could this be it?
Any help would be appreciated - this is sinking my ratings (and for a good reason, unfortunately)
Would love to give out promo code to anyone willing to look into this.
Thanks!!
Hanaan
From My AppDelegate, if helps:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.playerName = [[NSUserDefaults standardUserDefaults] objectForKey:#"player_name"];
if(self.playerName == nil){
self.playerName = #"nono";
self.pref_currentPuzzleNumberHintsString = #"";
self.pref_currentPuzzleFinishedSolutionString = #"";
self.pref_currentPlayerMarksString = #"";
self.pref_marksCompleteString = #"";
self.pref_currentPuzzleId = -1;
self.pref_gameInProgress = NO;
self.pref_soundOn = YES;
self.pref_buttonsOnLeft = NO;
self.pref_gameTimerValue = 0;
self.pref_gameSize = 0;
NSNumber *pref_gameInProgress_temp = [NSNumber numberWithInt:0];
NSNumber *pref_soundOn_temp = [NSNumber numberWithInt:1];
NSNumber *pref_buttonsOnLeft_temp = [NSNumber numberWithInt:0];
NSNumber *pref_gameNumber_temp = [NSNumber numberWithInt:self.pref_currentPuzzleId];
NSNumber *pref_gameSize_temp = [NSNumber numberWithInt:self.pref_gameSize];
NSNumber *pref_gameTimer_temp = [NSNumber numberWithInt:self.pref_gameTimerValue];
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
[standardUserDefaults setObject:self.pref_currentPuzzleFinishedSolutionString forKey:#"game_string"];
[standardUserDefaults setObject:self.pref_currentPuzzleNumberHintsString forKey:#"hint_string"];
[standardUserDefaults setObject:self.pref_currentPlayerMarksString forKey:#"solution_string"];
[standardUserDefaults setObject:self.pref_marksCompleteString forKey:#"marks_complete_string"];
[standardUserDefaults setObject:pref_gameNumber_temp forKey:#"game_id"];
[standardUserDefaults setObject:pref_gameSize_temp forKey:#"game_size"];
[standardUserDefaults setObject:pref_gameTimer_temp forKey:#"game_timer_value"];
[standardUserDefaults setObject:pref_gameInProgress_temp forKey:#"game_in_progress"];
[standardUserDefaults setObject:pref_soundOn_temp forKey:#"sound_on"];
[standardUserDefaults setObject:pref_buttonsOnLeft_temp forKey:#"buttons_on_left"];
[standardUserDefaults setObject:self.playerName forKey:#"player_name"];
[[NSUserDefaults standardUserDefaults] synchronize];
[pref_gameInProgress_temp release];
[pref_gameSize_temp release];
[pref_soundOn_temp release];
[pref_gameTimer_temp release];
[pref_gameNumber_temp release];
[pref_buttonsOnLeft_temp release];
}else {
self.pref_currentPlayerMarksString = [[NSUserDefaults standardUserDefaults] objectForKey:#"game_string"];
self.pref_currentPuzzleNumberHintsString = [[NSUserDefaults standardUserDefaults] objectForKey:#"hint_string"];
self.pref_currentPuzzleFinishedSolutionString = [[NSUserDefaults standardUserDefaults] objectForKey:#"solution_string"];
self.pref_marksCompleteString = [[NSUserDefaults standardUserDefaults] objectForKey:#"marks_complete_string"];
self.pref_currentPuzzleId = [[[NSUserDefaults standardUserDefaults] objectForKey:#"game_id"]intValue];
self.pref_gameSize = [[[NSUserDefaults standardUserDefaults] objectForKey:#"game_size"]intValue];
self.pref_gameTimerValue = [[[NSUserDefaults standardUserDefaults] objectForKey:#"game_timer_value"]intValue];
int pref_gameInProgress_temp = [[[NSUserDefaults standardUserDefaults] objectForKey:#"game_in_progress"]intValue];
self.pref_gameInProgress = (pref_gameInProgress_temp == 1);
int pref_soundOn_temp = [[[NSUserDefaults standardUserDefaults] objectForKey:#"sound_on"]intValue];
self.pref_soundOn = (pref_soundOn_temp == 1);
int pref_buttonsOnLeft_temp = [[[NSUserDefaults standardUserDefaults] objectForKey:#"buttons_on_left"]intValue];
self.pref_buttonsOnLeft = (pref_buttonsOnLeft_temp == 1);
//NSLog(#"Saved game: %#",self.pref_currentPlayerMarksString);
}
// Add the view controller's view to the window and display.
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
The log I got from a customer has this:
--
Incident Identifier: 1581089C-C02A-4155-9493-9E42B9AAB37D
CrashReporter Key: a913e5f82c7112b47b354f04909239bff1b39000
Hardware Model: iPad1,1
Process: Nonograms [193]
Path: /var/mobile/Applications/4F03245E-CFB8-4181-B881-859FDAEE18C7/Nonograms.app/Nonograms
Identifier: Nonograms
Version: ??? (???)
Code Type: ARM (Native)
Parent Process: launchd [1]
Date/Time: 2010-08-21 16:31:11.002 +0200
OS Version: iPhone OS 3.2.2 (7B500)
Report Version: 104
SYMBOLIZED:
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x00000000, 0x00000000
Crashed Thread: 0
Thread 0 Crashed:
0 libSystem.B.dylib 0x000790a0 __kill + 8
1 libSystem.B.dylib 0x00079090 kill + 4
2 libSystem.B.dylib 0x00079082 raise + 10
3 libSystem.B.dylib 0x0008d20a abort + 50
4 libstdc++.6.dylib 0x00044a1c __gnu_cxx::__verbose_terminate_handler() + 376
5 libobjc.A.dylib 0x000057c4 _objc_terminate + 104
6 libstdc++.6.dylib 0x00042dee __cxxabiv1::__terminate(void (*)()) + 46
7 libstdc++.6.dylib 0x00042e42 std::terminate() + 10
8 libstdc++.6.dylib 0x00042f12 __cxa_throw + 78
9 libobjc.A.dylib 0x000046a4 objc_exception_throw + 64
10 CoreFoundation 0x00094174 -[NSObject doesNotRecognizeSelector:] + 108
11 CoreFoundation 0x00093afa ___forwarding___ + 482
12 CoreFoundation 0x000306c8 _CF_forwarding_prep_0 + 40
13 Nonograms 0x00003238 0x1000 + 8760
14 UIKit 0x00003e58 -[UIApplication _performInitializationWithURL:payload:] + 336
15 UIKit 0x00003b22 -[UIApplication _runWithURL:payload:launchOrientation:] + 394
16 UIKit 0x0004f8c4 -[UIApplication handleEvent:withNewEvent:] + 1336
17 UIKit 0x0004f242 -[UIApplication sendEvent:] + 38
18 UIKit 0x0004ec8c _UIApplicationHandleEvent + 4772
19 GraphicsServices 0x00003b2c PurpleEventCallback + 660
20 CoreFoundation 0x00022d96 CFRunLoopRunSpecific + 2214
21 CoreFoundation 0x000224da CFRunLoopRunInMode + 42
22 UIKit 0x0000340a -[UIApplication _run] + 342
23 UIKit 0x00001954 UIApplicationMain + 636
24 Nonograms 0x00002538 0x1000 + 5432
25 Nonograms 0x00002508 0x1000 + 5384
You need to find the line of code that frame 13 of your stack trace represents.
I would hope that you used the "Build and Archive" feature of the recent versions of Xcode. In this case, all you would need to do is drag and drop the crash log to the Xcode Organizer. This will "symbolicate" the crash log, meaning that it will convert the addresses to classes and methods.
Once you know the line that caused the error it will (hopefully) be relatively simple to figure out what went wrong. My guess would be memory corruption of some description -- a value you assumed you saved on the first run isn't there or something.
I think some object or UI element of yours is getting released (deallocated), but you expect it to still exist:
http://www.iphonedevsdk.com/forum/iphone-sdk-development/51235-crash-log-help.html
The problem was releasing unowned objects...
[pref_gameInProgress_temp release];
[pref_gameSize_temp release];
[pref_soundOn_temp release];
[pref_gameTimer_temp release];
[pref_gameNumber_temp release];
[pref_buttonsOnLeft_temp release];
I dont know the specifics of the iPad and obj-c development.
However, this looks like memory corruption and/or dangling pointers in some way.
For example, you could be modifying an array beyond its bounds. Double check all your loops and add debug asserts that verify the bounds.
Another possibility is that you could be using pointers to objects that have been deleted, and writing/interpreting this memory has undefined effects. Usually it just crashes.
Or you could have uninitialized pointers.
All of this falls into the category that I like to call The Insanity of Developing Applications in C/C++/etc. Unchecked buffer bounds, manual memory deallocation, and unguarded call stack memory are just nutty ideas w/r to modern application development.