AppleWatch Messages URL works hard coded but not with variables
My guess is that it is not the acctual openSystemUrl
call that is the problem. I believe there must be something with the code that is building the number string programmatically.
The code bellow is a simplified version of all the code you have posted. I have confirmed that it is working on my Apple Watch. It opens the Messages app with pre-populated numbers & body text.
Take one more look at your code and see if there is something your missing. If you can't find anything, just delete the code and re-write it, probably will be faster then spotting the weird issue.
Once again the code bellow is confirmed working as expected, so you should be able to get it to work. (or just copy & paste my code) :)
class InterfaceController: WKInterfaceController {
@IBAction func doItButton() {
if let urlSafeBody = createBody() {
if let url = NSURL(string: "sms:/open?addresses=\(createNumbers())&body=\(urlSafeBody)") {
print(url)
WKExtension.sharedExtension().openSystemURL(url)
}
}
}
private func createBody() -> String? {
let messageBody = "hello test message"
return messageBody.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
}
private func createNumbers() -> String {
let numbers = ["(111) 222-3333", "(444) 555-6666"]
var tempArray: [String] = []
numbers.forEach { (number: String) in
tempArray.append(number.digitsOnly())
}
return tempArray.joinWithSeparator(",")
}
}
extension String {
func digitsOnly() -> String{
let stringArray = self.componentsSeparatedByCharactersInSet(
NSCharacterSet.decimalDigitCharacterSet().invertedSet)
let newString = stringArray.joinWithSeparator("")
return newString
}
}
With above said I would recommend against using undocumented Apple features for anything you plan on putting on the App Store for the reasons already mentioned in comments.
Opening iMessage with default body containing a link
You need to escape the content passed into the &body=
parameter. You can do this with addingPercentEncoding.
For example:
let body = "Download SomeApp by clicking the link below:\n\nhttps://appsto.re/us/someapp.i"
guard let escapedBody = body.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else {
return
}
guard let phoneUrl = URL(string: "sms:\(numberTextField.text!)&body=\(escapedBody)") else {
return
}
session.dataTaskWithURL completionHandler never called
The task never completes because it never gets started. You have to manually start the data task using its resume()
method.
let urlPath = apiURL + apiVersion + url + "?api_key=" + apiKey
let url = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url) { data, response, error in
print("Task completed")
// rest of the function...
}
task.resume()
User-Notification Did Receive Response Method Does not allow me to Pass Updated Variable to UIApplication.shared.open() ?
After some demonstrated time, I am able to clarify this by doing this in the following way.
Firstly, function open(URL) was called before, so there was a need of putting my code in dependant blocks, i-e using IOS GCD (Grand Central Dispatch).
I've created two functions and putted them in dispatch_Group
.
Here is my code:
// Function A
func functionA_With_Dispatch(identif: String) -> String
{
dispatch_group.enter()
if identif.contains("sms")
{
var numbersH = ""
var messageH = ""
var schemeHere = ""
var chrArr = Array(identif.characters)
chrArr.removeFirst()
chrArr.removeFirst()
chrArr.removeFirst()
let notifIdentifierSecond = String(chrArr)
var fullNameArr = notifIdentifierSecond.characters.split{$0 == "_"}.map(String.init)
let numbers = fullNameArr[1]
messageH = fullNameArr[2]
numbersH.removeAll()
for c in numbers.characters
{
if c != " "
{
numbersH.append(c)
}
}
print(messageH)
print(numbersH)
// "sms:/open?addresses=1-408-555-1212,1-408-555-2121,1-408-555-1221&body=/*message*/"
//sms:/open?addresses=(555)564-8583&body=/*No Bofy*/
schemeHere = "sms:/open?addresses=1" + numbersH + "&body=" + "Wanted to Inform You!"
//schemeHere1-408-555-1212,1-408-555-2121,1-408-555-1221, = "sms:/open?addresses=542-342-3423,23232323&body=/*No Bofy*/"
//sms:/open?addresses=15555648583&body=Wanted to Inform You!
//Open sms:/open?addresses=1115555648583&body=lllll: true
schemeHere = "sms:/open?addresses=\(numbersH)&body=\(messageH)"
print(schemeHere)
dispatch_group.leave()
return schemeHere
}
dispatch_group.leave()
return "empty"
}
Other function for opening URL.
func open_URL_With_Dispatch(schemeHere : String)
{
dispatch_group.enter()
if let url = URL(string: schemeHere) {
print("Inside URL")
if #available(iOS 10, *) {
print("Now Doing in IOS 10.")
UIApplication.shared.open(url, options: [:],
completionHandler: {
(success) in
print("Open \(schemeHere): \(success)")
self.dispatch_group.leave()
})
} else {
let success = UIApplication.shared.openURL(url)
print("Open \(schemeHere): \(success)")
dispatch_group.leave()
}
}
else
{
print("Inside Scheme!")
print(schemeHere)
dispatch_group.leave()
}
}
Now in userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { }
, the work is here.
NOTE: dispatch_group
is declared at the top of the viewController.
dispatch_group = DispatchGroup()
let notifIdentifier = response.notification.request.identifier
self.reloadEasy()
let schemeHere = self.functionA_With_Dispatch(identif: notifIdentifier)
dispatch_group.wait()
/*
switch response.actionIdentifier {
case "action1":
if MFMessageComposeViewController.canSendText() {
print("SMS services are available")
self.sendMessage(recipients: ["243243"], message: "ewhrewuew")
}
else
{
self.showMessage(message: "Can't send sms!")
print("Can't send sms!")
}
default:
if MFMessageComposeViewController.canSendText() {
print("SMS services are available")
self.sendMessage(recipients: ["243243"], message: "ewhrewuew")
}
else
{
self.showMessage(message: "Can't send sms!")
print("Can't send sms!")
}
} // Message Switch
*/
let state: UIApplicationState = UIApplication.shared.applicationState
if state == .active {
self.showMessage(message: "Active")
//let schemeHere = "sms:/open?addresses=1-408-555-1212,1-408-555-2121,1-408-555-1221,92-315-5849537&body=/*message*/"
//self.open(notifIdentifier: notifIdentifier)
self.open_URL_With_Dispatch(schemeHere: schemeHere)
}
else if state == .background
{
self.showMessage(message: "Background")
//self.open(notifIdentifier: notifIdentifier)
self.open_URL_With_Dispatch(schemeHere: schemeHere)
}
else if state == .inactive
{
self.showMessage(message: "In-Active")
//let schemeHere = "sms:/open?addresses=14085551212,14085552121,14085551221,923155849537&body=/*message*/"
//self.open(notifIdentifier: notifIdentifier)
self.open_URL_With_Dispatch(schemeHere: schemeHere)
}
else
{
self.showMessage(message: "Un-defined State")
//let schemeHere = "sms:/open?addresses=14085551212,14085552121,14085551221,923155849537&body=/*message*/"
//self.open(notifIdentifier: notifIdentifier)
self.open_URL_With_Dispatch(schemeHere: schemeHere)
}
Secondly, I've found one other problem after doing so, where I was passing spaces and newLines in the URL string, but now I'm replacing them in the following way for the whole URL.
for c in messageHere.characters
{
if c == " "
{
appendedMessage.append("%20")
}
else if c == "\n"
{
appendedMessage.append("%0A")
}
else
{
appendedMessage.append(c)
}
}
Why is my variable returning a nil after being converted to an int?
Even simpler, though slightly a trick, you can use integerValue
:
temperatureString.integerValue
Unlike toInt
, integerValue
will stop converting when it finds a non-digit (it also throws away leading spaces.
If temperatureString
is a String
(rather than an NSString
), you'll need to push it over:
(temperatureString as NSString).integerValue
Passing data to Apple Watch app
This applies to OS 1 only. See below for better answers.
I got it working using your method. I guess there's a couple of things you can check:
1) Are you synchronising the defaults after you set the value:
defaults?.synchronize();
NSLog("%@ ", defaults?.dictionaryRepresentation())
2) Have you enabled the App Group in both your app and your extension?
3) Are you using the correctly named app group when constructing the NSDefaults? For example, I use:
NSUserDefaults(suiteName: "group.com.brindysoft.MyWatch");
Once all that's set up I run the app, set the value in the defaults, then run the glance target which reads the value from the default and that seems to work!
- Still stuck? check your app groups in your apple account
Related Topics
Command Failed Due to Signal: Segmentation Fault: 11 While Emitting Ir Sil Function
Swift: Reflecting Properties of Subclass of Nsmanagedobject
Nsinvocationoperation' Is Unavailable in Xcode 6.1
Avplayer Seektotime Not Working Properly
Why Specializing a Generic Function Explicitly Is Not Allowed
Protocol Can Only Be Used as a Generic Constraint
Spritekit: Howto Make Holes in Layer with Blendmode
Use of Undeclared Type Autoreleasingunsafepointer Xcode 6 Beta 6
How to Build a Swift Executable for Linux on Macos
Firebase and Reading Nested Data Using Swift
How to Detect Text View Begin Editing and End Editing in Swift 3
Can My Class Override Protocol Property Type in Swift
Swiftui: How to Switch to a New Navigation Stack with Navigationviews
Firebasecore Lexical or Preprocessor Issue
How to Initialize a Unichar Variable in Swift
Delay a Repeating Animation in Swiftui with Between Full Autoreverse Repeat Cycles