Clear data base (Sqlite) on device - ios

I used SwiftData to create sqlite database in swift ,data base worked on simulator but when i want run app on real device it's not work and error is there is not such table, how i can solve this problem?
let fileMan = NSFileManager.defaultManager()
if (fileMan.fileExistsAtPath(dbPath)){
if let source = NSBundle.mainBundle().resourcePath?.stringByAppendingPathComponent(databaseStr){
if (fileMan.fileExistsAtPath(source)){
print("SQLiteDB - file \(databaseStr) not found in bundle")
} else {
// var error: NSError?
do {
try fileMan.copyItemAtPath(dbPath, toPath: source )
} catch _ {
}
}
}
}
return dbPath
}

Delete the App from the device and clean your project helps in many cases.
If it still don't work try to open the sqlite database. firefox sqlite-manager
But i think the easiest solution would be to delete the database and create a new one. After the delete you also need to remove the app from your device and simulator.

Related

Why is url.bookmarkData returning nil?

We have an implementation with the UIDocumentPickerViewController that looks something like this:
case .openInitialization:
// Setup UIDocumentPicker.
if #available(iOS 14, *) {
documentsPicker = UIDocumentPickerViewController(forOpeningContentTypes: [
UTType.text,
UTType.utf8PlainText,
UTType.flatRTFD,
UTType.pdf])
} else {
documentsPicker = UIDocumentPickerViewController(documentTypes: [
String(kUTTypeText),
String(kUTTypeUTF8PlainText),
String(kUTTypeFlatRTFD),
String(kUTTypePDF)], in: .open)
}
Everything works great and we can select a document. When we select a document we get a document url but in some cases (especially with one drive) we get issues when we want to turn the url into a bookmark. Following code returns nil:
guard let bookmark = try? url.bookmarkData(options: .minimalBookmark, includingResourceValuesForKeys: nil, relativeTo: nil) else { return }
Do anyone have an idea to why this is happening? Or what we can do to get it to work without returning nil?
Edit:
We've tryed to add try catch and we got following error which doesn't quite help much: Error Domain=NSCocoaErrorDomain Code=260 (file doesn't exist).
Edit 2:
So if I open from archive directly into our app it works no issues at all. But we still need to work from UIDocumentPickerViewController.
Also for some reasons files unlocked this way will just work from UIDocumentPickerViewController afterward.
Files can also be opened from onedrive and from there be opened in another app (ours). But this does't and gives a file does not exist error as well.
Edit 3:
So I've tested and read a ton. I can tell that following will return false for some files picked by documentpicker:
var exist = FileManager.default.fileExists(atPath: url.path)
But again if I open the file just once from iOS archive app it will work perfectly fine afterward. If there just were some way to tell it to update/download like apples does.
Edit 4:
I've made a sample project demonstrating the problem at github .
I answered a similar question here: PDFKit doesn’t work on iPads while works fine on a simulator [iOS, Swift]
Can you check if wrapping your url in a security access scope helps?:
url.startAccessingSecurityScopedResource()
print(FileManager.default.fileExists(atPath: url.path))
url.stopAccessingSecurityScopedResource()
The above should print true. This is because these API's access files outside of the applications sandbox.
See: https://developer.apple.com/documentation/uikit/view_controllers/providing_access_to_directories
Used a technical ticket for apple and they came with a solution :D
NSFileCoordinator().coordinate(readingItemAt: url, options: .withoutChanges, error:&err, byAccessor: { (newURL: URL) -> Void in
do {
let bookmark = try newURL.bookmarkData()
} catch let error {
print("\(error)")
}
})
if let err = err {
print(err.localizedDescription)
}

iCloud files not visible after app reinstall swift

I'm storing files in iCloud as a means of backup. Uploading and downloading files seems to work fine, but if I delete the app on a device and re-install the app on that same device, I no longer see the files that were uploaded to iCloud (even from that device just before deleting the app). The ubiquityIdentityToken is the same from all installs. I'm not trying to sync among devices, just store and retrieve. I can see the files in \settings\icloud\manage storage\ but not by running this code:
func createListOfSQLBaseFilesIniCloudDocumentsDirectory() -> [String]{
let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents")
var iCloudBackupSQLFiles = [String]()
do{
let directoryContents = try FileManager.default.contentsOfDirectory(at: iCloudDocumentsURL!, includingPropertiesForKeys: nil, options: [])
for myFile in directoryContents {
if myFile.pathExtension == "sqlite" {
let fileWithExtension = myFile.lastPathComponent
//backupSQLFiles is an array of full file names - including the extension
iCloudBackupSQLFiles.append(fileWithExtension)
}//if myFile
}//for in
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
}//do catch
return iCloudBackupSQLFiles
}//createListOfSQLBaseFilesIniCloudDocumentsDirectory
Any guidance would be appreciated. Swift 3, iOS 10, Xcode 8
Hard to believe no one else has had this issue. Again, this is for simple file storage and retrieval, not syncing dynamically among devices.
The gist of the issue is that iCloud does not automatically sync cloud files down to a new device. Your code must do that. So if you remove an app from a device (but not from iCloud) and reinstall that same app, the app will not see prior iCloud files. You can add new ones and see them with the code above, but you are really just seeing the local ubiquitous container copy. To see previous items you need to perform a metadataQuery on iCloud, parse the filenames of the files of interest from the metadataQuery results and then run
startDownloadingUbiquitousItem(at:) on each file. For example, make an array of files in iCloud from the metadataQuery results and put this do-catch in a for-in loop.
let fileManager = FileManager.default
let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents", isDirectory: true)
let iCloudDocumentToCheckURL = iCloudDocumentsURL?.appendingPathComponent(whateverFileName, isDirectory: false)
do {
try fileManager.startDownloadingUbiquitousItem(at: iCloudDocumentToCheckURL!)
print("tested file: \(whateverFileName)")
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
}//do catch

SetUbiquitous showing 'file already exists' for file that doesn't

In AppDelegate.swift, on first launch, the intent is to place some sample docs in the local Documents folder, or in the iCloud Documents folder if iCloud is enabled.
var templates = NSBundle.mainBundle().pathsForResourcesOfType(AppDelegate.myExtension, inDirectory: "Templates")
dispatch_async(appDelegateQueue) {
self.ubiquityURL = NSFileManager.defaultManager().URLForUbiquityContainerIdentifier(nil)
if self.ubiquityURL != nil && templates.count != 0 {
// Move sample documents from Templates to iCloud directory on initial launch
for template in templates {
let tempurl = NSURL(fileURLWithPath: template)
let title = tempurl.URLByDeletingPathExtension?.lastPathComponent
let ubiquitousDestinationURL = self.ubiquityURL?.URLByAppendingPathComponent(title!).URLByAppendingPathExtension(AppDelegate.myExtension)
// let exists = NSFileManager().isUbiquitousItemAtURL(ubiquitousDestinationURL!)
do {
try NSFileManager.defaultManager().setUbiquitous(true, itemAtURL: tempurl, destinationURL: ubiquitousDestinationURL!)
}
catch let error as NSError {
print("Failed to move file \(title!) to iCloud: \(error)")
}
}
}
return
}
Before running this, I delete the app from the device and make sure no doc of that name is in iCloud. On first launch, without iCloud, the sample docs copy properly into the local Documents folder. With iCloud, this code runs, and the setUbiquitous call results in an error that says the file already exists. The commented call to isUbiquitousItemAtURL also returns true.
What might be making these calls register that a file exists that I'm pretty sure doesn't? Thank you!
The file already exists, so just replace it
The primary solution...in all the trial and error, I'd forgotten to put "Documents" back in the url. Should be:
let ubiquitousDestinationURL = self.ubiquityURL?.URLByAppendingPathComponent("Documents").URLByAppendingPathComponent(title!).URLByAppendingPathExtension(AppDelegate.myExtension)
Without that, wrote the file to the wrong directory, and so I couldn't see it by normal means.

Will images be removed from within the local filesystem on update in iOS?

I am saving images captured from the camera within the local sandbox (filesystem) and store the filepath within my app to show the images (using Swift). I see that if I hit play in XCode, the images will be removed (which is ok)
Now I wonder what would happen if I submit this to the app store, the user saves images and I will update the app later on. Will the images will be removed as well?
To store the image, I use this function..
func saveImageLocally(imageData:NSData!) -> String{
let time = NSDate().timeIntervalSince1970
let fileManager = NSFileManager.defaultManager()
let dir = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0].stringByAppendingPathComponent(subDirForImage) as String
if !fileManager.fileExistsAtPath(dir) {
var error: NSError?
if !fileManager.createDirectoryAtPath(dir, withIntermediateDirectories: true, attributes: nil, error: &error) {
println("Unable to create directory: \(error)")
return ""
}
}
let path = dir.stringByAppendingPathComponent("IMAGENAME\(Int(time)).png")
var error: NSError?
if !imageData.writeToFile(path, options: NSDataWritingOptions.DataWritingAtomic, error: &error) {
println("error writing file: \(error)")
return ""
}
return path
}
Anything you store in your documents folder will persist through app updates providing you keep the same app ID and increment the version number.
Though it is worth noting that the full path to the app sandbox will be different (there will be a new sandbox for the update and the old data copied into it), so make sure you are only accessing resources by storing relative paths etc and are not storing full paths to images and expecting them to resolve after an update.

Using an existing SQLite database in MagicalRecord (swift)

I want my iOS swift app to preload existing sqlite file in MagicalRecord.
With reference to this, and others,
add sqlite, sqlite-shm, sqlite-wal file to my project, wrote some code in didFinishLaunchingWithOption like this.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// copy initial sqlite file to application directory
let preloadSQLiteURL:NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("myData", ofType: "sqlite")!)
let preloadShmURL:NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("myData", ofType: "sqlite-shm")!)
let preloadWalURL:NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("myData", ofType: "sqlite-wal")!)
let storeSQLiteURL:NSURL = NSPersistentStore.MR_urlForStoreName("myData.sqlite")
let storeShmURL:NSURL = NSPersistentStore.MR_urlForStoreName("myData.sqlite-shm")
let storeWalURL:NSURL = NSPersistentStore.MR_urlForStoreName("myData.sqlite-wal")
if !NSFileManager.defaultManager().copyItemAtURL(preloadSQLiteURL, toURL: storeSQLiteURL, error:&err) {
println("failed to copy sqlite file.")
}
if !NSFileManager.defaultManager().copyItemAtURL(preloadShmURL, toURL: storeShmURL, error:&err) {
println("failed to copy shm file.")
}
if !NSFileManager.defaultManager().copyItemAtURL(preloadWalURL, toURL: storeWalURL, error:&err) {
println("failed to copy wal file.")
}
MagicalRecord.setupCoreDataStackWithAutoMigratingSqliteStoreNamed("myData.sqlite")
return true
}
but copyItemAtURL all fails.
value of paths are these.
preloadSQLiteURL = file:///var/mobile/Applications/XXX/myApp.app/myData.sqlite
preloadShmURL = file:///var/mobile/Applications/XXX/myApp.app/myData.sqlite-shm
preloadWalURL = file:///var/mobile/Applications/XXX/myApp.app/myData.sqlite-wal
storeSQLiteURL = file:///var/mobile/Applications/XXX/Documents/myData.sqlite
storeShmURL = file:///var/mobile/Applications/XXX/Documents/myData.sqlite-shm
storeWalURL = file:///var/mobile/Applications/XXX/Documents/myData.sqlite-wal
my environment is Xcode6 beta7, iOS7.1.3.
Does anyone please help me? What should I do?
Any advice appreciated. Thanks in advance.
As a result, self-resolved.
NSError shows "The Operation couldn't be completed. (Cocoa error 516)"
Cocoa error 516 is "NSFileWriteFileExistsError" means "You can’t move a file to a place where a file already exists."
so, I corrected my code in this way.
let fileManager = NSFileManager.defaulManager()
let preloadSQLiteURL:NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("myData", ofType: "sqlite")!)
let storeSQLiteURL:NSURL = NSPersistentStore.MR_urlForStoreName("myData.sqlite")
if fileManager.fileExistsAtPath(storeSQLiteURL.path!) {
// file already exists, delete it and try again.
fileManager.removeItemAtURL(storeSQLiteURL, error:&err)
}
fileManager.copyItemAtURL(preloadSQLiteURL, toURL:storeSQLiteURL, error:nil)
and then, copyItemAtURL successfully completed and sqlite file takes effect.
While this is a poorly worded question, I'm assuming you want to load a SQLite database file from the app bundle into the user's documents directory so you can start with that data and then update it from there.
You're on the correct path, however, rather than copying all 3 files, when you create the default data store file, set your journal_mode to "DELETE" using the NSSQLitePragmasOption:
NSDictionary *options = #{NSSQLitePragmasOption: #{#"journal_mode": #"DELETE"}}
using this set of options when you add a persistent store to a coordinator when you're creating your default data set will only create a single SQLite file. From there, it'll be easier to copy only a single file over.
I also noticed in your code that you're copying myData.sqlite, but you're trying to load "acData.sqlite". Are you trying to load a file that isn't there?

Resources