Saving an iCloud Drive security scoped URL on iOS (UIDocumentPickerViewController) - ios

I'm trying to save the security scoped URL returned from iCloud document picker (UIDocumentPickerViewController)
The documentation states:
If the URL is not a ubiquitous URL, save a bookmark to the file using
the
bookmarkDataWithOptions:includingResourceValuesForKeys:relativeToURL:error:
method and passing in the NSURLBookmarkCreationWithSecurityScope
option. Calling this method creates a bookmark containing a
security-scoped URL that you can use to open the file without further
user intervention.
However, the compiler says that NSURLBookmarkCreationWithSecurityScope is not supported on iOS.
Anyone know what's going on here....?

After further digging, it turns out option NSURLBookmarkCreationWithSecurityScope is NOT needed at all when creating bookmark data in IOS. It's an option for OS X. You can just pass nil for the option field. I think Apple's document is confusing at the best.
However, you do need to call startAccessingSecurityScopedResource before creating the bookmark and make sure the call returns 1 (success) before proceed. Otherwise, bookmark creation will fail. Here is the sample code:
if ([url startAccessingSecurityScopedResource]==1) {
NSError *error;
NSData *bookmark = [url bookmarkDataWithOptions:nil
includingResourceValuesForKeys:nil
relativeToURL:nil
error:&error];
if (error) {
//handle error condition
} else {
// save your bookmark
}
}
[url stopAccessingSecurityScopedResource];
Again Apple's document is confusion at the best! It took me a lot of time to find out this. Hope this helps.

I ran into the same issue today, and indeed the compiler says NSURLBookmarkCreationWithSecurityScope is not available on iOS.
But to my surprise, if I use the raw constant instead (NSURLBookmarkCreationWithSecurityScope maps to ( 1 << 11 ), the method seems to work. It returns a valid bookmark data object, and when I call [[NSURL URLByResolvingBookmarkData:options:relativeToURL:bookmarkDataIsStale:stale], a valid security-scoped NSURL is returned and I can access the files and directories. Also, I tested these with iCloud Drive. And the documentation only says this should work for third-party document providers.
I am not sure how reliable this approach is, because it seems that Apple engineers didn't have time to finish up this feature, so disabled it in the last minute. Or it could be simply a bug in the header file. If anyone finds out more about this, please comment.

Related

NSData Assignment Vanishes (becomes nil) Directly After Assigned

Let me start by saying I'm not proficient in objective c, nor am I an iOS developer. I'm working on a react-native app and find that I'm having to dig into the native code. So, I appreciate your patience with me and would also very much appreciate if you made zero assumptions about what I might, or might not know. Thx!
I'm trying to use react-native-mail but it fails to attach the photo I've selected to the email.
In troubleshooting, I jumped into Xcode's debugger for the first time. Stepping through the code, it appears as though the attachmentPath which is something like file:///var/mobile/... is being assigned to the variable fileData as type NSData. But then, taking one step further into the code it becomes nil.
I'm not sure why this would happen nor how to go about troubleshooting this. Here's an image of the debugger session with 3 screenshots stitched together side-by-side.
Here's the code: RNMail.m
All pointers, tips, guidance, and advice welcome
In your first screenshot, the debugger is still on the line that declares and assigns the fileData variable. This means that that line hasn't actually been executed yet. -dataWithContentsOfFile: hasn't yet been called, and thus the value that appears to be in fileData is not meaningful; what you're seeing is just garbage data prior to the variable actually being assigned. In your second screenshot, the -dataWithContentsOfFile: method has finished running, and it has returned nil. What you need to do is to figure out why you're getting nil from -dataWithContentsOfFile:. Perhaps the path to the file is incorrect, or perhaps you don't have permission to read it, or perhaps you have a sandboxing issue.
I would suggest using -dataWithContentsOfURL:options:error: instead of -dataWithContentsOfFile:. This will return an error by reference (create an NSError variable ahead of time, assign it to nil, pass a pointer to the error as the third parameter to -dataWithContentsOfURL:options:error:, and then check the error if the method returns nil). More likely than not, the contents of the error will explain what went wrong when trying to read the file.
EDIT: Looking at your screenshot again, the problem is clear; from the description of the contents of attachmentPath, we can see that it isn't a path at all, but instead it contains a URL string (with scheme file:). So you cannot pass it to the APIs that use paths. This is okay, since the URL-based mechanisms are what Apple recommends using anyway. So, just turn it into a URL by passing the string to -[NSURL URLWithString:] (or, even better, -[[NSURLComponents componentsWithString:] URL], since it conforms to a newer RFC). So, something like:
// Get the URL string, which is *not* a path
NSString *attachmentURLString = [RCTConvert NSString:options[#"attachment"][#"path"]];
// Create a URL from the string
NSURL *attachmentURL = [[NSURLComponents componentsWithString:attachmentURLString] URL];
...
// Initialize a nil NSError
NSError *error = nil;
// Pass a pointer to the error
NSData *fileData = [NSData dataWithContentsOfURL:attachmentURL options:0 error:&error];
if (fileData == nil) {
// 'error' should now contain a non-nil value.
// Use this information to handle the error somehow
}

is App Indexing for iOS working?

Im trying to add the app Indexing, but the method [GSDDeepLink handleDeepLink:url]; is returning the same gsd-MY_URL:// when it's supposed to sanitize it to MY_URL://.
As you can see here, App Indexing the snippet is really simple.
My code is the same as in the docs,
DLog(#"url recieved: %#", url);
NSURL *sanitizedURL = [GSDDeepLink handleDeepLink:url];
DLog(#"sanitizedURL: %#", sanitizedURL);
That last sanitizedURL, returns the whole URL, not sanitized
Since it's available on a limited release I'm not sure if the method should work or am I doing something wrong.
I already have deep linking from my webpage, and it works perfectly, and this should be no pain, but it is.
Any info on this?

How can I get the list of all the files uploaded in my built.io application?

I have made an iOS application using built.io. There are several files uploaded in the application. However, i am unable to get the list of all the files uploaded in the app. Could anyone please help?
This can be done via BuiltFile class instance method fetchAllOnSuccess:onError:
It returns all files uploaded in your built application only if the requesting user has permission for it.
Built* builtfileObj = [Built file];
[builtfileObj fetchAllOnSuccess:^(NSArray *allFiles) {
// allFiles contains array of BuiltFiles
} onError:^(NSError *error) {
// there was an error in creating the object
// error.userinfo contains more details regarding the same
}];
To fetch all the uploads, the iOS SDK provides an instance method in the BuiltFile class. It returns an array of all the uploads.
Here's the link to the official documentation
http://static.built.io/downloads/sdk-docs/ios-docs/Classes/BuiltFile.html#//api/name/fetchAllOnSuccess:onError:
I dont know if its available in the iOS SDK but you can use the REST API to fetch it
Headers :
"application_uid: uid"
"application_api_key: api_key"
URL: GET : https://manage.built.io/v1/uploads?skip=0&limit=50&include_count=true
Params : skip and limit for pagination and include_count is for getting the total count.
The above url will fetch all types of files
But if you want only images or videos then you can use the below urls
https://manage.built.io/v1/uploads/images
https://manage.built.io/v1/uploads/videos
I hope i was helpful to you!!
Note : without the headers the API wont work

ios share extension - files from dropbox not loading correctly

When I try to load a shared item, the data that comes back is dropbox's login page - as if I weren't authenticated.
Here is the current method I am using to get the file data:
[itemProvider loadItemForTypeIdentifier:docType options:nil completionHandler:^(NSURL *url, NSError *error) {
//my code
}];
doctype is an appropriate kUTType like kUTTypeImage or kUTTypeText, for example. The mimeType that we write the file with is correct to, per other files. It's the actual content loaded from dropbox (just a login page every time).
I have used other variations of the method (UIImage *, and NSData *) but get the same result for dropbox files.
Our shared extension works fine with files that are downloaded in apps like goodreader or Files. The problem arises when I try to share a file from the dropbox app. It gives me a url that I can put into any browser and it will take me to the file, so the url is not the problem.
Has anyone else faced this?
Here is an example link to a document that does this:
https://www.dropbox.com/s/qxkd1957qf7iq9x/04%20-%20Test%20Document.doc?dl=0
Thank you for your help on this Greg. I found that this worked instead by just changing the url and setting dl=1 like so
From:
https://www.dropbox.com/s/qxkd1957qf7iq9x/04%20-%20Test%20Document.doc?dl=0
To https://www.dropbox.com/s/qxkd1957qf7iq9x/04%20-%20Test%20Document.doc?dl=1

Gracenote API - No track link data

Currently, in my AppDelegate, I have an instance variable declared for GNConfig that is set up with all properties I would like to receive.
This instance of GNconfig is used by any class that makes a gracenote request.
The requests I am using are recognition from an audio stream, recognition by local file and a text search which populates an array. The array is then used for track lookups by id for the corresponding array item.
I am able to get all the content I need, except for track and album link data (always returns null).
I have tried plenty of different suggestions and guides with no luck.
Could somebody please help me out? This data is essential to my app and my app is pretty much complete except for this big obstacle.
Thanks in advance.
** edit **
This is in my appDelegate:
_gnConfig = [GNConfig init:#"XXXXXXX-XXXXXXXXXXXXXXXXXXXXXXX"];
[_gnConfig setProperty:#"content.coverArt" value:#"1"];
[_gnConfig setProperty:#"content.coverArt.sizePreference" value:#"LARGE"];
[_gnConfig setProperty:#"content.allowFullResponse" value:#"1"];
I have this in one of my class methods:
NSURL *filePath = [item valueForProperty:MPMediaItemPropertyAssetURL];
[GNOperations recognizeMIDFileFromFile:self config:[[AppDelegate sharedDelegate] gnConfig] fileUrl:filePath];
In the delegate method I have:
gracenoteResponseItem = [result bestResponse];
NSLog("%#", [gracenoteResponseItem trackLinkData]);
Some tracks may not have link data available.
Also if you are doing a local lookup then you will have to set this config option:
[publicProperties setObject:#“1"forKey:#"content.allowfullresponse"];
Unless you have explicitly had your client ID entitled for Link IDs (aka 'external' or '3rd party' IDs), you won't get any in your responses.
By default, Gracenote Open Developer client IDs aren't entitled for any external IDs. You need to coordinate with Gracenote to entitle your client ID to start receiving the desired IDs.

Resources