I'm trying to call my local API to turn off my house lighting from my watch, but I'm having trouble with calling a url from within the watchkit extension.
In my ViewController (iPhone app) I've got exactly the same code (which works), but somehow it doesn't work when I call it in the InterfaceController from the Watchkit Extension.
#IBAction func confirmTapped() {
let url = NSURL(string: "http://homeserver.local/api/lights/4/0")
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
print(NSString(data: data!, encoding: NSUTF8StringEncoding))
}
task!.resume()
}
I've also attached a gist: https://gist.github.com/f72125cd4678069af7af.git
Am I missing something obvious?
While Frederick's advice was solid advice for WatchKit 1, openParentApplication:reply is no longer available in WatchKit 2. With WatchKit 2, you would instead definitely open the NSURLSession in the WatchKit App Extension itself, because using a WCSession means that the URL would only be opened if and when the iPhone application itself is running, either in the foreground or if it happens to still be running in the background because the system has not closed it.
It is possible that the problems you were experiencing were because you needed to add the 'Allows Arbitrary Loads' property on the WatchKit App Extension. See discussion in this possibly related thread: NSURLSession returns data as Null on Watch OS2 using Objective-C
I don't know if it's a good thing to start a NSURLSession from within the Watch extension. If the request takes to long, it will be cancelled.
Maybe you could ping the watch via openParentApplication:reply and handle the NSURLSession on your iPhone app.
Related
I'm currently developing an App that contains a XPC Service embedded.
The App starts in background and communicates with the XPC Service in order to make the service move the mouse from time to time.
My app review by Apple returned this:
Guideline 2.4.5(v) - Performance
Your app requests admin access in order to function.
- App requires Accessibility in order to function.
Resources
An informational video concerning requesting access from users is available from our WWDC 2019 conference. See the Advances in macOS Security video.
AppDelegate.swift
func applicationDidFinishLaunching(_ aNotification: Notification) {
connection = NSXPCConnection(serviceName: "com.some.ServiceName")
connection?.remoteObjectInterface = NSXPCInterface(with: MyHelperXPCProtocol.self)
connection?.resume()
}
MyHelperXPC.swift (XPC Service Target)
import Foundation
import Cocoa
#objc class MyHelperXPC: NSObject, MyHelperXPCProtocol {
func terminateHelper() {
}
/* This function triggers the dialog informing that the app would like
to control this computer using accessibility features. */
func activate(duration: TimeInterval) {
CGEvent(mouseEventSource: nil, mouseType: CGEventType.mouseMoved, mouseCursorPosition: point, mouseButton: CGMouseButton.left)?.post(tap: CGEventTapLocation.cghidEventTap)
}
}
When the function 'activate' is called this dialog is shown:
The user now have to unlock Security & Privacy preferences and check my App.
After this, my application can now move the mouse without a problem.
XPC Service Info.plist contains:
com.apple.security.app-sandbox = 1
App Info.plist contains:
Application is background only = YES
The question is, how can I understand better this App Store rejection and fix it?
My App and XPC Service are signed with a Developer ID Application.
I'm using Xcode 12.4, macOS Big Sur and swift 5, not using frameworks.
After appealing to the Apple Review Board, turned out that moving the mouse using the Accessibility is considered inappropriate.
I understand that using the Accessibility this way exploits the feature originally designed to make your app more accessible for people.
They also wrote that will look into other apps that have the same functionality because they may be considered inappropriate as well.
I am developing a Cocoa app that using TwilioVideo. Since TwilioVideo SDK is only built for iOS and not worked for macOS so I wanted to create an approach using Twilio with the shared weblink and work it with WKWebView in Cocoa. I start with
let pRoom = URL(string: "https://meetingroomfortwilio.com/room/roomid")!
let request = URLRequest(url: pRoom)
videoWebView.load(request)
in viewDidLoad method.
It opened the communication web page but with error like below.
I searched for error and learned that these problems via Twilio official API errors page.
The Client may not be using a supported WebRTC implementation.
The Client may not have the necessary resources to create or apply a new media description.
So, good or bad, I have to implement a video call system in Cocoa for the app.
How can I implement supported WebRTC implementation for my app in Cocoa?
What would you do for a building an app with WebRTC (video & voice call)?
Is opened a Safari browser from the app good approach for building this and can I track the browser which I opened for the video-voice call, situations like success, error?
I would like to learn how to achieve the problem, maybe in different ways?
Thanks in advance!
I am looking for the watchkit extension to read a file from iCloud document storage. I wrote the file from the iOS app which is also able to read it. I am leveraging a shared class so the code is the same. The problem is that on the watch, the URL for the cloud container returns nil.
static func readFromFile(fileName:String) -> String?
{
let fileManager = FileManager.default
var cloudURL = fileManager.url(forUbiquityContainerIdentifier: nil)
cloudURL = cloudURL?.appendingPathComponent("Documents/\(fileName)")
do
{
return try String(contentsOf: cloudURL!)
} catch {
print (error)
return nil
}
In the case above, cloudURL is nil on the watch but not the phone. For the forUbiquityContainerIdentifier I checked that the same identifier is used for both watch and phone. I have also tried to directly enter the name rather than using nil and letting it grab it from the entitlements. The format of the container:
iCloud.com.company.app
It's my understanding that Watch OS 3 is supposed to be able to use iCloud.
Update:
I printed out let token = fileManager.ubiquityIdentityToken and I get the following:
WatchKit Extension[390:687462] [default] [ERROR] error while getting
ubiquityIdentityToken: Error Domain=NSCocoaErrorDomain Code=4099 "The
connection to service named com.apple.bird.token was invalidated."
UserInfo={NSDebugDescription=The connection to service named
com.apple.bird.token was invalidated.}
I have officially heard back from Apple that this is not a supported feature of Watch OS. This runs contrary to their own documentation which I let them know about. Hopefully others see this response and it can save a ton of time that I wound up wasting.
It was 2021. Apple documentation still says that iCloud Drive methods can be used by watchOS 2.0+, but url forUbiquityContainerIdentifier returns nil :(
I want to send a dictionary from iPhone to Watchkit in watchOS 2.
In watchOS 1 it works fine for me with appgroups but in watchOS 2 I know that we have to use WCSession but I don't know how to use it.
Please help me find the solution.
This blog post should help you out.
From that post: First, you'll create and activate a WCSession like so:
if (WCSession.isSupported()) {
let session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
}
For transferring a dictionary:
let applicationDict = // Create a dict of application data
let transfer = WCSession.defaultSession().transferUserInfo(applicationDict)
Then, on the receiving end, you'll need to implement session:didReceiveUserInfo: (Developer documentation). Note, according to Apple's "watchOS2 Transition Guide,"
To begin communication, both your Watch app and your iOS app must have an active WCSession object. Typically, each app creates, configures, and activates a session object at launch time and stores a reference to it in a central location. When you want to send data, you retrieve the session object and call its methods.
Here's what I'm up to:
I now have
An iPhone app
A WatchKit Extension
A Cocoa Touch Framework that holds all my shared classes
What I would like to accomplish, is having a persistent storage (Core Data) that is shared between my iPhone app and WatchKit Extension.
So this is what I've done so far
Create an app group to have a shared container.
Add a Core Data Model (Model.xcdatamodeld) to my Cocoa Touch Framework.
Created one Entity in this model
Created an NSMangedObject subclass for this entity and added is to my Cocoa Touch Framework
Added a DataManager class to my Cocoa Touch Framework
Here what the initializer in my DataManager looks like
public init() {
let sharedContainerURL: NSURL? = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.com.company.Project")
if let sharedContainerURL = sharedContainerURL {
let storeURL = sharedContainerURL.URLByAppendingPathComponent("Model.sqlite")
MagicalRecord.setupCoreDataStackWithAutoMigratingSqliteStoreAtURL(storeURL)
let station: Station? = Station.MR_createEntity()
}
}
The issue I'm running into
When I init my DataManager from the iPhone app's AppDelegate, no crash occures, but station will be nil.
When I replace the last line with let stations: [Station]? = Station.MR_findAll() as? [Station] the app crashes and shows the following error: A fetch request must have an entity.
I've searched all of SO and Magical Records issues on GitHub, but couldn't find anything to push me in the right direction. All help is much appreciated.
Thanks to Leo Natan's comment I now realize that I should store my core data in both my iPhone app's sandbox as well as in my WatchKit app's sandbox. And not inside a shared container, like I was trying to.
When building for Watch OS 2, I'll be able to use the WatchKit Connectivity Framework to keep both databases in sync. In the meanwhile I could use a solution like MMWormhole to achieve the same thing.
I have done my task in my live app with watch and iPhone both. i not needs 2 stores. and MMWormhole is good one to help for instant call back both the sides. also i have handled watch's event by handleWatchKitExtensionRequest.
The sync is proper and works well.
I have followed this forum. - http://www.makeandbuild.com/blog/post/watchkit-with-shared-core-data
Hope this may help you.