I try to preload my database in my app (.sqlite, .sqlite-wal and .sqlite-shm), but I can't.
I try this:
func preloadDBData()
{
let sqlitePath = Bundle.main.path(forResource: "leksikonPreload", ofType: "sqlite")
let sqlitePath_shm = Bundle.main.path(forResource: "leksikonPreload", ofType: "sqlite-shm")
let sqlitePath_wal = Bundle.main.path(forResource: "leksikonPreload", ofType: "sqlite-wal")
let URL1 = URL(fileURLWithPath: sqlitePath!)
let URL2 = URL(fileURLWithPath: sqlitePath_shm!)
let URL3 = URL(fileURLWithPath: sqlitePath_wal!)
let URL4 = URL(fileURLWithPath: NSPersistentContainer.defaultDirectoryURL().relativePath + "/leksikonPreload.sqlite")
let URL5 = URL(fileURLWithPath: NSPersistentContainer.defaultDirectoryURL().relativePath + "/leksikonPreload.sqlite-shm")
let URL6 = URL(fileURLWithPath: NSPersistentContainer.defaultDirectoryURL().relativePath + "/leksikonPreload.sqlite-wal")
if !FileManager.default.fileExists(atPath: NSPersistentContainer.defaultDirectoryURL().relativePath + "/leksikonPreload.sqlite") {
// Copy 3 files
do {
try FileManager.default.copyItem(at: URL1, to: URL4)
try FileManager.default.copyItem(at: URL2, to: URL5)
try FileManager.default.copyItem(at: URL3, to: URL6)
print("=======================")
print("FILES COPIED")
print("=======================")
} catch {
print("=======================")
print("ERROR IN COPY OPERATION")
print("=======================")
}
} else {
print("=======================")
print("FILES EXIST")
print("=======================")
}
}
and call preloadDBData() in my appDelegate didFinishLaunchingWithOptions method. Name of my Core Data model: "leksikon", name of my preload data: "leksikonPreload". This func work fine and really write when "FILES COPYED" and "FILES EXIST", but when I try print my data - my array contain 0 elements, but I am sure, that leksikonPreload contains 12 values.
My code of print:
func printData() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest: NSFetchRequest<Word> = Word.fetchRequest()
do
{
let arr = try context.fetch(fetchRequest)
for obj in arr {
print(obj.engValue)
print(obj.rusValue)
print(obj.was)
}
}
catch
{
print(error.localizedDescription)
}
}
I am having the same problem.
I have a preloadedDataBase called: BenedictusCoreData.sqlite
I added it to my project. And modified the AppDelegate:
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "BenedictusCoreData")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
// MARK: - Preload data from my sqlite file.
func preloadDBData() {
let sqlitePath = Bundle.main.path(forResource: "BenedictusCoreData", ofType: "sqlite")
let originURL = URL(fileURLWithPath: sqlitePath!)
let destinationURL = URL(fileURLWithPath: NSPersistentContainer.defaultDirectoryURL().relativePath + "/BenedictusCoreData.sqlite")
if !FileManager.default.fileExists(atPath: NSPersistentContainer.defaultDirectoryURL().relativePath + "/BenedictusCoreData.sqlite") {
// Copy file
do {
try FileManager.default.copyItem(at: originURL, to: destinationURL)
print("=======================")
print("FILE COPIED")
print("=======================")
} catch {
print("=======================")
print("ERROR IN COPY OPERATION")
print("=======================")
}
} else {
print("=======================")
print("FILE EXIST")
print("=======================")
}
}
I copied only the sqlite file because I have no wal and shm files and because I just want to copy the file the first time it is launched and only for reading purposes.
The preloadDBData() function is called in AppDelegate didFinishLaunchingWithOptions. And when launched for the first time says "FILE COPIED". And after it, when launched said "FILE EXIST". So it seems that the file is copied.
The model file in the project is called BenedictusCoreData.xcdatamodeld and the project name is BenedictusCoreData
And in the ViewController I wrote the following:
var encyclicalsArray = [Encyclicals]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
loadItems()
}
func loadItems() {
let request: NSFetchRequest<Encyclicals> = Encyclicals.fetchRequest()
do {
try encyclicalsArray = context.fetch(request)
for encyclical in encyclicalsArray {
print(encyclical.titulo_es!)
print(encyclical.date!)
print(encyclical.idURL!)
}
} catch {
print("Error fetching encyclicals: \(error)")
}
}
And it prints nothing. However, my sqlite preloaded file has three entries within this table.
Related
I want to upload an image to iCloud drive from my ios app. Upto now I have upload the images by saving them locally in iCloud drive in the device and syncing it to the iCloud. here is the code i have tried.
if (!FileManager.default.fileExists(atPath: iCloudDocumentsURL.path, isDirectory: nil)) {
do{
try FileManager.default.createDirectory(at: iCloudDocumentsURL, withIntermediateDirectories: true, attributes: nil)
}catch let error {
print(error.localizedDescription)
}
}
}
let localDocumentsURL = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: .userDomainMask).last! as NSURL
let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents").appendingPathComponent("MyArtworks")
let image = UIImage(named: "testpoto2") as UIImage?
// get the documents directory url
// choose a name for your image
let fileName = "image6.png"
// create the destination file url to save your image
let fileURL = localDocumentsURL.appendingPathComponent(fileName)
// get your UIImage jpeg data representation and check if the destination file url already exists
if !FileManager.default.fileExists(atPath: fileURL!.path) {
do {
try UIImagePNGRepresentation(image!)!.write(to: fileURL!)
print("Image Added Successfully")
} catch {
print(error)
}
} else {
print("Image Not Added")
}
if let iCloudDocumentsURL = iCloudDocumentsURL {
var isDir:ObjCBool = false
if (FileManager.default.fileExists(atPath: iCloudDocumentsURL.path, isDirectory: &isDir)) {
do{
try FileManager.default.removeItem(at: iCloudDocumentsURL)
}catch let error {
print(error.localizedDescription)
}
}
do{
try FileManager.default.copyItem(at: localDocumentsURL as URL , to: iCloudDocumentsURL)
}catch let error {
print(error.localizedDescription)
}
}
But I need to save the images directly to the iCloud. Any suggestions are appreciated.
I am trying to download an audio file from the internet and save it onto the phone. This is the download function:
func download() {
if let audioUrl = downloadUrl {
// then lets create your document folder url
let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// lets create your destination file url
let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
print(destinationUrl)
// to check if it exists before downloading it
if FileManager.default.fileExists(atPath: destinationUrl.path) {
print("The file already exists at path")
// if the file doesn't exist
} else {
// you can use NSURLSession.sharedSession to download the data asynchronously
URLSession.shared.downloadTask(with: audioUrl, completionHandler: { (location, response, error) -> Void in
guard let location = location, error == nil else { return }
do {
// after downloading your file you need to move it to your destination url
try FileManager.default.moveItem(at: location, to: destinationUrl)
print("File moved to documents folder")
} catch let error as NSError {
print(error.localizedDescription)
}
}).resume()
}
}
}
Then, after I close and open the app, I use the following function to retrieve the url and play it using an AVPlayer:
func getUrl2() {
if let audioUrl = downloadUrl {
// then lets create your document folder url
let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
if let u = self.destinationUrl {
let player = AVPlayer(url: u)
print(u)
print("Bouta play")
print(CMTimeGetSeconds(player.currentItem!.duration))
player.play()
}
}
}
The duration that keeps getting printed out is "nan". Is there a way to check if the audio file is actually downloading? Or could it be a problem with retrieving the file after the download? Thanks in advance.
First of all you have to check for the URL is not empty with the below logic:
if !link.isEmpty{
checkBookFileExists(withLink: link){ [weak self] downloadedURL in
guard let self = self else{
return
}
play(url: downloadedURL)
}
}
Then checkBookFileExists function will check if the file already saved or not before download it again:
func checkBookFileExists(withLink link: String, completion: #escaping ((_ filePath: URL)->Void)){
let urlString = link.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
if let url = URL.init(string: urlString ?? ""){
let fileManager = FileManager.default
if let documentDirectory = try? fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create: false){
let filePath = documentDirectory.appendingPathComponent(url.lastPathComponent, isDirectory: false)
do {
if try filePath.checkResourceIsReachable() {
print("file exist")
completion(filePath)
} else {
print("file doesnt exist")
downloadFile(withUrl: url, andFilePath: filePath, completion: completion)
}
} catch {
print("file doesnt exist")
downloadFile(withUrl: url, andFilePath: filePath, completion: completion)
}
}else{
print("file doesnt exist")
}
}else{
print("file doesnt exist")
}
}
Then if the file doesn't exists you will download it with the below function:
func downloadFile(withUrl url: URL, andFilePath filePath: URL, completion: #escaping ((_ filePath: URL)->Void)){
DispatchQueue.global(qos: .background).async {
do {
let data = try Data.init(contentsOf: url)
try data.write(to: filePath, options: .atomic)
print("saved at \(filePath.absoluteString)")
DispatchQueue.main.async {
completion(filePath)
}
} catch {
print("an error happened while downloading or saving the file")
}
}
}
That function will save it and you can play it with:
func play(url: URL) {
print("playing \(url)")
do {
audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayer?.prepareToPlay()
audioPlayer?.delegate = self
audioPlayer?.play()
let percentage = (audioPlayer?.currentTime ?? 0)/(audioPlayer?.duration ?? 0)
DispatchQueue.main.async {
// do what ever you want with that "percentage"
}
} catch let error {
audioPlayer = nil
}
}
I am trying to create a simple app that creates a csv file and saves it in a temporary directory. It seems to work but where or how can I access that file?
Below is the sample code that I use to create my csv file:
// CSV file creating
func creatCSV() -> Void {
let fileName = "Example.csv"
let path = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(fileName)
let csvText = "Time,Date,Heartrate(BPM)\n"
do {
try csvText.write(to: path!, atomically: true, encoding: String.Encoding.utf8)
} catch {
print("Failed to create file")
print("\(error)")
}
print(path ?? "not found")
}
To write to the file:
func createCSV() -> String? {
let fileName = "Example.csv"
let tempDir = NSTemporaryDirectory()
let fileURL = URL(fileURLWithPath: tempDir, isDirectory: true).appendingPathComponent(fileName)
let csvText = "Time,Date,Heartrate(BPM)\n"
do {
try csvText.write(to: fileURL, atomically: true, encoding: .utf8)
return fileURL.path
} catch {
print("Failed to create file: \(error)")
return nil
}
}
To read from the file:
func readCSV(path:String) throws {
let text = try String(contentsOfFile: path)
print("I read the following from the file: \(text)")
}
Example using both:
if let path = createCSV() {
print("Path was \(path)")
try readCSV(path: path)
}
I'm trying to retrieve images from the documents directory in order to populate a collection view but my try block returns an error but I don't know what the error is or why it is occurring.
func refreshCollectionView() {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path)
let filePath = url.appendingPathComponent(imagesDirectoryPath)?.path
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath!) {
print("FILE AVAILABLE")
do {
titles = try FileManager.default.contentsOfDirectory(atPath: imagesDirectoryPath)
print(titles.count)
for image in titles {
let data = FileManager.default.contents(atPath: imagesDirectoryPath + "/\(image)")
let image = UIImage(data: data!)
myImages.append(image!)
}
self.collectionView?.reloadData()
}
catch {
print("Error")
}
}
else {
print("FILE NOT AVAILABLE")
}
}
The line print(titles.count) is never executed and the error is caught but what is the error?
if fileManager.fileExists(atPath: filePath!) {
print("FILE AVAILABLE")
do {
// ...
} catch {
print("Error:", error)
}
}
This will show you actual error
I know how to get a remote URL in Swift
let remoteURL = NSURL(string: "https://myserver/file.txt")!
I know how to get a local URL in Swift
let localURL = NSURL(fileURLWithPath: documentsFolder + "/my_local_file.txt")
and unfortunately this does not work
NSFileManager.defaultManager().copyItemAtURL(remoteURL, toURL: localURL)
with the following error
The file “file.txt” couldn’t be opened because URL type https isn’t supported.
Is there a way how to perform this?
You can use NSURLSessionDownloadTask to download the file:
func downloadFile(url: URL) {
let downloadRequest = URLRequest(url: url)
URLSession.shared.downloadTask(with: downloadRequest) { location, response, error in
// To do check resoponse before saving
guard let tempLocation = location where error == nil else { return }
let documentDirectory = FileManager.default.urlsForDirectory(.documentDirectory, inDomains: .userDomainMask).last
do {
let fullURL = try documentDirectory?.appendingPathComponent((response?.suggestedFilename!)!)
try FileManager.default.moveItem(at: tempLocation, to: fullURL!)
print("saved at \(fullURL) ")
} catch NSCocoaError.fileReadNoSuchFileError {
print("No such file")
} catch {
// other errors
print("Error downloading file : \(error)")
}
}.resume()
}
let stringURL = "https://wordpress.org/plugins/about/readme.txt"
downloadImage(url: URL(string: stringURL)!)
Update: SWIFT 2.2
func downloadFile(url: NSURL) {
let downloadRequest = NSURLRequest(URL: url)
NSURLSession.sharedSession().downloadTaskWithRequest(downloadRequest){ (location, response, error) in
guard let tempLocation = location where error == nil else { return }
let documentDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first
let fullURL = documentDirectory?.URLByAppendingPathComponent((response?.suggestedFilename)!)
do {
try NSFileManager.defaultManager().moveItemAtURL(tempLocation, toURL: fullURL!)
} catch NSCocoaError.FileReadNoSuchFileError {
print("No such file")
} catch {
print("Error downloading file : \(error)")
}
}.resume()
}
let stringURL = "https://wordpress.org/plugins/about/readme.txt"
let url = NSURL.init(string: stringURL)
downloadFile(url!)
You should download it first, then save it to a local file.
Code example can be found here: (using AFNetworking)
How I properly setup an AFNetworking Get Request?