is App Indexing for iOS working? - ios

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?

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
}

Get NSString out of ENNoteContent with Evernote Cloud SDK 2.0

I am new to Evernote SDK development and am using the evernote cloud SDK 2.0 as recommended by Evernote.
However, I am having trouble to get the NSString content out of the ENNoteContent object. I have tried the followings from searching online but none seems to work with the cloud sdk as I guess they are all for the old version of Evernote SDK...
1 Using "convertENMLToHTML" method.
According to this and this, I could call convertENMLToHTML directly on an ENNoteContent object much like this convertENMLToHTML:note.content. However, in the cloud SDK, this resulted in an exception inside ENMLUtility that terminates the app because convertENMLToHTML is expecting an NSString as opposed to ENNoteContent and the first thing this function does is trying to call [enmlContent dataUsingEncoding:NSUTF8StringEncoding]] which caused the exception if enmlContent is a pointer to ENNoteContent but not a pointer to NSString.
2 Attempting to get _emml object out of the ENNoteContent object
This post has a quote of calling [note.content enml] but this again doesn't work with cloud sdk as object enml isn't defined in the interface.
Does anyone know how one can get an NSString out of ENNoteContent? I would expect this to be a very straightforward process but am surprised that I wasn't able to find anything that works for the Cloud SDK.
3 Using generateWebArchiveData method
Per Sash's answer below, I have also attempted to use the generateWebArchiveData method in the example from the cloud sdk. The code I have looks like this:
[[ENSession sharedSession] downloadNote:result.noteRef progress:^(CGFloat progress) {
} completion:^(ENNote *note, NSError *downloadNoteError) {
if (note) {
NSLog(#"%#", note.title);
[note generateWebArchiveData:^(NSData *data) {
NSString* strContent = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"test content %#", strContent);
}];
} else {
NSLog(#"Error downloading note contents %#", downloadNoteError);
}
}];
However, strContent outputs "null" for a note that I have verified with legitimate content.
As a temporary hack, we added #property (nonatomic, copy) NSString * emml;
in ENNoteContent.h and removed the same line in ENNoteContent.m to get around this for now.
You are close. Technique #1 above is what you want, but as you discovered the enml property is private in the "default" SDK. Import the "advanced" header and you'll have access to note.content.enml. That is a string, and you can send it to convertENMLtoHTML if you prefer an HTML representation.
Do note that there is no "plaintext" string content for an existing note. You'll always see it as markup, and if you want to get rid of the markup, doing so is beyond the scope of the SDK-- how to do that depends very much on what the content you're dealing with looks like.
You should check out their samples included with SDK, seems like
-[ENNote generateWebArchiveData:] will get you HTML NSData in the completion block
https://github.com/evernote/evernote-cloud-sdk-ios/blob/master/Getting_Started.md#downloading-and-displaying-an-existing-note might also help

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

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.

GAIDictionaryBuilder fails for NSNumber values

I am trying to send commerce transaction data to google analytics on iOS with V3 SDK. I am building the data dictionary using GAIDictionaryBuilder class provided by Google (which is not open source unfortunately). For both createTransactionWithId and createItemWithTransactionId calls, my NSNumber values (revenue, price, etc.) are failing to be added to dictionary data properly. Here is the sample code:
NSMutableDictionary* test = [[GAIDictionaryBuilder createTransactionWithId:(NSString *)transactionId
affiliation:(NSString *)affiliation
revenue:(NSNumber *)revenue
tax:(NSNumber *)tax
shipping:(NSNumber *)shipping
currencyCode:(NSString *)currencyCode] build];
NSLog(#"revenue: %#", revenue);
NSLog(#"TR data: %#", test);
// if I explicitly set the value, IT WORKS!!!!
[test setObject:revenue forKey:#"&tr"];
NSLog(#"TR data FIXED??: %#", test);
In the output, I see revenue correctly, then when logging test dictionary I see the following line corresponding to revenue data:
"&tr" = "<null>";
Then, for the manual fix attempt, I see
"&tr" = "15.25";
as expected.
Here are some clues:
I use the same code in a different project compiled in a different OSX machine without any issues like this.
The transactions are in TRY (Turkish Lira), I suspect Google is trying to fix the separator (',' in Turkish vs '.' everywhere else), but as said above, the other app is also using TRY.
So the question is, why "<null>", why and how does it fail to convert a proper NSNumber to this bizarre value?
Eventually, I fixed the issue by working around it. I assigned the NSNumber to a new one (by getting its floatValue) and it seemed to fix the null values.
By the way, google analytics library version 3.07 readme mentions a similar issue as fixed however neither 3.03 nor 3.07 actually fixed my problem.

AFNetworking 2 AFHTTPRequestOperation failure block stripping keys from error userInfo

I have just updated my app from AFNetworking 1.3.3 to 2.0.1, which required rewriting my network client that used to subclass AFHTTPClient.
I swapped out AFHTTPClient for AFHTTRequestOperationManager (I need to support iOS 6) and everything works fine apart from this:
The server gives me a JSON error string with the details of the error in:
error.userInfo.localizedRecoverySuggestion
However, this key (localizedRecoverySuggestion) is no longer in my NSError object.
Does anybody any idea how I can access it? Or what part of AFNetworking is stripping it out? The server is still sending it, it just doesn't make it as for as the error object in my POST: etc methods.
I've spent some time on this and I'm struggling to find where the issue is.
After a spot of debugging, it looks like the data takes the following path through AFNetworking:
AFURLConnectionManager connection:didReceiveData:
AFURLResponseSerialization validateResponse:data:error:
At which point it is thrown away.
So as a quick fix I just added an extra dictionary entry to that method where userInfo is created as follows:
NSLocalizedRecoverySuggestionErrorKey: [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]
This is obviously a complete hack, but if anyone could give a pointer on how to accomplish this correctly, I'd be very grateful.

Resources