Create a link on the ios filesystem with Objective-C - iphone

I'm trying to create a comic reader app which supports both online reading & off-line reading (by downloading).
I've found MWPhotoBrowser as my image viewer, which supports SDWebImage as the image cache.
My problem is that if some user read little part of a comic on-line, and then they decides to download it for offline reading. Since the already read part is cached by SDWebImage, I don't wanna download them again from the web server. But since user asks to download them locally, I don't wanna keep them on the image cache neither as this will make the downloaded images out of our hand.
Copy the image from the image cache to the place I wanna put is a feasible solution, but it takes storage space. So, what I'm trying to do is cut the image from the image cache to the right place, and then make some soft-link in the image cache. In this way, there should be only one image copy in the storage file system.

You don't want a symbolic (soft) link. A symlink doesn't prevent the original file (in the cache) from being deleted. If the original file is deleted, you'll get an error when you try to open it through the symlink.
You want a hard link. You can create a hard link using -[NSFileManager linkItemAtURL:toURL:error:] or -[NSFileManager linkItemAtPath:toPath:error:]. Take a look at the NSFileManager Class Reference.
If you need to learn more about hard links and symbolic links, you can quickly find a lot of information by searching for “hard link” or “symbolic link” in your favorite search engine.
NOTE FOR FUTURE SEARCHERS
You can create a symbolic link using -[NSFileManager createSymbolicLinkAtURL:withDestinationURL:error:] or -[NSFileManager createSymbolicLinkAtPath:withDestinationPath:error:].

Related

File Uploading in Sakai

I want to know if there is a 'right' way to make file uploads through custom tools.
I've seen the https://confluence.sakaiproject.org/display/BOOT/File+Uploads+with+RSF guide and it seens ok, but It stops with the file in memory with no further info. I can built a random file upload code but I want to make it Sakai-friendly (Using ContentHosting and Resources service?)
Any hints?
Thanks
The link you provided for the first part is a good example of how to get the upload initially processed. Going through RequestFilter will get your files validated, but you can use whatever method you want to upload it.
For the second part, I'd look at the ContentHosting webservice (createContentItem) for an example of how to add a file from a byte[] in memory after you've uploaded it.
These methods in ContentHostingService also accept InputStream as a parameter as of 2.7 (KNL-325), so you don't have to store the entire file in memory and can stream it as you're uploading, which you should do if the files are of any reasonable size.

Multiple Image storing and dealing with table view

Despite there are a lot of themes around this topic, I seem very frustrated in the following situation :(
The app downloads and parses a JSON with about 1000 objects, which have in their attributes link for a small image. I need to download (once) these images, store them and use in my TableView as icons.
What is the best way to store such amount of files and to work efficiently with them while displaying the TableView?
I will tell you how will I do it but before I would like to give you a warning about downloading files from the Internet and storing them in your app.
I got one of my apps rejected from Apple lately because I violated rule 2.23 from the App Store Review Guidelines which says:
2.23 Apps must follow the iOS Data Storage Guidelines
or they will be rejected
Since Apple is using iCloud lately you should minimize the traffic that each app will upload and therefore you should not have more than 40MB stored in your Documents folder of your app. They also say (if you read the links I provided):
Data that can be downloaded again or regenerated should be stored in
the /Library/Caches directory.
And since the cache folder can be deleted by the iOS if needed, you should design your app to be prepared to download the images again in case they are gone, so keep this in mind.
Now for my solution, I think downloading 1000 files is too much (even if they are small files). I suggest that you have the files saved in a ZIP file on the server from which you are willing to download and unzip them on your disc once downloaded. This will be much easier and more practical. You can look here to see how to zip and unzip in your app.
After you have your files unzipped I suggest to have a small database (SQLite) from which you can load load the file names, store these names in an array, and then use this array to fill the images in your table in the function cellForRowAtIndexPath.
I hope this helps you. By the way, it is my way to do it but I am not saying it is the "best way" as you are asking :)
Given that you would like to keep these images/data persistent, you now have two options: You can manage them yourself or you can utilize Core Data to help you do it. I recommend Core Data.
If your not familiar with Core Data, you can start reading about it Here. It's a little bit daunting to get started, but once you've run through a tutorial it's extremely straightforward and will make your life much easier.
If you would like store the images yourself, or would like a more efficient Core Data structure, I recommend writing all of your images into your Documents directory as see Here. Then you can just store File path strings in your CD structure or manually in your plist like This.
And finally, for loading them into your TableView you can use those stored image paths to load UIImages with:
[[UIImage alloc] initWithContentsOfFile:filePath];
This would be placed within your:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
function so that you can set the image where you would like.

Valid file types for iCloud?

I find many similar question but i didn't get solution for this.
Is it possible to upload some file like image, document, zip file to upload on iCloud programmatically?
See table 4-1 in the documentation:
How do you manage the data? Manage files and directores using the
NSFileManager class. Open, close, read, and write files using standard
file system routines.
So if you can create a file, you can store it in iCloud. But remember there's a finite, relatively small amount of space available.
iCloud can handle all kinds of files. So if you want rot use an obscure file format or invent your own, go for it. It only can to be converted into a byte stream/NSData, but then again, what isn't?
Check this tutorial walkthrough app. It shows how to create, modify and delete files for iCloud.
http://github.com/lichtschlag/iCloudPlayground

How can I save pdf's to my app resources folder, and access them in run-time?

I have an app I'm designing that will allow for lots of PDF viewing. There are a lot of different languages available, and so if I were to include all of them in the app, it would be like 100+ mb in size which just won't fly.
So I'm thinking that I am going to put the pdf's on my server, and access them with a direct download link like this:
http://mysite.com/pdfs/thepdf.pdf
Which will return the exact pdf I want. So I'm wondering how I can go about accessing these resources as I download them on the fly?
I imagine I need to save the pdf's to the app resources folder? And then when a tableView row for the pdf is selected, I check if the pdf is in the resources folder (how do I do that?), and if not, pull it down off the server, and load it into my view?
I think I have an okay idea of what I need to do, just not very clear on the code to do it. Can anybody post the code for accessing the resources folder (if that's actually what I need to be doing), and maybe the code for how to check if something is in the resources folder?
Thanks!
Have you considered using a UIWebView to view the PDF instead of downloading and loading it yourself? UIWebView should take care of caching, so you won't have to worry about that.
Assuming that a UIWebView won't work, to download PDFs and see if they exist, you need to store it in the Documents folder. The resources folder cannot be altered after you submit your app to Apple, but the Documents folder in your app is completely fine. To access it, I would actually recommend ConciseKit, which can be found on GitHub. It gives you a helper method to access your app's document directory. The helper method is
[$ documentPath];
Then you can get the path for a file by doing
[[$ documentPath] stringByAppendingPathComponent:#"file.pdf"];
So that is how you get a path to a file, to check if it exists, you want to use NSFileManager.
[[NSFileManager defaultManager] fileExistsAtPath:#"path from above"];

Where to cache remote image files in iOS?

I am planning to cache the images from a server and use show it as a sort slide show in my App. I would be asynchronously loading the images.
I have two options:
Either to cache the images as a File and use it whenever necessary.
Cache the images objects in memory and use it when ever necessary and write it in to files when Application quits.
Which one would be better?
Please let me know if you you have any kind of suggestions regarding caching images.
Your second approach has 2 major flaws:
If there's too many images then your application will get low memory warning and you'll have to dispose your images from memory anyway
It's also not a good idea to save all images to file on application quit - it is not guaranteed that your saving code will finish on application exit (e.g. if it takes too long system may just terminate your app and your images will be lost)
I'd suggest saving images to files right after you download them and keep in memory reasonable number of images you need to show without visible delay (loading extra images when required and disposing of unnecessary ones)
I would recommend you the first option. Leaves you more flexibility, e.g. when the data size increases the memory size.
I'd do it like this: Have a NSMutableDictionary with the cached images (as UIImage objects). If the image is not in the cache, look whether it's available as a file. If it's not available as a file, load it, put it into your dictionary and also write it to a file.
As for where to write the files to: you can either use the NSTemporaryDirectory() or create a directory inside your NSLibraryDirectory (use NSSearchPathForDirectoriesInDomains to locate it). The later has the advantage/disadvantage that it will be in the iTunes backup (whether that's an advantage or not depends on the use case). Using the Library directory is Apple's recommended way of storing data that is backed up but does not appear in the iTune's file exchange thingy (Documents directory).
I have started using EGOImageView to handle my caching; it's very versatile and handles the intricacies of caching for you.
It works very well for pulling images via http, you can find it on the EGO developer website here
http://developers.enormego.com/
For image caching solution on iOS platform, you might want to consider SDWebImage framework available at: https://github.com/rs/SDWebImage. It is very easy to integrate and takes care of all your image caching worries.: read more about the working here: https://github.com/rs/SDWebImage#readme
We recently picked this up for our app and it works great.