I'm downloading images and displaying them each time the user visits a particular view. To make it more efficient I want to start caching so instead of fetching from the database the user already has the images downloaded.
From my research I found a bunch of Swift libraries that handle caching for you, such as HanekeSwift, KingFisher, and Nuke. I'm wondering what the difference is between using one of these libraries and just downloading the image to Core Data.
As far as I know, the first time a user downloads the images I can just save them to Core Data and check if they exist by key the next time. Are there any advantages to using one of these libraries instead?
You shouldn't save images to core data. You should save them to files and then if you want you can store the path or file name or other attributes about the image in core data. You can save the images to your apps documents directory for instance with the following code.
let dir = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0] as String
if let filePath = dir.stringByAddingPathComponent("filename.png"){
try? UIImagePNGRepresentation(image)?.write(to: URL(fileURLWithPath: filePath))
}
If you want to save to a sub folder just use FileManager to make sure the sub folder has been created and create it if not.
Related
I'm currently sharing data between devices using core data and cloud kit.
Currently I have a "Picture" entity which stores the filename, the date it was added and a relation to another entity.
The details in core data successfully syncs, how would I go about syncing the image file.
The file is saved in the documents folder and I can get its file path using
let imagePath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(imageName)
Research seems to show I need to use CKAsset to upload/download the file but how do I go about doing this?
Resolved the issue by saving the image as data into core data, can then convert it back to an image when displaying
I am trying to access a specific folder in a remote URL e.g.http://dev.servertest.com/sessions/id/video
from there, I want to grab all the videos from the folder and download them to the device.
I know how to download the videos from a remote URL to the directory but I can't work out to grab all the videos from the specific video folder.
Also, the server may change depending on the user using their own server but the rest of the structure should be the same "/sessions/id/video"
Below is the code I use to upload from a specific folder "ImportVideos" from my app directory if that helps.
func loadVideos(){
let fm = FileManager.default
let dirPaths = fm.urls(for: .documentDirectory, in: .userDomainMask)
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
do {
let videoList = try fm.contentsOfDirectory(atPath: "\(documentsPath + "/ImportVideo")")
for filename in videoList {
videoSubtitles.append(filename) //this is used to populate my tableview
}
} catch let error {
print("error: \(error.localizedDescription)")
}
}
If someone could point me in the right direction that would be great. Thanks.
The HTTP protocol does not provide any means of getting a list of files in a directory. What you're trying to do is not generally possible without a manifest — a list of files that you want to download.
The easiest way to do that is to run a script on the server, e.g.
#!/bin/sh
FILES_DIR=/path/to/directory/on/server
cd "$FILES_DIR"
ls > allfiles.txt
Then have your app fetch the file http://example.com/path/to/allfiles.txt, then split it by newline, and fetch each file. This approach also provides the advantage of letting you later replace that text file with a script handler that serves different file lists to different clients, if desired, e.g. for supporting different versions of your app.
Alternatively, if your server supports WebDAV, then it is possible to configure the directory with WebDAV enabled and use a WebDAV library to find out what files are in the directory. However, this is probably not a good idea, because WebDAV is relatively complex and easy to misconfigure.
Finally, some web servers provide a way to enable "directory listings" — a web page that has links to all of the files in the directory. (Many people will tell you that this is a bad idea from a security perspective, though that is debatable.) It is possible, though inherently fragile, to parse such a page and extract the links. This approach is strongly discouraged, however, because it could break completely when you update to a new version of the web server software.
I have (finally) managed to get prototype app using Core Data to persist to an sqlite file. Quitting and restarting I see the same data. So all seems well.
I want to now start from scratch again so I went to delete the sqlite persisted data. I set up it's location as :
open lazy var applicationDocumentsDirectory: NSURL = {
// The directory the application uses to store the Core Data store file.
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return urls[urls.count-1] as NSURL
}()
let url = self.applicationDocumentsDirectory.appendingPathComponent("TrainingDiary.sqlite")
which places the .sqlite files in ~/Library/Containers/uk.me.stevenlord.Core-Data-Binding/Data/Documents
There are four files in there: iChats, TrainingDiary.sqlite, TrainingDiary.sqlite-shm and TrainingDiary.sqlite-wal
I close my app. Delete all there files. When I reopen my app the full Core Data model is still there and when I look back in this directory the files are back.
What am I missing ?
EDIT:
I've figured out whats happening though I still don't quite understand why this is how it works. The above code specifies where the Core Data should be saved:
which places the .sqlite files in
~/Library/Containers/uk.me.stevenlord.Core-Data-Binding/Data/Documents/TrainingDiary.sqlite
This it does however I've now found that the app also saves the following
~/Library/Containers/uk.me.stevenlord.Core-Data-Binding/Data/Library/Application Support/Core Data Binding/Core_Data_Binding.sqlite
My XCode9 project is called "Core Data Binding". If I delete this file and start up my app I get an app with no data as expected.
So the persistent store is not going to where I specified. So still confused.
I'm missing something still. But something different
here's the thing: I download a bunch of data in JSON format. I put that into an array of dictionaries. Then, I save to disk. One dictionary stores a link to some image. What I would like to do is to store also the actual image (not the link!) along with rest of the data. How would you start? Which way to go?
I would download the image and save the local path alongside the URL path.
However, if you're going for one big file, you could always base64-encode it.
I think using the filesystem directly and saving your local path would be more efficient and effective than one monolithic file, as you'll save a lot of parsing and encode/decode time.
I suggest you to start from this tutorial : SimpleFTPExample
As per my query from the below link, i've implemented retrieving photo album images from ALAsset Library.
Upload ALAsset URL images to the server
I get the images Asset URL's like below,
"assets-library://asset/asset.JPG?id=1000000001&ext=JPG"
"assets-library://asset/asset.JPG?id=1000000002&ext=JPG"
"assets-library://asset/asset.JPG?id=1000000003&ext=JPG"
I want to store these in a database (or) file [I don't know which is suitable for comparison for later purposes]. Next time(say,after 30 mins), i want to get again all the image URL's from Asset and compare with the previous image URL's which has stored in a DB, to find if any new images has been added in photo album or not. If any new image is been added in photo album, then i get that image in my code.
I want to know, what should i use to store the image URL strings, whether SQLite database (or) file, and next time which one should be sufficient to compare the previous data and the current data? I thought of going with creating sqlite database and store the data and compare the image URL strings with the stored data like that …. Am i thinking right to go? If yes, may i know how to store the data(image URL strings) in a sqlite database and do comparison between new image URL's and stored data?
I created a sqlite database through Firefox sqlite manager plugin and added a table. I'm not getting any samples further to go through to solve my purposes, i.e. store the image URL strings in sqlite database and do comparison between the stored image URL strings and new image URL strings which i got from Asset library.
Please help and advise.
Thank you!
yes you are going right. Use sqlite database to store URLs follow the tutorial
http://dblog.com.au/iphone-development-tutorials/iphone-sdk-tutorial-reading-data-from-a-sqlite-database/
Edit..sorry, i missed the last comment that explains what you want to do..
Here
http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/iPhoneCoreData01/Introduction/Introduction.html
do that tutorial to learn how to set up the database and core data, you'll see how they save information - and from there just change code to suit your needs
Edit again.. after that you can use predicates to pull out info you need, and/or use string comparisons (Google "iPhone sdk compare strings") to compare to a new string.
or create an array of existing URL's and do something like
if ([myArrayOfURLS containsObject:theNewUrl]) {
[self doSomethingWithMyNewURLIGuess];
}