NSURL URLByResolvingBookmarkData seems to fail randomly - ios

My app is an image viewer for iOS. I allow users to pick files from the camera roll or cloud file providers. For each file chosen, I create a bookmark so that the user to come back to view the file later without having to go through all of the steps of the camera roll/cloud file pickers again. The camera roll bookmarks work consistently, but the cloud file provider bookmarks fail randomly by returning nil from the call to URLByResolvingBookmarkData. The error returned is:
"File Not Found"
This happens with files from iCloud, DropBox, Box, Google Drive, etc. Here is how I create and retrieve the bookmarks:
// bookmark created from url returned by UIDocumentPickerViewController
NSData *bookmark = [url bookmarkDataWithOptions:options includingResourceValuesForKeys:nil relativeToURL:url error: nil];
// retrieving the URL from this bookmark works for a short time, then returns nil
url = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithoutUI relativeToURL:nil bookmarkDataIsStale:&isStale error:&error];
Anyone can shed some light as to why a bookmark will work for a while, then fail? Limited storage/RAM?
I have a feeling that the answer is to keep a local copy of files from cloud storage since they're not guaranteed to be accessible more than once.

You should use startAccessingSecurityScopedResource on the URL, making sure to call stopAccessingSecurityScopedResource when you are finished.
Alternatively, Apple highly recommend using FileCoordinator or UIDocument to manage access to files. Especially now you may access files that other apps are also accessing.

Related

Upload images via Firebase Storage, make it accessible to anyone via public link

Whenever I upload an image to Firebase Storage, the file is only accessible through "download link".
What if I want anyone to access this file?
If I go to Google Platform Storage and enter the same bucket that Firebase uses, I can see that the "Public link" is unchecked.
How can I let this be automatically checked when photo has been uploaded?
Such actions can be done through Google Cloud Storage API, but there doesn't seem to be any option for this through Firebase.
Also, all images that are being uploaded via Firebase has a Content-Type of "application/octet-stream".
Since I am uploading an image, I would like this to have either "image/jpeg" or "image/png". Is there a way to change the metadata?
UPDATE: Reason why I am asking this is because if one create an app with an Instagram like feed of thousands of images. Requesting a download link for each image that is being fetched is unnecessary since the images in questions should already be open to public by default. Firebase file upload prevents this and each user therefor has to make one request per image (which can be tons of images per app launch). Firebase Flame subscription plan for instance has a limit of 100,000 downloads/uploads per month. This makes it unrealistic to create an image feed with thousands of users with thousands of image request each. Files should have the option to create a public link during upload, just as the Google Cloud Storage API itself.
There is no configuration to automatically check the public access checkbox of Google Cloud Storage for files that are uploaded through Firebase Storage.
That said, you could write a Google Cloud Function that triggers when a file is uploaded and that then changes the properties of the file, specifically, you'll want to change the object ACLs to be publicRead.
But since the download URL that Firebase generates for you is already publicly readable, I'm not sure what you gain by checking the box. Is there a specific use-case that you're looking for that isn't covered by simply sharing the download URL?
On the second part of your question, check out the File Metadata section of our docs, which shows you how to set the content type of a file:
// Create file metadata to update
FIRStorageMetadata *newMetadata = [[FIRStorageMetadata alloc] init];
newMetadata.contentType = #"image/jpeg";
// Update metadata properties
[myRef updateMetadata:newMetadata completion:^(FIRStorageMetadata *metadata, NSError *error){
if (error != nil) {
// Uh-oh, an error occurred!
} else {
// Updated metadata for 'images/forest.jpg' is returned
}
}];
Metadata can on added on upload as well, so there's no need for a second request.

Any other ways to access Documents Directory on iDevice Locked State?

I am implementing Music Player application in iOS platform. Here I am storing and retrieving the media contents using Documents directory. So I can't able to access the 'Documents Directory' when iPhone is getting locked with passcode. I referred Apple developer library, they said the Encryption & Decryption is comes under the accessing the file contents from documents directory. So if device is getting locked the Decryption key is Destroyed. Here I have attached the Screen shot of Problem Description. I was stuck with this problem last 2 months. Pls give me any other ways to access the Documents directory at locked state. Not Only Media , Any other content*.
Thanks in Advance.
Apple Developer Site:
https://developer.apple.com/library/mac/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html
You need to specify the file protection level as an option when you write your files. Example:
[someData writeToFile:filePath options:NSDataWritingFileProtectionNone error:&error];
In this, someData is an NSData representation of the data you want to write to disk, filePath is the string path where you want to save the file.
Read the documentation on NSDataWritingOptions in the NSData Class Reference for more encryption options.

Launching a different app to open file on server

The Apple Docs say that UIDocumentInteractionController "provides in-app support for managing user interactions with files in the local system". Is there a similar setup for viewing files on a server? I tried just sending the link to the file as the NSURL for interactionControllerWithURL:, but that didn't work. I guess the alternative would be to download the file, then open it once it has downloaded, then delete the file. That seems like a lot of extra coding work though, if there is an easier way that's already available.
Edit: I already know the name of the file I want to view/download, so I'm not really looking for the "file list" aspect of UIDocumentInteractionController. On the server, there are many Google Earth .kml files. The user isn't going to directly select which file to open from a list - I select the file to open programmatically based on actions taken by the user previously in the session.
As I understand it, presentOpenInMenuFromRect:inView:animated: will show a popover something like "Would you like to open the file 'myFile.kml' in Google Earth?". If the user selects 'Yes', the UIDocumentInteractionController launches Google Earth and opens myFile.kml. So I guess I'm not really looking for a file list viewer, just a way to trigger an "Open With" kinda functionality, where the file I'm opening exists on my server.
UIDocumentInteraction controller can't be used to view list of files present on server.
UIDocument interaction controller takes local file present in source application and shows list of applications that can open that file.Once use clicks on file then it is transferred to target app.
If you want to get file from server then you can use NSURLConnection class to download file form server and store it on device.
I think I figured this out. I don't need to use a UIDocumentInteractionController at all for what I'm looking for. I can simply
NSURL *url = [NSURL URLWithString:#"comgoogleearth://www.mysite.com/myfile.kml"];
BOOL canOpen = [[UIApplication sharedApplication] canOpenURL:url];
if (canOpen)
{
[[UIApplication sharedApplication] openURL:url];
}
else
{
NSLog (#"Open failed. Make sure Google Earth is installed and the URL is correct.");
}
This will launch Google Earth with my file just like I'm looking for.
FYI, I got the scheme for Google Earth from elpsk's answer to this question. It looks like a pretty comprehensive list of a lot of file types and the apps that open them. Just replace the comgoogleearth in my URL with the scheme for whatever app you are trying to open a file with.

Is it possible to save files outside of the sandbox via the built-in apps?

If I have a UIWebView which has links to files then is it possible to save those files to disk outside of the application sandbox?
Yes I know an app can't access the filesystem outside of its sandbox, but could the saving process be done by whatever app can handle the file type? - For example if its an audio file, could my app launch QuickTime passing it the file (or file url) and the user is then able to save the file via the QuickTime app saving it in the appropriate location for audio files?
Apps are limited to saving data within their own sandbox. Which you seem to acknowledge already.
You can make one app launch another, which in theory could allow a second app to save data, but within its own sandbox. You also mention this.
In effect, you've answered your own question.
It is possible to write images to the photo album which is outside the sandbox.
UIImage* image = [UIImage imageNamed:#"picture_of_my_cat.png"];
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
In order to get data out from a UIWebView (javascript to objective C) you can subclass NSURLProtocol and use jQuery.ajax.

storing files on iCloud and distributing them to all app users

I am building a iOS 5.1 app using storyboard. this app contains a table view. My idea was to add an "add" button to my title bar, in the table view. When a user clicks on the add, a simple document editor I need to build (like keynote or pages) will open. when the user clicks on the save button, the file will be uploaded possibly on I cloud, and all other users of the application will be able to access it, from a downloads tab, download it, and add it to their own app (a sort of file sharing via iCloud). Is it possible to do something like that? How can I do it? Can I do it using iCloud, or do i need to build my own database?
maybe you should try to use this:
NSURL *urlToShare = ...; NSDate *date;
NSError *error;
NSURL *sharedURL =
[[NSFileManager defaultManager] URLForPublishingUbiquitousItemAtURL:urlToShare
expirationDate:&date
error:&error];
Thats from CS193p lessons. This code will help you to share files between different iCloud Accounts.
But remember that "Only files (not directories) maybe exported in this way.
The URL points to a copy of the file (so it is a read-only sharing mechanism)."
Hope this helps!

Resources