How can I programmatically compose a message on Watch? - swift

How can I open the Messages app to the compose screen, with the message body preloaded with specific text?

Benjy's answer is almost correct, but has one issue.
Since urlSafeBody isn't unwrapped, string interpolation yields
sms:&body=Optional("Hello%20World!")
which is causing NSURL initialization to return nil, since the URL string is malformed.
Here's a working example which conditionally unwraps optionals. This removes any possibility of crashes related to nil optionals being force-unwrapped.
let messageBody = "Hello World!"
let urlSafeBody = messageBody.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
if let urlSafeBody = urlSafeBody, url = NSURL(string: "sms:&body=\(urlSafeBody)") {
WKExtension.sharedExtension().openSystemURL(url)
}

Thanks to #Jatin for finding the openSystemURL(url: NSURL) function.
Here's the code:
let messageBody = "Hello World!"
let urlSafeBody = messageBody.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
WKExtension.sharedExtension().openSystemURL(NSURL(string: "sms:&body=\(urlSafeBody)")!)

Related

My catch isn't working on url request

I am trying to do my first try catch in Swift.
Essentially the user can give a name to something. So say he/she types in Gmail and hits submit.
Since G is the first letter of the String (doesn't matter if its lower or upper case) the image will load a picture of a G.
If the user also adds in a URL so say gmail.com or www.gmail.com it will pull the favicon for gmail.
So far so good.
HOWEVER. If the person types gmailllllll.com
it loads a picture of a globe (which I think is the default)
What I am trying to do is only put the gmail favicon in the image view if it is actually the image. If it is nil then I want to put the image of the G which I provided.
I understand why my code isn't working. I just do not know how to add to it to do what I want.
DispatchQueue.main.async {
let myURLString: String = "http://www.google.com/s2/favicons?domain=\(self.serviceArray[row].serviceUrl)"
let myURL = URL(string: myURLString)
do {
let myData = try Data(contentsOf: myURL!)
cell.serviceLogoImage.image = UIImage(data: myData)
} catch {
cell.serviceLogoImage.image = UIImage.init(named: "\(self.getLetterOrNumberAndChooseImage(text: self.serviceArray[row].serviceName))")
}
}
Also, If the user were to type in www.go google.com
with the space it has an optional crashe!
I tried saying
if myData == nil {...}
But it says it always returns false...
Any help would be appreciated
Optional binding
This solution avoids force unwrapping (ie myURL!) with optional binding.
Note that try? returns an optional. It returns nil rather than throwing an error. It is appropriate when you want to handle all errors in the same way.
let myURLString: String = "http://www.google.com/s2/favicons?domain=\(self.serviceArray[row].serviceUrl)"
if let myURL = URL(string: myURLString), let myData = try? Data(contentsOf: myURL), let image = UIImage(data: myData) {
cell.serviceLogoImage.image = image
}
else {
cell.serviceLogoImage.image = UIImage.init(named: "\(self.getLetterOrNumberAndChooseImage(text: self.serviceArray[row].serviceName))")
}
This expression Data(contentsOf: myURL!) is unsafe. I think you expect it to raise an error, but it will just crash your code (by design) if the URL cannot be parsed. Here is a safe example:
if let url = URL(string:mystring) {
do {
let data = try Data(contentsOf:url)
} catch {
print ("network issue")
}
} else {
print("bad string")
}
First of all, never EVER use ! unless you are sure that there is a value and not nil because forced unwrapping will crash your entire app. Second of all, I don't really get what are you trying to do with that Dispatch. I mean, if the user hits submit, you should make a function for example and you would call that when the submit button is tapped.
I would write something like this:
func updateImage() {
var myData: Data?
let myURLString: String = "http://www.google.com/s2/favicons?domain=\(self.serviceArra‌​y[row].serviceUrl)"
let myURL = URL(string: myURLString)
if let url = myURL {
do {
myData = try Data(contentfOf: url)
} catch {
print("error")
}
}
if let data = myData {
cell.serviceLogo.image = UIImage(data: data)
} else {
cell.serviceLogo.image = UIImage.init(named: "\(self.getLetterOrNumberAndChooseImage(text: self.serviceArray[row].serviceName))")
}
I really can't figure out what you were trying with that Dispatch, but eventually I'm thinking that first you should use a Dispatch.global(qos: .background).async where you would first verify what the user has entered and eventually download the necessary photos and then, when you're trying to update the UI, you should come back to the main thread with Dispatch.main.async. I guess.

Can't Use String Variable in NSURL?

I have a variable copiedURL which contains a URL string, I am trying to use that string variable to display an image programmatically
let url = NSURL(string: copiedURL)
let data = NSData(contentsOfURL: url!)
let image2 = UIImage(data: data!)
When I build and run I get a EXC_BAD_INSTRUCTION error fatal error: unexpectedly found nil while unwrapping an Optional value
I am certain that copiedURL has a value because I used print() to debug and everything printed just fine.
Also, I also tried:
let url = NSURL(string: "\(copiedURL)")
but that didn't solve it.
NSURL(string:) is a failable initializer. In the case that the URL isn't valid, it will not initialize a new NSURL instance, but will instead return nil.
Check that your copiedURL is a valid URL.

Cannot subscript a value of type [NSURL]

I am getting the following error. Is there a way around this?
i want to read text file from URL
let requestURL: NSURL = NSURL(string: "http://www.xxxxx.com/file.txt")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
struct FactBook {
let factsArray = [requestURL]
//let factsArray = ["my text"] ---> is working
func randomFact() -> String {
let randomInt = Int(arc4random_uniform(UInt32(factsArray.count)))
//Error here...
return factsArray[randomInt]
}
}
thanks.
randomFact is declared to return a String, factsArray is an [NSURL], hence indexing it is an NSURL. Change the function type to:
func randomFact() -> NSURL {
and you should be good to go
Further observations:
You're not ever loading the contents of the URL, so it's not clear that even this change really solves your problem.
As it stands, there's only one element of factsArray so randomizing it seems pointless.
It seems likely you're really wanting to strings from the URL and then return a random element of the returned strings.

Why is the URL error occurring?

I am using the iTunes search API, and for testing I am searching for "Angry Birds" and printing the results. But when I convert the urlPath into NSURL I get a nil value. How do I fix this? The urlPath has the link, but it is nil in the url variable. This is the exact error:
fatal error: unexpectedly found nil while unwrapping an Optional value.
var searchTerm: String = "Angry Birds"
var itunesSearchTerm = searchTerm.stringByReplacingOccurrencesOfString(" ", withString: "+", options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil)
var escapedSearchTerm = itunesSearchTerm.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
var urlPath = "https://itunes.apple.com/search?term=\(escapedSearchTerm)&media=software"
var url: NSURL = NSURL(string: urlPath)!
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)!
print("Search iTunes API at URL \(url)")
connection.start()
stringByAddingPercentEscapesUsingEncoding returns an Optional String, so what you get is actually this:
https://itunes.apple.com/search?term=Optional("Angry+Birds")&media=software
The solution is to safely unwrap the Optional:
if let escapedSearchTerm = itunesSearchTerm.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {
let urlPath = "https://itunes.apple.com/search?term=\(escapedSearchTerm)&media=software"
let url = NSURL(string: urlPath)
// ...
}
Result:
https://itunes.apple.com/search?term=Angry+Birds&media=software
NSURL returns nil when URL contain illegal characters like space. Verify that your URlString is correct one.

NSMutableDictionary path "unexpectedly found nil while unwrapping an Optional value"

I have a simple:
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String
let dataPath = documentsPath.stringByAppendingPathComponent("Images")
let imagesPath = dataPath.stringByAppendingPathComponent(fileName)
var dictionary = NSMutableDictionary(contentsOfFile: imagesPath)!
And after it gets to the last line it crashes and gives me the ol'
fatal error: unexpectedly found nil while unwrapping an Optional value
The variable fileName is declared as var fileName: String!
I'm unable to write to the path as well. What am I doing wrong?
Another potential issue in addition to gnasher729's suggestion is that the contentsOfFile initializer for NSDictionaries and their subclasses:
Return Value:
An initialized dictionary—which might be different than the original receiver—that contains the dictionary at path, or nil if there is a file error or if the contents of the file are an invalid representation of a dictionary.
So if there is an issue with that dictionary, when you force unwrap it in this line
var dictionary = NSMutableDictionary(contentsOfFile: imagesPath)!
it will crash.
Declaring a fileName as String! means it might not contain a String, but you are quite sure it does, and you accept that your app crashes if you use the variable fileName and it doesn't contain a String. That seems to be the case here.
As others have noted, the problem is likely to be one of the force unwrapped optionals that you are using. There's a reason why a ! is sometimes referred to as a Bang!. They have a tendency to blow up :) Unwrapping things one at a time and using some print statements will help you find out what went wrong:
if let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as? String,
let filePath = filePath {
println("Determined that both documentsPath and filePath are not nil.")
let dataPath = documentsPath.stringByAppendingPathComponent("Images")
let imagesPath = dataPath.stringByAppendingPathComponent(fileName)
if let dictionary = NSMutableDictionary(contentsOfFile: imagesPath) {
println("Determined that dictionary initialized correctly.")
// do what you want with dictionary in here. If it is nil
// you will never make it this far.
}
}