Adding External Sqlite Database to iOS application using swift - swift

I want to add my own Database named Photos.sqlite to my iOS application. I have the following code to open the database, but is this creating a database named Photos.sqlite, and not using my own?
func createDB() -> OpaquePointer?{
let filePath = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathExtension(path)
var db : OpaquePointer?
guard sqlite3_open(filePath.path, &db) == SQLITE_OK else {
print("error opening database")
sqlite3_close(db)
db = nil
return nil
}
return db
}
I am asking how would I use my own database within the application? Where would I put the file? I did a bit of research and it states the Photos.sqlite must be in documents but I do not think I need this since I will only be reading data from the database, I will not be inserting or updating the database in any way.

Related

Permission error when saving to documentDirectory

I am trying to save favourites to document directory, the code works fine when I run it in simulator however when I build it to my device I am getting the following error.
You don’t have permission to save the file
“Documents.LikedDepartments” in the folder
“F36073C0-AC1E-46CA-BC1E-E03F9F316E1D”.
Also it might be worth noting that when I change use .cachesDirectory instead of .documentDirectory it works fine.
How can I grant write access for the documents directory ?
import Foundation
extension FileManager {
static var documentsDirectory: URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
print(paths)
return paths[0]
}
}
let savePath = FileManager.documentsDirectory.appendingPathExtension("LikedDepartments")
func save() {
let favourites = calculateFavourites()
do {
let data = try JSONEncoder().encode(favourites)
try data.write(to:savePath, options: [.atomic, .completeFileProtection])
} catch {
print("\(error)")
}
}
Cool file extension .LikedDepartments
Use appendingPathComponent instead.
https://developer.apple.com/documentation/foundation/nsstring/1417069-appendingpathcomponent

Empty Core Data Sqlite Database in mail attachment

I am trying to export Core Data Local Sqlite Database from iPhone to System through mail.
I can see .sqlite database as attachment. But it is empty, no data in any table.
I am doing this with below code.
if MFMailComposeViewController.canSendMail(){
let composer = MFMailComposeViewController()
composer.setToRecipients(["test#gmail.com"])
composer.setSubject("Sending Local Database File")
composer.setMessageBody("Hello,\nPlease find the attached local database file in this email.\n and Kindly check it and let us know.", isHTML: false)
composer.mailComposeDelegate = self
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsDirectory.appendingPathComponent("Project.sqlite")
print("Database File URL is - \(fileURL)")
do {
let attachmentData = try Data(contentsOf: fileURL)
composer.addAttachmentData(attachmentData, mimeType: "application/x-sqlite3", fileName: "Project.sqlite")
self.present(composer, animated: true)
} catch {
print(error)
}
}
Or is there any way to export core data sqlite database from app other than connecting device to MAC or Any system through cable (except iTunes/XCode)?
can we export it directly from app?

Opening a SQLite from bundle using Swift

I have a .sqlite file in my app bundle. I seem to open the file, but I can not access the tables in the file.
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("test.sqlite")
//opening the database
if sqlite3_open(fileURL.path, &db) == SQLITE_OK {
print("opening database")
}
let queryString = "SELECT * FROM Table1"
var stmt:OpaquePointer?
//preparing the query
if sqlite3_prepare(db, queryString, -1, &stmt, nil) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing insert: \(errmsg)")
return
}
This gives following error message: "error preparing insert: no such table: Table1"
As I see it, the databse is found and opened, but cannot be accessed. As I see it from other posts at Stackoverflow, this should work
EDIT: I now see that if I misspell the databse name from test.sqlite to ttestt.sqlite, I still get the same error. Meaning the database is not found. What is wrong with this line?
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("test.sqlite")
The solution was to copy the database from the bundle to the documnents directory:
let bundleURL = Bundle.main.url(forResource: "test", withExtension: "sqlite")!
try manager.copyItem(at: bundleURL, to: documentsURL)
rc = sqlite3_open_v2(documentsURL.path, &db, SQLITE_OPEN_READWRITE, nil)

Get all the "*.xxx" files in the document directory in Swift 4

I'm looking over the NSFileManager.h dox in Swift 4 and it seems it changed since I last used it (for the better!).
I'm wondering if contentsOfDirectoryAtURL:includingPropertiesForKeys, url or enumeratorAtURL:includingPropertiesForKeys provides a way to enumerate over a specific type of file, in my case images?
I've looked at the many Swift 2 answers and they all suggest looping and examining the name, and I want to be sure they haven't "fixed" this and I'm simply confused by the API?
Just filter the returned URLs by pathExtension
do {
let documentsURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let docs = try FileManager.default.contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
let images = docs.filter{ $0.pathExtension == "xxx" }
print(images)
} catch {
print(error)
}

Sqlite error in while appending file

I am ne to iOS developer i want to one thing that when i connect Sqlite with Xcode then after appending the code in nsobject class the error comes second line that instance member documents cannot be used type of class name
Here is code-
let documents = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
let fileURL = documents.URLByAppendingPathComponent("test.sqlite")
var db: COpaquePointer = nil
if sqlite3_open(fileURL, &db) == SQLITE_OK {
print("Successfully opened connection to database at \(fileURL)")
return db
} else {
print("Unable to open database. Verify that you created the directory described " +
"in the Getting Started section.")
}
Please resolve my problem
It would appear that you're trying to declare fileURL outside of a method. If this is a property, you can't reference documents like that. So, either make this a local variable of your method, or collapse these two declarations into a single statement:
In Swift 3:
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
.appendingPathComponent("test.sqlite")!
In Swift 2:
let fileURL = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
.URLByAppendingPathComponent("test.sqlite")!
That avoids referencing documents at all.
As an aside, you can't pass fileURL to the sqlite3_open function. You should use fileURL.path (or, in Swift 2, fileURL.path!).