IOS (Swift) How to explore persistent file(s) during debug session? - ios

First post on StackOverflow, after extensively using it for a long time.
I'm building a small app (just to lear swift), and I have troubles with making some data persistent. I use NSCoding to achieve that. The problem is that when saving, the function NSKeyedArchiver.archiveRootObject() return true (so apparently it worked), but when, later, I try to retrieve these saved informations, the result of NSKeyedUnarchiver.unarchiveObjectWithFile() is nil.
Without posting all my code, I was just wondering if it were possible to explore the file in which persistent data are stored during a debug session. That would allow me to check whether I have a problem with the saving or the loading part of the process, and see if the data are indeed stored in the right file.
Thanks,
Lb

Per Apple Documentation, you get a nil with unarchiveObjectWithFile when there is no file at the mentioned path. I would advise to check your file path where you are archiving and saving your object.
As for the debugging, follow this:
Print the file path when you are archiving and saving the object. So in this NSKeyedArchiver.archiveRootObject(myObject, toFile: filePath) print filePath.
Open your terminal app and execute open <filePath> command to open the file path where data is being saved.
Check out if your data file is created in there with right archiving.

Related

Where should I save files

I've a question, not about code, but about a good practice.
I've searched on Google but I didn't find anything.
In my app (iOS) I have the possibility to download a file, but I don't know where I have to store it, for now I put it in the Documents folder, but I'm pretty sure that it's not its place.
If you have the answer, or a link that could explain where I have to store it, it could be helpful.
Thanks !
Apple has a strong opinion about that: https://developer.apple.com/icloud/documentation/data-storage/index.html
In short:
documents and user generated data -> Documents directory
downloaded and/or easily to regenerate -> Caches directory
temporary data -> tmp directory -
The location you use (and maybe properties you set) is important for how the backup works as well.
dont use temp directory to store data.then the path will unknown to user.save it on documents directory using the function called savetophotoalbum in IOS. it will save the datas on the Photos and also only limited space is allocated to an IOS app on your phone.it will last to crash in the future when you try to store lot of data on temp directory

How to correctly configure path for the Realm DB-file (<db_name>.realm) in iOS project?

Sorry for my english.
I have developed a mobile application that needs its own local data store. I chose Realm as the database management system. In the process of studying the Realm documentation I had no problems with the database design, it's normalization, the CRUD-operations and everything that is related directly to the code.
I was confused following. I test my application in the simulator. I did not create the local database. I’ve just done it as it is written in the documentation of Realm. Realm created by itself its database and I did not specify any settings. The location of my file with database is given below:
/Users/macbookpro/Library/Developer/CoreSimulator/Devices//EFECD945-285C-494F-8C1B-950D9AA05147/data/Containers/Data/Application/8D71FF0A-60D2-4875-96BB-36955E80D505/Documents/default.realm.
I quite inconvenient to apply each time this path for the analyzing of records in the database. The file is stored at this path is inaccessible for Realm Browser, because I need root privileges. I have seen that people store their .realm-files in project directory. Answer me please - how can I do it? Would it be the right alternative?
I have repeatedly seen the code, where paths to the database file appeared. For example, here: https://github.com/pietbrauer/CarthageRealmUploadFailureExample/blob/master/Carthage.checkout/realm-cocoa/examples/ios/swift/Migration/AppDelegate.swift
I'm not sure if it's the right direction.
As a result, I want to:
1) have on hand a database file and be able to quickly refer to it;
2) know the algorithm - how to set own path to the Realm-database
file;
3) know what realm configuration must be on a real device, to
ensure security and data integrity.
Thank you very much to all!
When you don't specify a path for the default Realm in your app, Realm will automatically create one named default.realm in the Documents directory of your app. On apps running in the iOS Simulator, this will save the Realm file in the appropriate Simulator folder, but you are correct in that it's not very intuitive to find it.
In response to your questions:
There is a cool utility called SimPholders that lets you inspect the Documents folders of apps in the iOS Simulator. This is the best way to get at any Realm files the Simulator has generated very quickly.
When creating an instance of a Realm object, you can supply a Configuration object to customise it. You can explicitly set the file path of the Realm file by setting the path property of that Configuration object.
iOS supplies an automatic layer of file encryption on disk, that makes files unable to be read when the device is locked. If you want additional security, then it's possible to set the encryptionKey property of a Realm Configuration object to have a Realm itself encrypt that Realm file on disk.
I hope that helped! Let me know if you need any more clarification!
1) and 2) does have very small effect on security and data integrity
3) if you are worry about security of you data, use Realm-level encryption like here

MagicalRecord SQLite file empty

I am having problem reading a file. I'm using MagicalRecord as my CoreData wrapper. I successfully save or update object. With my NSLog I can see it, everything is fine and I can use it in my database. But every time I want to see SQLite file with my application (I'm using Datum LE), file is empty. I cannot access that file directly within my Library folder in my app. I copy that file to my desktop and it is empty. What am I doing wrong? So once more, everything inside my iOS application works fine, I can see records being saved and I can fetch them normally.
You are clearly looking at the wrong file. If your app is saving (I assume, across app restarts), the date is definitely saved.
One way to find out is to NSLog the persistent store URL and check the referenced file.
I believe the issue you are encountering is the new default journaling mode that Core Data uses.
See this article
https://developer.apple.com/library/ios/qa/qa1809/_index.html
Basically your changes are not written to the .sqlite file, but are found in .sqlite-wal. HOWEVER, most SQLite reading apps I have tried blow away the -wal when you open the .sqlite, so good luck.
You could try changing the journaling mode for debugging purposes

Saving xml file on iOS (pugiXml and Cocos2d-x)

Recently I've ran into a big problem with pugiXml (used within cocos2d-x engine).
Shortly, I've made a quiz game (in mentioned Cocos2d-x). I keep my questions (and some other data) in an Xml file. On new game they get parsed and inserted into dictionaries. If a question is answered, a short string indicating the answer (whether it was good or not - Y/N) is inserted into that Xml file (below that particular question). Later, I use this data to show statistics (I count the percentage of questions with good answers - which is counting the amount of Y's divided by the amount of questions, multiplied by 100).
I use:
CCFileUtils::sharedFileUtils()->fullPathForFilename(o_QA);
to get the file and later
pBuffer = CCFileUtils::sharedFileUtils()->getFileData(fullPath.c_str(), "rb", &bufferSize);
to put file into buffer and
pugi::xml_parse_result result = doc.load_buffer(pBuffer,bufferSize);
to parse data and start working on it.
Finally, I save the file with:
doc.save_file(fullPath.c_str());
Android:
It's working very well, although I had to copy the file with questions to /data/data/app/Files/ . Still, It's keeping the changes on many devices.
iOS:
Unfortunately, on iOS it's not working. Data get loaded and parsed (which means, that I can actually play the game), but they are not saved. I've tried moving the files to other folders (started from Resources/Documents, then main Resources folder, Resources/Library/Application Support). It's still not saving the data and I don't know what to do. The result is my statistics not being counted well (it doesn't matter how you answer the questions - all of them are false, because the Xml file is not being updated).
Did anyone run into similar problem?
Can you, please, help me?
I am doing something similar in my own app, using both pugixml and cocos2d-x. So I can confirm this combination works well.
Rather, because on iOS you cannot both read and write the data from and to the app bundle (which is read only), you will need to implement a simple check in the writable document directory - If you a saved file there, load it, if not, load from the app bundle.
So in essence for loading, if your saved filename is "my_save.xml", here is an example flow:
1) Construct a path for your save file in the writable folder by concatenating the writable folder path + your filename. CCFileUtils should have something like getWritablePath() for that.
2) if the file exists in the folder, load it. Otherwise, go to 3).
3) Construct a path to your original data file from the app bundle, using CCFileUtils::sharedFileUtils()->fullPathForFilename(). Load the file from there.
For saving, simply do step 1 and save the file there.

Check if UI(Managed)Document is already in iCloud via URLForUbiquityContainerIdentifier+Path instead of NSMetadataQuery?

I have a quite simple shoebox-style iOS app with 1 single Core Data database (as a UIManagedDocument) and thought about trying to add iCloud support.
I of course have to check if there is already an existing database in the cloud *before creating a new UIManagedDocument at startup*, saving/opening it, etc.
As i already know the filename and that there's either 1 document or no document at all, I didn't really get if I had to
start a NSMetaDataQuery with a predicate for the exact filename
and then get the fileURL from the result (and download it
explicitly?) and open it if there is one, or
just use [[NSFileManager defaultManager] fileExistsAtPath:self.iCloudDBURL]
with iCloudDBURL created from URLForUbiquityContainerIdentifier + appending ? Is this URL only a local one and doesn't check the "real" cloud automatically?
I know the use of UIManagedDocument might not be the "right" way for this kind of app, but I thought it'd easier and I could try..
You need to use the NSMetadataQuery approach.
When using iOS on iCloud, documents don't download automatically-- they only download when you ask for them. Using NSFileManager as you suggest would only tell you if the file existed on the local device. But, the file might exist up in the cloud, not downloaded locally yet. If you use NSMetadataQuery you can find out if the document exists anywhere, even if it's in the cloud and not actually downloaded yet. You can find out about the document if it was created on a different device. This also covers the case where the user deletes and reinstalls the app, but doesn't delete cloud data-- you find out if it exists even though it's not downloaded.
Since you're using UIManagedDocument you shouldn't need to make a specific download call-- it will handle that for you when you open it.

Resources