Xamarin - NSURL returning null - ios

I am building an app using Xamarin's Unified API and am creating a NSUrl with a string. However the app crashes as soon as I try to create the NSUrl.
string url = "comgooglemaps-x-callback://?daddr=" + destination;
NSUrl googleMapsURL = new NSUrl (url);
The value of url is comgooglemaps-x-callback://?daddr=600+Drake+Apartments\n600+Drake+St,+Vancouver+BC+V6B+5W7,+Canada
The message in the console is:
Could not initialize an instance of the type 'Foundation.NSUrl': the
native 'initWithString:' method returned nil. It is possible to ignore
this condition by setting
MonoTouch.ObjCRuntime.Class.ThrowOnInitFailure to false.
How do I fix this ?

This will work (tested with your above code).
using System.Web.Services;
...
string destination = System.Web.HttpUtility.UrlEncode(
"600 Drake Apartments\n600 Drake St, Vancouver BC V6B 5W7, Canada");
Now turns into
"comgooglemaps-x-callback://?daddr=600+Drake+Apartments%0a600+Drake+St%2c+Vancouver+BC+V6B+5W7%2c+Can…"
Add Reference System.Web.Services to the project. My guess is that your URL encoding, wherever it's coming from isn't compatible with what the Apple APIs expect.

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
}

How to get an image from server? or How to get NSData from NSUrl?

I am using xamarin.ios I have already uploaded a selected image to server. And I want to get it again. I am getting NSUrl as http://172.16.10.49/thunder_ex/backend/web/uploads/AppUserProfilePic/Profile_140.jpg . I want to use this NSUrl and show the image in UIImage. I tried
NSData data;
data = NSData.FromUrl(url);
profileImage.Image = UIImage.LoadFromData(data);
But I am getting data as null.
Your code should work, in fact it's very similar to the one I posted there.
If you get null it generally comes from either:
the URL, i.e. an invalid URL (that iOS does not like) will return `null; or
the downloaded data is not in a format that iOS supports.
The URL you provided does not seems to connect or load (from Chrome) for me. That could also be the reason (as the API does not have any other way to return an error condition).

Deprecated methods in xcode7/swift 2.0

I am in the middle of updating my app which was built in ios 8 to ios9 by using xcode7/swift 2.0. Like many other people, my app crashed very heavily. The basic concept of my app is to let users to upload videos/images to a certain event. Right now, I am having an error message saying
object not found for update (Code: 101, Version: 1.9.0)
from parse. I thought it was Parse's error at first but figured out I may have made some dumb mistakes while I was updating codes. If you can take a look at the changes I made and point out the errors I made, it would be super helpful.
I changed following:
var outputURL = NSURL.fileURLWithPath(NSTemporaryDirectory().stringByAppendingPathComponent("\(filename)").stringByAppendingString(".mp4"))
to
var outputURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent("\(filename).mp4")
I made this change because stringByAppendingString is deprecated now.
Other change i made is:
let filename = (outputFileUrl.absoluteString.stringByDeletingPathExtension.lastPathComponent ?? "video") + "-c"
to
let filename = (outputFileUrl.URLByDeletingPathExtension?.lastPathComponent ?? "video") + "-c"
I am pretty sure I did right with converting functions. It would be greatly appreciated if anyone can point out what I did wrong in those two changes.
The difference of the first example is:
The former syntax creates an NSString object
The new syntax creates an NSURL object
Either use the URL related API for example instead of …contentsOfFile use …contentsOfURL or get the path of the URL from the path property
let outputURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent("\(filename).mp4").path!
The second example returns a string with percent encoded special characters in the former syntax and a string without percent encoding in the new syntax. You might add the percent encoding.
An alternative method to keep the older syntax is to cast the String to NSString e.g.
let filename = (((outputFileUrl.absoluteString as NSString).stringByDeletingPathExtension as NSString).lastPathComponent ?? "video") + "-c"
but I recommend to use the URL related API

How to Hardcode a NSURL path?

So, this seems like it should be super easy, but i'm stumped...
I have an iOS application that I am developing where I am downloading video content from a server, storing it in a custom folder in the Documents, and upon a certain trigger, trying to play the video. I am experiencing some loading errors in my MovieViewController, so am trying to debug the NSURL that is constructed from the file path in a separate standalone application. It is worth noting that the same content works fine when added to the Bundle, but there's quite a lot, so can't afford to do that.
Anyways...
I have set breakpoints in my app and copied out the path of the NSURL that gets loaded into my movie player, and am attempting to hardcode it into an NSURL in my test app. But I can't seem to just assign it with a preexisting value... Eg.
NSURL *url = "file:///var/mobile/Containers/Data/Application/21078F3B-12C5-4D42-8B8B-3C85CB7A0A91/Documents/SecondStory/BloodAlley/MEDIA/copperthief.mp4"
(which is what I copied out of the Variables View of the Debug area).
It gives me the error:
*"Implicit conversion of a non-Objective-C pointer type 'char *' to 'NSURL ' is disallowed with ARC"
... which I cannot seem to track down on SO ....
Of course, I have the NSString representation of the file path before it gets converted to an NSURL, so can just try to reconstruct it, but this got me curious why I couldn't just assign a value...
As the error states, "file:///var/.../copperthief.mp4" is a char * not an NSURL.
To convert it to an NSURL, first you have to get the char *'s NSString representation by adding the # prefix:
#"file:///var/.../copperthief.mp4"
then convert the NSString to an NSURL using URLWithString::
[NSURL URLWithString:#"file:///var/.../copperthief.mp4"];
The first thing is that "..." is not an NSString. It's a C string. An NSString would be #"...", wouldn't it? And even then, if you wanted an NSURL, you'd have to convert from NSString to NSURL, wouldn't you? I mean, you can't assign a string of any kind to an NSSURL variable and expect it to work, can you? This is a computer language; you can't say just any old thing that comes into your head - you have to obey the rules.

Replacement for DeviceInfo in phonegap > 1.5

It seems that they have deprecated the Phonegap variable DeviceInfo as of Cordova 1.5 (I think I saw that it was technically deprecated for 1.5 as well, but left it in). I know there is the device variable, but I was using the DeviceInfo variable to store some of my own data via the callback to
- (NSDictionary*)deviceProperties{...}
It seems that function is still called for the var device data, but it doesn't let me add any data to that variable. Does anyone know if there is anyway to get back the functionality of having custom device data or is it gone forever?
OK so the workaround I came up with was to simply create the variable myself in a javascript call so that the rest of the javascript code still access it as needed. I etd a catagory to override
- (void)viewDidAppear:(BOOL)animated;
and in the implementation I called the following code
NSString* jsString = [NSString stringWithFormat:#"window.DeviceInfo = {param1:%#, param2:%#}}", param1, param2];
[self.viewController.webView stringByEvaluatingJavaScriptFromString:jsString];
That added code allowed for backward compatibility with code based on the editable DeviceInfo variable that has been removed.

Resources