Sqlite error in while appending file - swift

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!).

Related

Swift Filemanager fails to create temporary directory

This Code:
let csvString = self.generateCSV()
let tmpURL = try FileManager.default.url(for: .itemReplacementDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true)
let tempFileUrl = tmpURL.appendingPathComponent("App-DigiAufklaerung-\(self.formatDateToPrecision(Date())).csv")
let data = csvString.data(using: .utf8)
try data?.write(to: tempFileUrl,
options: .atomic)
self.csvFile = tempFileUrl
(I thought) should create a tmp file, from which i can then share the cdv through AirDrop, but the creation of the tmpDir fails, what am i doing wrong here?
This error message was printed several times:
CFURLSetTemporaryResourcePropertyForKey failed because it was passed an URL which has no scheme

create plist and copy it to folder MacOS Swift

I have been racking my brain on how to create and write a plist to a certain Folder Directory in MacOS. In my case to the LaunchDaemons folder in /Library. I know how to create the plist but its the writing to the LaunchDaemons folder that I am having issues with. This code below from my understanding is for the sandbox but how do I do it outside of the sandbox? Cheers
let fileManager = FileManager.default
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let path = documentDirectory.appending("test.plist")
I have added the code with the help I have received and have no errors but it is not writing anything to the folder. Here is the code:
let libraryDirectory = try! FileManager.default.url(for: .libraryDirectory, in: .localDomainMask, appropriateFor: nil, create: false)
let launchDaemonsFolder = libraryDirectory.appendingPathComponent("LaunchDaemons/test.plist")
if FileManager.default.fileExists(atPath: launchDaemonsFolder.path) {
print(launchDaemonsFolder)
let plistDictionary : [String: Any] = [
"ExitTimeOut": 600,
"Label": "BOOT.SHUTDOWN.SERVICE",
"ProgramArguments": ["/test.sh"] as Array,
"RunAtLoad": false,
"WorkingDirectory": "/"
]
let dictionaryResult = NSDictionary(dictionary: plistDictionary)
let fileWritten = dictionaryResult.write(to: launchDaemonsFolder, atomically: true)
print("is the file created: \(fileWritten)")
} else {
print("File Exists")
}
First of all NSSearchPathForDirectoriesInDomains is outdated, it's highly recommended to use the URL related API anyway.
This code creates an URL pointing to /Library/LaunchDaemons
let libraryDirectory = try! FileManager.default.url(for: .libraryDirectory, in: .localDomainMask, appropriateFor: nil, create: false)
let launchDaemonsFolder = libraryDirectory.appendingPathComponent("LaunchDaemons")

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)
}

Swift 4 alternative if let

I have this code, it checks if a file exists in the document directory, if it does it used this to set up the data for the controller, if it doesn't it uses a file supplier in the bundle, and if also that fails it set up an empty view controller.
Is there a way to conditionally set the url variable so that I can write the parse(fromFile:) method once instead of in an if else? The most intuitive way would appear to be if let url = something || let url = somethingElse then perform in the parse(fromFile: url) in the brackets, but it appears that it's not possible with swift.
if let url = try? FileManager().url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true).appendingPathComponent("database.json") {
parse(fromFile: url)
} else if let url = Bundle.main.url(forResource: "database", withExtension: "json") {
parse(fromFile: url)
} else {
setUpWithNothing()
}
I would recommend to split the code into several steps:
let documentsUrl = try! FileManager.default.url(
for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true
)
The documents directory should always exists therefore I am not too worried about using try!. However, if you worry, you should solve that special case separately, e.g. using:
guard let documentUrl = try? ... else {
setUpWithNothing()
return
}
Then:
let fileUrl = documentUrl.appendingPathComponent("database.json")
This call never fails, it doesn't check the existence of the file. You need to check existence explicitly:
let fileExists = FileManager.default.fileExists(atPath: fileUrl.path)
let defaultUrl = Bundle.main.url(forResource: "database", withExtension: "json")
let databaseUrl = fileExists ? fileUrl : defaultUrl!
Again, you shouldn't worry about the existence of the file in your bundle, if you know it's there and simply call:
parse(fromFile: databaseUrl)
However, if you want to be extra careful, just remove the ! and use:
if let databaseUrl = fileExists ? fileUrl : defaultUrl {
parse(fromFile: databaseUrl)
} else {
setUpWithNothing()
}
You can use the nil-coalescing operator (??):
If the expression with FileManager returns nil (by throwing, thanks to the try?), then Bundle.main.url(...) will be used instead.
If that is also nil, then the conditional binding will fail entirely, and the else block will be run setUpWithNothing().
if let url = (try? FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true
).appendingPathComponent("database.json"))
?? Bundle.main.url(forResource: "database", withExtension: "json") {
parse(fromFile: url)
} else {
setUpWithNothing()
}
Since you're doing the same thing in the first two cases and something different in the second, this is a good candidate for it's own function:
func databaseFileURL() -> URL? {
if let url = try? FileManager().url(for: .documentDirectory, in: .userDomainMask,
appropriateFor: nil, create: true) {
return url.appendingPathComponent("database.json")
}
else {
return Bundle.main.url(forResource: "database", withExtension: "json")
}
}
and then you can just do
if let url = databaseFileURL() {
parse(fromFile: url)
} else {
setUpWithNothing()
}
It nicely separates concerns and makes it cleaner and clearer at the point of use. And if you need to do anything else with the file you can just call the function rather than copy-pasting the logic.