I'm writing a game write now which involves saving highscores and basic data such as "soundeffects on" and "music on" onto a plist file.
However, when in the future, I need to update my game and upload a new version of the app onto users' iphones/ipods, how will the highscores be retained? Is there a way to save specific plist files while overwriting others? Thanks in advance!
EDIT:
Is there any way to overwrite PART of a plist or merge an existing plist with a new one?
If you're putting these plists in the documents directory, there's nothing further you need to do. These files are all retained when your app is upgraded. You get the documents directory like this:
+ (NSString*) documentsPath
{
NSArray* sysPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
return [sysPaths objectAtIndex:0];
}
Related
I have an iOS app in the app store that can download relatively large files that need to stay on the device for offline use. Those files are currently stored in the app's Documents folder but I'm just now reading that the Documents folder is backed up and should really only be used for user-generated content. This Apple technical Q&A states that the NSURLIsExcludedFromBackupKey should be set to prevent backup. This states that an app's /Library/Caches is the right place to put these kinds of files although further reading suggests that the folder may be cleared when the device is low on storage which is unacceptable for this app. I believe /Library/Application Support/ is then the best location for them -- does this sound right?
Unfortunately, this mistake got through the app review process. What are some best practices for fixing this now that people are using the app and already have some files persisted to the Documents folder and to their backups? It seems I need to move all the existing files and set their NSURLIsExcludedFromBackupKey on app update. How do I guarantee that this is done exactly once and that it isn't interrupted? Is moving the files out of the Documents folder important or could I leave them there? Will changing the files' backup status remove them from existing backups?
I'm using Swift 2.1.1 and targeting iOS 8.0+.
As stated in the technical Q&A, you best bet could be create a subdirectory in the Documents, and exclude that subdirectory once.
I don't believe you can write a 'do it once and be sure it is done' routine, since you can't guarantee your app doesn't crash while it is running. You certainly could set a completion flag when you are sure it is done so that once it is done you don't have to run it again.
Exclude your directory from backup, not the individual files.
From Xcode:
You can use this property to exclude cache and other app support files which are not needed in a backup. Some operations commonly made to user documents cause this property to be reset to false; consequently, do not use this property on user documents.
Here is the strategy I have used with good results
(sorry, its in objective-c -- I'm not a swift guy. Hopefully it will give you the idea):
- (BOOL)moveAllFiles{
// Searches through the documents directory for all files ending in .data
BOOL success = true;
NSString *myNewLocation = #"/store/my/files/here/now";
// Get the documents directory
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [documentDirectories objectAtIndex:0];
// Get all files ending in .data (whatever your file type is)
NSArray *dataFilesArray = [NSArray arrayWithArray:[NSBundle pathsForResourcesOfType:#"data" inDirectory:documentDirectory]];
// If you have multiple resource types, use this line once each for each resource type, then append the arrays.
// Iterate the found files
NSString *fileName = [NSString string];
for (int i=0; i<[dataFilesArray count]; i++) {
fileName = [[dataFilesArray objectAtIndex:i] lastPathComponent];
// Move file, set success to false if unsuccessful move
if (![[NSFileManager defaultManager] moveItemAtPath:[dataFilesArray objectAtIndex:i]
toPath:[myNewLocation stringByAppendingPathComponent:fileName]
error:nil]) {
success = false; // Something went wrong
}
}
return success;
}
Now use the value of success to set a key in the user defaults file. Check for that key on startup. If it is false (or absent), run this routine (again).
This example is with file paths. You can do the same thing with file URLs if you wish.
Im new to core data, Created one model and saved some data in my simulator and opened the .sqlite folder which will contain my data.
Now i done the same thing in my iPad with different data
How to see that .Sqlite file, where its stored… in iPad
Can I copy Same data in another iPad, I mean with out entering all data again ….
Thanks …
You can get your app's container when you attach you device to Xcode.
Windows->Devices->Your App->Click the small setting button->Select download container.
Show the content of your appdata you saved, you will see the .sqlite file in the folder.
In terms of browsing the data, you have several choices.
Here is a discussion about good tool for browsing core data.
Is there a good Core Data browsing tool out there?
In this case I use DB Browser, it works fine.
Could you explain more why you want to do that?
Hope it helps :)
Yes, you can by storing your data files in "Documents" folder, whose path is:
- (NSString *)pathToDocumentFolder
{
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES);
if( [paths count] < 1 )
return nil;
return [paths objectAtIndex:0];
}
I have created a plist on XCode that will have a few values that I can't insert manually. So I want to add this values programmatically at development time. But it seems that I can only read the plist I can not save a plist that is on the App bundle, which makes sense at runtime.. When I will distribute my app I want everyone to have this plist file that's why I am not saving on documents or cache. How can I achieve what I want?
From http://www.karelia.com/cocoa_legacy/Foundation_Categories/NSFileManager__Get_.m (pasted below) you can build a path within the user's personal library with the -(NSString *) pathFromUserLibraryPath:(NSString *)inSubPath method found there.
For example, NSString *editedPlist = [self pathFromUserLibraryPath:#"my.plist"]; gets you the name of the modified plist within the user's library (even if that plist doesn't exist yet).
How you read/write it is according to what kind of plist you have, but you could read it into a dictionary with:
NSMutableDictionary *thePlist= [[NSMutableDictionary alloc] initWithContentsOfFile:editedPlist ];
If you are unable to read, easily detected by, for example [thePlist count] == 0, then you would instead call the same initWithContentsOfFile: initializer with a path to the template within your bundle, but you would then write the plist out to the editedPlist path so it appears in the user directory.
Here is the utility method I referenced above:
/*
NSFileManager: Get the path within the user's Library directory
Original Source: <http://cocoa.karelia.com/Foundation_Categories/NSFileManager__Get_.m>
(See copyright notice at <http://cocoa.karelia.com>)
*/
/*" Return the path in the user library path of the given sub-path. In other words, if given inSubPath is "foo", the path returned will be /Users/myUser/Library/foo
"*/
- (NSString *) pathFromUserLibraryPath:(NSString *)inSubPath
{
NSArray *domains = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,NSUserDomainMask,YES);
NSString *baseDir= [domains objectAtIndex:0];
NSString *result = [baseDir stringByAppendingPathComponent:inSubPath];
return result;
}
What I would suggest is writing code that checks for the plist in the documents directory at start. If it's there, read it into memory.
If you don't find the file in the documents directory, read it from the app bundle instead. Then drop into the code that uses it from memory and writes the changed version to the documents directory.
Remember that all the objects you read from a plist file are read as immutable, even if you wrote mutable objects into the file. You have to write code that makes mutable copies of anything that you want to change. (And have to implement a mutable deep copy if you have complex structures like arrays of dictionaries that in turn contain arrays of strings.)
I am creating a quiz app for iPhone. I store all the questions in an NSArray that is loaded from a .xml file every time the app is opened. That file will be the same accross all "instances" of the app, and it will never be changed by the user.
I could hard-code all the questions with code, but I found it more elegant to have it in a file that is easily edited by any text editor.
But how do I give each app "instance" of the app a copy of that file? That file should be bundled along with the rest of the application files.
This is the code I use so far (in app delegate).
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *path = documentPaths[0];
path = [path stringByAppendingPathComponent:#"questions.archive"];
NSArray *fileQuestions = [[NSArray alloc] initWithContentsOfFile:path];
if (!fileQuestions)
{
// Code to add three default questions…
[fileQuestions writeToFile:path
atomically:YES];
}
// And here the "file questions" are transformed to instances of my question class
No need to try to store the file in Documents directory. Just store it right there in the app bundle itself. This works exactly like an image file, a sound file, or any other resource. Make the file part of the project; make sure it is part of the app target, so that it will be copied into the app bundle as part of the build process. In the running app, get its path with [[NSBundle mainBundle] pathForResource:ofType:], and read it as you would any file of this type.
I want to handle files in my iOS App.
My app should create a file with a custom suffix (e.g. file.mysuff) and save it to the device so I'll be able to copy it using iTunes File Sharing.
Then I want to be able to attach that file to a new mail.
When the receiver opens the document, mail should launch my app and handle that file.
Are there good tutorials on that topic?
I'm still quite new to cocoa / cocoa touch so it should be easy to my.
Is maybe a wrapper out there that I could implement so I just have to code something like
[self [saveMyFile path:[NSURL] contents:[NSString]]]??
Thanks for help!
Greets, J.
This is one example of how you can save the file to documents on the iPhone to use later. This stores a dictionary from a list, changes a value and then writes the updates dictionary back to the file specified. Let me know if this is what you were looking for.
//user document directory and instantiate dictionary
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *plistFilePathInDocumentsDirectory = [documentsDirectoryPath stringByAppendingPathComponent:#"YourFile"];
NSMutableDictionary *yourList= [[NSMutableDictionary alloc] initWithContentsOfFile:plistFilePathInDocumentsDirectory];
//save the new information to the plist in the user documents directory
[yourList setObject:someObject forKey:someKey];
[yourList writeToFile:plistFilePathInDocumentsDirectory atomically:YES];