NSURL get/set ResourceValue exc_breakpoint - iphone

I don't know where to start, I'm really losing my mind so let's jump straight into it.
My app has a file which gets larger while using the app. I do not want it to be backupped in the iCloud and so I use the following part to prevent it:
// load file path
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, TRUE) objectAtIndex:0];
NSURL *dbPath = [NSURL fileURLWithPath:[documentsPath stringByAppendingPathComponent:#"database.db"]];
assert([[NSFileManager defaultManager] fileExistsAtPath:[dbPath path]]);
NSError *error;
[dbPath setResourceValue:[NSNumber numberWithBool:TRUE] forKey:NSURLIsExcludedFromBackupKey error:&error];
This code only works for iOS 5.1 or later, but that is satisfied by the deployment target version. My app is in app store since march this year.
Now the strange thing happens:
I did not work on my app for some months and today I wanted to start the app in simulator. The start went other than expected: I got
"Thread 1: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)"
at
CoreFoundation`CFHash:
[...]
calll 0x2dafa00 ; symbol stub for: getpid
Trace at: http://image-upload.de/file/Tf660h/b341100208.png
StackTrace showed that this occured within [dbPath setResourceValue...].
Although it is stated as a breakpoint I cannot run the app since the marked line.
I did not change anything since my last app store submission and now I am not able to start it. Neither in simulator nor on my devices.
If I try to get the previous flag value with [dbPath getResourceValue...] the same thing happens. I'm trying for hours to understand what happens but no progress.

Related

Writing values to a .plist more than once?

I have an iPhone App in the works, and I have a settings page within the app. I use a .plist to store the settings that the user picks, and then I read the data from the .plist later. This is not the -Info.plist that comes with it when you create the project, it is another plist file. When I tested the settings after coding it, it worked. The setting was able to be read, and it was the correct setting that I used. However, I went back to the settings in the same app-session, and changed the same setting. When I went to the app to see if it read the new setting, it only used the old (first) one. I tried again, but it yielded the same result. I am only able to write the setting once, and I cannot 'rewrite' or 'overwrite' the same setting. I cannot figure out what is wrong for the life of me.
You can't overwrite or write to files in the app bundle itself. If you want to write to a file, you should first copy it to the app's Library or Documents directory, something like this:
NSString *docsDir = [NSSearchPathsForDirectoriesInDomains(NSDocumentsDirectory, NSUserDomainMask) objectAtIndex:0];
NSString *plistFile = #"myplist.plist";
NSString *plistInBundle = [[NSBundle mainBundle] pathForResource:plistFile ofType:nil];
NSString *plistInDocsDir = [docsDir stringByAppendingPathComponent:plistFile];
[[NSFileManager defaultManager] copyItemAtPath:plistInBundle toPath:plistInDocsDir error:NULL];
// now `plistInDocsDir` is (over)writeable
However, for storing preferences of your app, it's better practice to use the NSUserDefaults class:
[[NSUserDefaults standardUserDefaults] setObject:#"Some string" forKey:#"MySettingKey"];
and/or create a Preference Bundle for your app.

sqlite db path in bundle acces?

I want to punt my sqlite db in to a custom bundle and use that bundle in more than one project.
I have created a new target from Mac OS X FrameWork&Library -> Bundle, I have build the target and the I have put my sqlite db in the bundle.
I have added the bundle to my iOS project and try to read the db from it.
Now comes the problem: I can get the bundle and read its identifier but when I try to get the path for db I get null return string.
The code to read db path:
NSBundle *myDbBundle = [NSBundle bundleWithPath:[[NSBundle mainBundle]pathForResource:#"myDbBundle" ofType:#"bundle"]];
NSLog(#"BundleIdentifier:%#",[myDbBundle bundleIdentifier]);
NSString *databasePath = [myDbBundle pathForResource:#"myDbName" ofType:#"sqlite"];
NSLog(#"DataBasePath:%#",databasePath);
Any sugestion, docs or tutorial about this issue are wellcome.
Update:
It seems that I can not load the bundle that is why when I try to read from it I fail.
Code:
NSError *error;
NSLog(#"LoadBundle:%#",[myDbBundle loadAndReturnError:&error]?#"yes":#"no");
NSLog(#"Error:%#",[error localizedDescription]);
So the real problme is how do I create a bundle in witch I place a sqlite db and witch can be read from ios app? To create the bundle I used the xcode template under Mac OS X so I think that I have to change something in the build settings, but I don't know what.
NSString *databasePath = [[NSBundle mainBundle] pathForResource:#"myDbName" ofType:#"sqlite"];
should be good enough to get the path to your myDbName.sqlite inside your main bundle
EDIT:
Okay, here is what I did, first, New File -> Resources -> Settings Bundle, create a new one, name it myDbBundle, then right click on that newly created bundle, add myDbName.sqlite in it, make sure that it's not inside en.lproj. Also, make sure when you create a new bundle, you tick the targets to include it into your current target, since this is not Settings.bundle, you want to include it. Then run you code, it works fine.
and here is the code I use
NSBundle* bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:#"myDbBundle" ofType:#"bundle"]];
NSLog(#"%#", bundle);
NSString* test = [bundle pathForResource:#"myDbName" ofType:#"sqlite"];
NSLog(#"%#", test);
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:[bundle pathForResource:#"Root" ofType:#"plist"]];
NSLog(#"%#", dict);
the NSLog(#"%#", dict); is printing out correct value, which means it's successfully loaded
I haven't done this myself, but this blog seems to be what you are trying to do Universal framework iPhone iOS 2.0
It describes creating a framework that can be used to package up any files and then simply imported into other projects as needed.
Swift 3
let dbname = Bundle.main.path(forResource: "horoscope-release", ofType: "sqlite")!

App data loss from NSDocumentDirectory in iOS 5

When I update from iOS 4+ to iOS 5, I lose all data in my own app. I also upgraded to OSX Lion and Xcode 4. I back up my iPhone in iTunes and was able to get the data using iPhone Backup Extractor.
I save my app data to a file in the following way:
- (NSString *)iouArrayPath
{
// Standard way of getting file path for iOS
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dir = [paths objectAtIndex:0];
NSLog(#"Directory: %#", dir);
return pathInDocumentDirectory(#"IouTableArray.data");
}
- (void)archieveIou
{
NSLog(#"archieveIou");
// Get the path to the document directory
NSString *iouPath = [self iouArrayPath];
// grab the objects to archieve
NSMutableArray *iouTableArray = [iouViewController iouTableArray];
// ARCHIVE DATA
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:iouTableArray forKey:#"IouTableArray"];
[archiver finishEncoding];
[data writeToFile:iouPath atomically:YES];
if([data writeToFile:iouPath atomically:YES]) {
NSLog(#"writeToFile success!");
}
else {
NSLog(#"writeToFile failed");
}
[archiver release];
}
This is what I've tried to understand. I open the project in Xcode 4, I copy the .data file from the backup and paste it to the /iPhone Simulator/5.0/Applications/Some digit/Documents. Theorectically, when the app starts, it will look into that folder and load the .data file if it exists. It does not. However, the app will work fine if I create some test data and save it. It will replace the backup file with the same file name and properly load it when I restart the app.
This makes me wonder if there is some NSCoder/archieving change between XCode3/XCode4 or between iOS4 and iOS5.
Does anyone know what is going on? Once I figure this out, I plan to use the backup data file and copy it to the current app /Document folder. Actually, come to think of it, I am not sure how to do that either. The /Document folder for the app reside within the phone. I'll have to see if I can use iTunes and inject the app with the data. Anyways, first things first! Understand the system.
Thanks!
It turns out that iOS5 installs an older version of the app. Strange but make sure you get all your provisioning squared out.

Xcode: directory file for simulator Iphone

i want to write a string in a file "file.txt": this file in my project (for Iphone) is inside Resources; I try to write a string in this file but it don't work, I show my code.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"file.txt"];
NSError *error;
[outputString writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
I want write in this file with simulator xcode, not with device
I'm not sure if you are able to write in your bundle, but you can in your Documents directory instead as your code does. Why don't you try this?
Use the same code and you will find your file in:
/Users/YOURUSER/Library/Application Support/iPhone Simulator/IOSVERSION/Applications/APPID/Documents/file.txt
This changed with XCode 6 and iOS 6 and this got tricky.
The documents directory are now hidden within:
~/Library/Developer/CoreSimulator/Devices/<some-id>/data/Containers/Data/Application/<some-other-id>
It seems the location is changing at each application start, so it's really hard to track. There is a simple tip I borrowed from this article and that I will include for the lazy ones:
#if TARGET_IPHONE_SIMULATOR
// where are you?
NSLog(#"Documents Directory: %#", [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]);
#endif
Add this for example to your applicationDidFinishLaunching method, should make it easier!
If you want more details, just have a look to the original article
NB: I know the question is old, but well, I found it while searching, so I think adding an updated answer may serve some of us!
The Documents directory for your app in the simulator is located at;
~/Library/Application Support/iPhone Simulator/YOUR-IOS-VERSION/Applications/UNIQUE-KEY-FOR-YOUR-APP/Documents
Stop at a breakpoint anywhere in your app and type "po NSHomeDirectory()" in the debugger. Use Finder's Go > Go To Folder feature to jump directly there.
With the example code that you have here it will not write into your Resources folder, but into the Documents folder of the Simulator, which is actually where you should write on device, but as you mention that you only want to do this on the simulator, you could use
filePath = [[NSBundle mainBundle] bundlePath] stringByAppendingPathComnponent:#"Resources"]
But, don't do this in a shipping app, it will fail.
Paste this in the terminal.
open ~/Library/Application\ Support/iPhone\ Simulator/
In gdb, stop process and paste it, then the location of Documents will be printed.
[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]
po [[[NSFileManager defaultManager] URLsForDirectory:9 inDomains:1] lastObject]
If you are using Xcode 7 and higher follow this:
Documents Directory:
file:///Users/codercat/Library/Developer/CoreSimulator/Devices/YourProjectDict/data/Containers/Data/Application/(sample digit)7F53CFB3-C534-443F-B595-62619BA808F2/Documents/your file located here

Add String Attribute to CoreDataBooks

I've been messing around with CoreDataBooks and trying to add another field to the sqlite file in addition to the current three. I've added the attribute string in the .xcdatamodel, and declared it in the book.h, book.m, and localized file (all without changing the sqlite file). However, these changes never add the field in sqlite, and the app never loads. Each time I am deleting the app in the simulator and performing a build--> clean, but to no avail. I've also tried changing the sqlite file to match the .xcdatamodel but the app still fails to load.
Is this a problem with CoreDataBooks or me? Do I need to version the app before doing this? Doesn't seem like I should have to as long as I'm deleting the app in the simulator.
Anyone know how I can add this forth string attribute (sqlite field) in CoreDataBooks?
Thanks in advance!
I've found such a nice piece of code in CoreDataBooks
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"CoreDataBooks.sqlite"];
/*
Set up the store.
For the sake of illustration, provide a pre-populated default store.
*/
NSFileManager *fileManager = [NSFileManager defaultManager];
// If the expected store doesn't exist, copy the default store.
if (![fileManager fileExistsAtPath:storePath]) {
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:#"CoreDataBooks" ofType:#"sqlite"];
if (defaultStorePath) {
[fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
}
}
in CoreDataBooksAppDelegate.m:154, this means for me that every time apps does not find sqlite file it is copied from bundle where it was not changed by modification of CoreDataBooks.xcdatamodel.
Try to use another approach, or just modify bundled sqlite file.
If the app doesn't load then there might be something wrong with your datamodel. Check the console for error messages.
And you have to decide if you want to use sqlite or core-data. If you want to monitor sqlite files for changes or add fields to sqlite files you should use sqlite and not core-data.
If you want to use core-data you should ignore the sqlite file.
Figured it out. The application WAS creating the new sqlite file, I just needed to find it within the simulator files. Grrrr, so much time wasted when I was doing everything correctly. Lessons learned I guess :)