iOS Data protection on core data not working - ios

I am trying to enable the data protection for my core data file. Here is what I did.
Project settings enabled the data protection in capabilities.
Modified persistent store coordinator getter
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
var failureReason = "There was an error creating or loading the application's saved data."
do {
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: [NSSQLitePragmasOption : ["journal_mode" : "DELETE"], NSPersistentStoreFileProtectionKey : NSFileProtectionComplete])
}
Ran the code and installed the app on the device.
Downloaded the app container and opened package content, and could see the .sqlite file
Now locked the device
Kept it for 10 sec, and then downloaded the app container again for the same app.
7.Opened the package content, I can still see the package content and sqlite file :(
I am using free provisioning profile if that helps in anyway.
What mistake am I doing here?? Why is this .sqlite file is not encrypted?
Please help. Thanks in advance.

Because the computer your device is connected to is a Trusted Computer, it can read your app's container even if the device is locked. I know of two options to test if the sqlite file is encrypted:
1) Jailbreak your device. Then SSH into your device, and try to read the sqlite file (ie. 'cat sqlite_file') when the device is locked. If the file is encrypted, you won't be able to read it.
2) You can inspect the attributes on the sqlite file and make sure the NSFileProtectionKey attribute is appropriately set:
let attributes = try? FileManager.default.attributesOfItem(atPath: sqlite_path)
print(attributes)

Related

Inconsistent crash while trying to add a persistent store in CoreData

I am facing a weird crash that happens on some devices, reported by Firebase and Xcode crashes history, while migrating to a new CoreData model. The only chan and adding 3 new propertiesge needed to be done is to remove a couple of properties in one table/object. I have regenerated the classes and upgraded the model version as it doesn't need but a light weight migration.
And all I am getting is:
crash_info_entry_0
Fatal error: Error migrating store: Error Domain=NSCocoaErrorDomain Code=256
"The file "<FileName>.sqlite" couldn't be opened." UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/45859729-F07E-4006-8742-3B53DF6D1CE9/Documents/<FileName>.sqlite, NSSQLiteErrorDomain=23}: file /ProjectName/Repo/Models/Storage/CoreData/CoreDataEngine.swift, line 137
I am using Swift 4.2.
SQLite error 23 is an authorization error. This probably means that you have data protection turned on in your app's capabilities (or else you're using NSPersistentStoreFileProtectionKey when loading the persistent store), and you're trying to access the persistent store when the file is not accessible (e.g. when the screen is locked).
If you can turn off data protection, that would solve the problem. If you need data protection, you need to use data protection related methods in your app delegate to detect when your app can safely access the file.

iOS - App Files not deleted when app is deleted

We ran into strange behavior.
Install the app from test flight
App creates a local sqlite database in the NSDocumentDirectory
User deletes the app
User reinstalls the app again from test flight (newer version)
App sees old database in the app
This has happened several times. And my understanding was that apps are supposed to delete everything with it once they are deleted. Yet intermittently this happens.
Anyone seen this issue before?
I assume this is caused by iCloud backup and restore functionality. If you don't set the exclude back-up key explicitly, the iOS will automatically back-up your files in the document directory. In your case, the previous database was backed-up in the iCloud and when you re-installed the app, the iCloud restored the database file. That's the reason why you are seeing the old data. If you don't need to back up your app's database file use the following code:
Swift 4:
do
{
var resourceValues = URLResourceValues()
resourceValues.isExcludedFromBackup = true
try databaseURL.setResourceValues(resourceValues)
}
catch
{
print(error.localizedDescription)
}
Old Version Code
do
{
// Database URL
try databaseURL.setResourceValue(true, forKey:NSURLIsExcludedFromBackupKey)
}
catch let error as NSError
{
print("Error excluding \(URL.lastPathComponent) from backup \(error)");
}
Reference: How do I prevent files from being backed up to iCloud and iTunes?

Multiple firebase apps, crash reporting configuration issue

I have configured multiple firebase databases in my single iOS app.
here is the code in my AppDelegate, that selects which firebase db I have to choose at run-time
func initFirebase(){
// Check the Flag which Firebase to connect with
if (UserDefaultsManager().getFirebaseConfiguration()){
let resource = UserDefaultsManager.env_firebase?.value(forKey: "resource") as! String
print("resource \(resource)")
let filePath = Bundle.main.path(forResource: resource, ofType:"plist")
let options = FirebaseOptions(contentsOfFile:filePath!)
FirebaseApp.configure(options: options!)
}
}
This is all working fine.
Issue is with crash reporting, I have to make the firebase crash reporting dynamic too.
Right now I have configured my firebase crash reporting with jBackend-genetech-dev-crash-reporting.json , here is my crash reporting shell script.
# Replace this with the GOOGLE_APP_ID from your GoogleService-Info.plist (its my genetech-dev firebase service account actually) file
GOOGLE_APP_ID=1:740631780656:ios:ddccc74c2f726b3a
# Replace the /Path/To/ServiceAccount.json with the path to the key you just downloaded
"${PODS_ROOT}"/FirebaseCrash/upload-sym "${SRCROOT}/JamesApp/jBackend-genetech-dev-crash-reporting.json"
So When I connect my app to the firebase db with configuration defined in service account GoogleService-Info.plist its working flawlessly i.e I am getting the crash reports with the exact line number of the crash. here is the screenshot.
But whenever I connect with other firebase accounts example GoogleService-Info-mh6-prod.plist, I am getting the crash reports in this case too but with no Line number, see screenshot below.
More Info
Am I testing on real device? Yes
Is bitcode support disabled in my project? Yes
Question:
How to make my crash reporting script dynamic in my case.
I have seen this iOS Firebase Crash Reporting - Error running build script , i.e making the script dynamic depending upon the app configuration variable i.e release/debug. but my scenario is different, my app select the firebase database depending on the app's System settings bundle. seen screenshot below.

Logging data on device and retrieving the log

On a debug build in Xcode, regardless of whether I am using the simulator or an actual device, NSLog, printf, fprintf assert and NSAssert statements come out on the console
If I now run a release build on the device (say I send a test flight build and big it up on my iPhone; this will be a release build), which of these (if any) are getting recorded?
And how do I retrieve the log?
Does NSLog actually output something on release build? What is the determining factor? Whether it is writing to stdout or stderr? is only stderr written to device log? Does this mean I have to use fprintf? Is ANYTHING written to device log? is there even such a thing? If so, how to pick it up?
Could someone clarify the situation?
In Xcode 6.1.1, you can view the NSLog output by doing the following. However, I'm not sure if it lets you see logs from too far back in time. I've only seen it go back up to a couple hours.
In any case, here are the steps:
In Xcode, go to Window -> Devices.
Select your device in the left panel.
Click the little arrow as shown in the screenshot below.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName =[NSString stringWithFormat:#"%#.log",[NSDate date]];
NSString *logFilePath = [documentsDirectory stringByAppendingPathComponent:fileName];
freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
Just add this block of code in application:didFinishLaunchingWithOptions method in the app delegate file and it will create a log file in app document directory on iPhone which logs all console log events. You need to import this file from iTunes to see all console events.
Note: In the .plist file make sure that Application supports iTunes file sharing is exists and is set to YES so that you can access through iTunes.
To get Logfiles :
Launch itunes, after your device has connected select Apps - select your App - in Augument Document you will get your file. You can then save it to your disk
In swift 4.0+, the code of Shyl will changes to,
var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let fileName = "\(Date()).log"
let logFilePath = (documentsDirectory as NSString).appendingPathComponent(fileName)
freopen(logFilePath.cString(using: String.Encoding.ascii)!, "a+", stderr)
all other process are same that explained by Shyl
Just add this block of code in application:didFinishLaunchingWithOptions method in the app delegate file and it will create a log file in app document directory on iPhone which logs all console log events. You need to import this file from iTunes to see all console events.
Note: In the .plist file make sure that Application supports iTunes file sharing exists and is set to YES so that you can access
through iTunes.
To get Logfiles : Launch iTunes, after your device has connected
select Apps - select your App - in Augument Document you will get your
file. You can then save it to your disk
NSLog is written to device log in production release and you can check this by connecting your iPhone to your system and using Organizer. Select your iPhone in the organizer, click Device Logs. You would see all NSLog outputs in the log.
I found this link from APPLE very informative and complete.
It pretty much gives you all the options to see or access logs of the device whether or not they are connected to your dev machine.
https://developer.apple.com/library/ios/qa/qa1747/_index.html
Yes, NSLog outputs on the device. You can see it's outputs with your device connected to your Mac and using Xcode Organizer tool.
If you use Testflight SDK, you can capture all logs with their Remote Logging feature.
I know this is an old thread but you can also have access to the device logs going to:
Settings -> Privacy -> Analytics -> Data
Hope this help
Regards
I think in Xcode 9.3 the device log screen has been moved to a new location.Kindly refer the following link.
Get device logs at runtime in Xcode

Install IPA using itms-services from disk on iOS device [duplicate]

I'm trying to install an iOS app from a plist on the device's filesystem.
NSString *launchNewPlistURL = [NSString stringWithFormat:#"itms-services://?action=download-manifest&url=file://%#",[self saveFilePath]];
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:launchNewPlistURL]];
And I'm prompted with "(null) would like to install {myappname}". Usually (null) is the domain name the plist is coming from, but in this case it's null as it's a local file.
Is there anyway to specify the title in the plist or pass a fake domain name in the url?
Thanks,
Dan
You can use the project MongooseDaemon to create an HTTP local server.
With a domain similar to: http://192.168.xxx.xxx/yourplist.plist to install it.
Anyhow, I think you can't use it with an large IPA. I have tried with my IPA greater than 15MB and it is very, very slow to start the install.
I was in a similar situation, and went through the route of using Mongoose originally, but just today stumbled upon CocoaHttpServer.
With Mongoose, I was only getting about a 20% success rate serving up local plist/IPA files. Sometimes the localhost would like to install dialog never came up, sometimes install started and failed about halfway in, and sometimes it actually worked. Even worse, once an App failed, I had to completely uninstall and reinstall it, so all data was lost. I was never able to successfully "fix" a failed install.
So far, with just about 10-15 minutes of testing, the CocoaHttpServer hasn't failed, yet. I know this is a very small sample size, but my Mongoose success rate was around 10%.
self.httpServer = [[HTTPServer alloc] init];
[self.httpServer setType:#"_http._tcp."];
[self.httpServer setPort:8080];
//This is just a path where I save my IPA and Plist file locally.
//In my case it's /{NSDocumentDirectory}/install/
[self.httpServer setDocumentRoot:[self pathForLocalInstallFiles]];
Then the URL to the plist on the disk:
NSURL *plistUrl = [NSURL URLWithString:#"itms-services://?action=download-manifest&url=http://localhost:8080/appname.plist"];
[[UIApplication sharedApplication] openURL:plistUrl];
Inside the plist, where you have your URL that points to the local IPA file, I had success using either file:// or http://localhost/.

Resources