Extensions

RSS for tag

Give users access to your app's functionality and content throughout iOS and macOS using extensions.

Posts under Extensions tag

200 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Using MatterSupport framework to add Matter device to our system
1, I add an Matter extension named TRMatterExtension, using the Template in Xcode. 2, check the InfoPlist with the TRMatterExtension module, I see the NSExtension key with two key which are like this: 3,The RequestHandler.swift file is like this: import os import MatterSupport let logger = Logger(subsystem: "com.airdroitech.commissionMtr2", category: "MatterExtension") // The extension is launched in response to MatterAddDeviceRequest.perform() and this class is the entry point // for the extension operations. class RequestHandler: MatterAddDeviceExtensionRequestHandler { override init() { logger.log("QAWI3 - init") super.init() } override func validateDeviceCredential(_ deviceCredential: MatterAddDeviceExtensionRequestHandler.DeviceCredential) async throws { // Use this function to perform additional attestation checks if that is useful for your ecosystem. logger.log("QAWI3 - validateDeviceCredential") } override func selectWiFiNetwork(from wifiScanResults: [MatterAddDeviceExtensionRequestHandler.WiFiScanResult]) async throws -> MatterAddDeviceExtensionRequestHandler.WiFiNetworkAssociation { // Use this function to select a Wi-Fi network for the device if your ecosystem has special requirements. // Or, return `.defaultSystemNetwork` to use the iOS device's current network. logger.log("QAWI3 - Returning default system network") return .defaultSystemNetwork } override func selectThreadNetwork(from threadScanResults: [MatterAddDeviceExtensionRequestHandler.ThreadScanResult]) async throws -> MatterAddDeviceExtensionRequestHandler.ThreadNetworkAssociation { // Use this function to select a Thread network for the device if your ecosystem has special requirements. // Or, return `.defaultSystemNetwork` to use the default Thread network. return .defaultSystemNetwork } override func commissionDevice(in home: MatterAddDeviceRequest.Home?, onboardingPayload: String, commissioningID: UUID) async throws { // Use this function to commission the device with your Matter stack. logger.log("QAWI3 - Starting commissioning flow") } override func rooms(in home: MatterAddDeviceRequest.Home?) async -> [MatterAddDeviceRequest.Room] { // Use this function to return the rooms your ecosystem manages. // If your ecosystem manages multiple homes, ensure you are returning rooms that belong to the provided home. return [.init(displayName: "Living Room")] } override func configureDevice(named name: String, in room: MatterAddDeviceRequest.Room?) async { // Use this function to configure the (now) commissioned device with the given name and room. } } 4, I add Privacy - Local Network Usage Description and Bonjour services [ _matter._tcp _matterc._udp _matterd._udp ] to the main target's InfoPlist. 5, click a button to call MatterAddDeviceRequest.perform(), the code is as the following: let homes = [MatterAddDeviceRequest.Home(displayName: "TRHome")] let topology = MatterAddDeviceRequest.Topology(ecosystemName: "TR", homes: homes) let request = MatterAddDeviceRequest(topology: topology) do { try await request.perform() print("Successfully set up device!") } catch { print("Failed to set up device with error: (error)") } 6, Result: Most times, Matter devices can be added to the KeyChain and the commission window of the Matter device could be opened. But sometimes the MatterSupport window will show "Pairing Failed". The total error is: [1E1D8753] Failed to perform Matter device setup setup: Error Domain=HMErrorDomain Code=18 "Pairing Failed" UserInfo={HFErrorUserInfoOptionsKey={ HFErrorUserInfoOptionDescriptionKey = "Pairing Failed"; HFErrorUserInfoOptionTitleKey = "\U65e0\U6cd5\U6dfb\U52a0\U914d\U4ef6"; }, NSLocalizedDescription=Pairing Failed, NSUnderlyingError=0x3009e8240 {Error Domain=HAPErrorDomain Code=15 "Failed to pair Matter Accessory in time" UserInfo={NSLocalizedDescription=Failed to pair Matter Accessory in time, NSUnderlyingError=0x3009e86c0 {Error Domain=HAPErrorDomain Code=24 "(null)"}}}}. From the log I can see, the Function selectWiFiNetwork(from wifiScanResults: [MatterAddDeviceExtensionRequestHandler.WiFiScanResult]) async throws -> MatterAddDeviceExtensionRequestHandler.WiFiNetworkAssociation of the RequestHandler.swift file will be called and commissionDevice(in home: MatterAddDeviceRequest.Home?, onboardingPayload: String, commissioningID: UUID) will NOT called. Sometimes the RequestHandler class will not be called at all, this means the first function validateDeviceCredential will not be called. But ,when this happens, the iPhone will Continuously can NOT add device for a long time, sometimes it gets better inexplicably. Even under normal circumstances, the probability of successfully adding a device is less than 50% and very slowly. When using Apple Home app, the success rate is very high, almost 100%, and very fast. So, can you help me identify where the problem is and what areas need attention? Thank you very much! Finally, I often encounter logs like this: nw_browser_dns_service_browse_callback [B3] not in ready or waiting state Do you know what it means and whether it will affect the equipment distribution network? My testing machine is iPhone 12, operating on iOS 18 and above 17.0. Thank you very much!
3
0
322
Sep ’24
How to contact the NSFileProviderDomainUsageDescription
Hi,Regarding FileProvider, I know it has a permission authorization pop-up to control whether to open the FileProvider extension in the application settings But when I first used it, the switch was turned off by default. I noticed that some applications can pop up an authorization pop-up to prompt the user to turn on this permission I would like to ask what API this authorization pop-up is displayed through I expect the authorization pop-up window to pop up as shown in the following picture Thanks
2
0
279
Sep ’24
Use of Auth-plugin and certificate-based persistent token for User login
I'm currently exploring Apple's Auth-Plugin extension and have modified the authdb to log in to a Mac device without using the default login password. Specifically,I am replacing builtin:authenticate,privileged with a custom privileged mechanism that authenticates the user and grants desktop access based on our custom logic. However, this approach does not unlock the user's Keychain. Since I'm bypassing the login password, the Keychain remains locked. I'm considering whether a certificate-based persistent token could be used to unlock the Keychain. Is this approach recommended, or is there a more suitable solution, such as using CryptoTokenKit or another available API?
1
0
343
Sep ’24
How to I archive macros into a static library as xcframework?
I'm trying to make an xcframework from my static library (SPM btw) with macros. My script doesn't work properly My SPM declaration of macros: // swift-tools-version: 5.9 // The swift-tools-version declares the minimum version of Swift required to build this package. import CompilerPluginSupport import PackageDescription let package = Package( name: "SomeMacr", platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .macCatalyst(.v13)], products: [ .library( name: "SomeMacr", targets: ["SomeMacr"] ), .executable( name: "SomeMacrClient", targets: ["SomeMacrClient"] ) ], dependencies: [ .package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0") ], targets: [ .macro( name: "SomeMacrMacros", dependencies: [ .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), .product(name: "SwiftCompilerPlugin", package: "swift-syntax") ] ), .target(name: "SomeMacr", dependencies: ["SomeMacrMacros"]), .executableTarget(name: "SomeMacrClient", dependencies: ["SomeMacr"]), .testTarget( name: "SomeMacrTests", dependencies: [ "SomeMacrMacros", .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax") ] ) ] ) My .sh script: xcodebuild archive \ -scheme $1 \ -sdk iphoneos \ -archivePath "Products/archives/ios_devices.xcarchive" \ SKIP_INSTALL=NO \ BUILD_LIBRARY_FOR_DISTRIBUTION=YES xcodebuild archive \ -scheme $1 \ -sdk iphonesimulator \ -archivePath "Products/archives/ios_simulators.xcarchive" \ SKIP_INSTALL=NO \ BUILD_LIBRARY_FOR_DISTRIBUTION=YES xcodebuild archive \ -scheme $1 \ -sdk macosx \ -archivePath "Products/archives/macos.xcarchive" \ SKIP_INSTALL=NO \ BUILD_LIBRARY_FOR_DISTRIBUTION=YES xcodebuild -create-xcframework \ -library Products/archives/ios_devices.xcarchive/Products/Library/Frameworks/lib$1.a \ -library Products/archives/ios_simulators.xcarchive/Products/Library/Frameworks/lib$1.a \ -library Products/archives/macos.xcarchive/Products/Library/Frameworks/lib$1.a \ -output Products/xc/$1.xcframework It requires destination (But in other tutorials, authors clearly shows, that after this script I will get an xcframework) xcodebuild: error: Building a Swift package requires that a destination is provided using the "-destination" option. The "-showdestinations" option can be used to list the available destinations But when I setup the destination it was compiled to exec file, which I don't mind how to include to another SPM package / or xcframework What am I doing wrong?
4
0
283
Oct ’24
Safari Extension Stops on iOS 17.5.1 - 18
We are encountering an issue where the Safari extension we are developing stops working while in use on relatively new iOS versions (confirmed on 17.5.1, 17.6.1, and 18). Upon checking the Safari console, the content script is displayed in the extension script, so the background script or Service Worker must be stopping. The time until it stops is about 1 minute on 17.5.1 and about one day on 17.6.1 or 18. When it stops, we would like to find a way to restart the Service Worker from the extension side, but we have not found a method to do so yet. To restart the extension, the user needs to turn off the corresponding extension in the iPhone settings and then turn it back on. As mentioned in the following thread, it is written that the above bug was fixed in 17.6, but we recognize that it has not been fixed. https://forums.developer.apple.com/forums/thread/758346 On 17.5.1, adding the following process to the background script prevents it from stopping for about the same time as on 17.6 and above. // Will be passed into runtime.onConnect for processes that are listening for the connection event const INTERNAL_STAYALIVE_PORT = "port.connect"; // Try wake up every 9S const INTERVAL_WAKE_UP = 9000; // Alive port var alivePort = null; // Call the function at SW(service worker) start StayAlive(); async function StayAlive() { var wakeup = setInterval(() => { if (alivePort == null) { alivePort = browser.runtime.connect({ name: INTERNAL_STAYALIVE_PORT }); alivePort.onDisconnect.addListener((p) => { alivePort = null; }); } if (alivePort) { alivePort.postMessage({ content: "ping" }); } }, INTERVAL_WAKE_UP); } Additionally, we considered methods to revive the Service Worker when it stops, which are listed below. None of the methods listed below resolved the issue. ① Implemented a process to create a connection again if the return value of sendMessage is null. The determination of whether the Service Worker has stopped is made by sending a message from the content script to the background script and checking whether the message return value is null as follows. sendMessageToBackground.js let infoFromBackground = await browser.runtime.sendMessage(sendParam); if (!infoFromBackground) { // If infoFromBackground is null, Service Worker should have stopped. browser.runtime.connect({name: 'reconnect'}); // ← reconnection process // Sending message again infoFromBackground = await browser.runtime.sendMessage(sendParam); } return infoFromBackground.message; Background script browser.runtime.onConnect.addListener((port) => { if (port.name !== 'reconnect') return; port.onMessage.addListener(async (request, sender, sendResponse) => { sendResponse({ response: "response form background", message: "reconnect.", }); }); ② Verified whether the service worker could be restarted by regenerating Background.js and content.js. sendMessageToBackground.js export async function sendMessageToBackground(sendParam) { let infoFromBackground = await browser.runtime.sendMessage(sendParam); if (!infoFromBackground) { executeContentScript(); // ← executeScript infoFromBackground = await browser.runtime.sendMessage(sendParam); } return infoFromBackground.message; } async function executeContentScript() { browser.webNavigation.onDOMContentLoaded.addListener((details) => { browser.scripting.executeScript({ target: { tabId: details.tabId }, files: ["./content.js"] }); }); } However, browser.webNavigation.onDOMContentLoaded.addListener was not executed due to the following error. @webkit-masked-url://hidden/:2:58295 @webkit-masked-url://hidden/:2:58539 @webkit-masked-url://hidden/:2:58539 ③ Verify that ServiceWorker restarts by updating ContentScripts async function updateContentScripts() { try { const scripts = await browser.scripting.getRegisteredContentScripts(); const scriptIds = scripts.map(script => script.id); await browser.scripting.updateContentScripts(scriptIds);//update content } catch (e) { await errorLogger(e.stack); } } However, scripting.getRegisteredContentScripts was not executed due to the same error as in 2. @webkit-masked-url://hidden/:2:58359 @webkit-masked-url://hidden/:2:58456 @webkit-masked-url://hidden/:2:58456 @webkit-masked-url://hidden/:2:58549 @webkit-masked-url://hidden/:2:58549 These are the methods we have considered. If anyone knows a solution, please let us know.
1
1
340
3w
iOS 18 ShareExtension openURL:
When I write code in shareExtension like below: dispatch_async(dispatch_get_global_queue(0, 0), ^{ UIResponder *responder = [self nextResponder]; while ((responder = [responder nextResponder]) != nil) { if ([responder respondsToSelector:@selector(openURL:)] == YES) { [responder performSelector:@selector(openURL:) withObject:[NSURL URLWithString:APP_SCHEME]]; break; } } }); Will output in the console: BUG IN CLIENT OF UIKIT: The caller of UIApplication.openURL(:) needs to migrate to the non-deprecated UIApplication.open(:options:completionHandler:). Force returning false (NO).
4
1
1.2k
Sep ’24
A server with the specified hostname could not be found exception
Hi, I have been working on the app that implements DNS Proxy Extension for a while now, and after a couple builds to TestFlight I noticed that I got a couple crashes that seem to be triggered by EXC_BREAKPOINT (SIGTRAP) After some investigation, it was found that crashes are connected to CFNetwork framework. So, I decided to additionally look into memory issues, but I found the app has no obvious memory leaks, no memory regression (within recommended 25%, actual value is at 20% as of right now), but the app still uses 11mb of memory footprint and most of it (6.5 mb is Swift metadata). At this point, not sure what's triggering those crashes, but I noticed that sometimes app will return message like this to the console (this example is for PostHog api that I use in the app): Task <0ABDCF4A-9653-4583-9150-EC11D852CA9E>.<1> finished with error [18 446 744 073 709 550 613] Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." UserInfo={_kCFStreamErrorCodeKey=8, NSUnderlyingError=0x1072df0f0 {Error Domain=kCFErrorDomainCFNetwork Code=-1003 "(null)" UserInfo={_kCFStreamErrorDomainKey=12, _kCFStreamErrorCodeKey=8, _NSURLErrorNWResolutionReportKey=Resolved 0 endpoints in 2ms using unknown from cache, _NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, uses wifi}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalUploadTask <0ABDCF4A-9653-4583-9150-EC11D852CA9E>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalUploadTask <0ABDCF4A-9653-4583-9150-EC11D852CA9E>.<1>" ), NSLocalizedDescription=A server with the specified hostname could not be found., NSErrorFailingURLStringKey=https://us.i.posthog.com/batch, NSErrorFailingURLKey=https://us.i.posthog.com/batch, _kCFStreamErrorDomainKey=12} If DNS Proxy Provider uses custom DoH server for resolving packets, could the cache policy for URLSession be a reason? I had a couple other ideas (HTTP3 failure, CFNetwork core issues like described here) but not sure if they are valid Would be grateful if someone could give me a hint of what I should look at
18
0
764
3w
What happened to logging in a Message Filter Extension on iOS 18?
If an app with a Message Filter Extension is run on an iPhone with iOS 18 installed then there's no logging output to the console (using print or NSLog), however there is logging in all previous versions of OS. Being able to view logging at run time for this component is essential as a debugging aid to see, for example, if the extension launches, if a text is handled locally or deferred to the network, to see if there's a network error, to examine the server response etc. Is there a specific reason it was disabled or is it accidental? Thank you
2
0
274
Oct ’24
Change in iOS 18 prevents SwiftData synchronization between main app and extension
I have a Live Activity with a button that updates a SwiftData model. This used to work in iOS 17, but not on iOS 18. The reason is that in iOS 17, when you run an AppIntent from a Live Activity, the perform() method would run in the main app's process, meaning it had access to the app's ModelContainer/ModelContext. However, in iOS 18, this is no longer the case, and the perform() method of an AppIntent now runs in the extension's process. While I can still construct a new ModelContainer & ModelContext in the AppIntent's perform() method, the main app's container and context will not see these changes until the app is relaunched. How can I make this work in iOS 18 now that an AppIntent executed from an extension runs in a different process from the main app?
1
0
401
Sep ’24
Workaround for Activating Content Filter via CLI with GUI App on macOS
Hi all, I would like to know if it is possible to activate a content filter through the command line interface (CLI). Based on my research, it seems that Apple does not allow this for security design reasons. If it’s indeed not permitted, is there a way to use a GUI-based app as a workaround, where the GUI would only serve the purpose of activating the content filter? After the filter is activated, I’d like to hide the GUI app and run the content filter in the background. Is this approach feasible, and what would be the best way to achieve it? Thanks in advance for your help!
1
0
179
Sep ’24
Syncing changes between main app and extension
I have an app that starts a Live Activity on a certain user action. This Live Activity contains a button that the user can tap, which updates a SwiftData model instance. However, when you return to the main app after tapping the button on the Live Activity, the views do not update to reflect the changes, even though the changes were written to the database. The underlying issue here is that the ModelContainer/ModelContext used by the AppIntent (performed from the LiveActivity when the button is tapped), are different from the instances in the main app. Meaning that while the changes are written to the underlying storage, the in-memory instances of ModelContext/ModelContainer in the main app don't get the changes from the extension, so SwiftUI doesn't update either. What is the recommended way to handle this scenario? Or is there one? :) Shared access to a SwiftData container is clearly supported through App Groups, so is there not a mechanism to ensure changes made by an extension are updated in real-time for the main app? Otherwise, it seems I would have to go through and manually rerun queries that views depend on to make sure they are showing the most recent data. This is cumbersome and error-prone. Perhaps I'm missing something? Any suggestions would be greatly appreciated.
3
0
439
Sep ’24
ControlWidget can't open APP
My custom control widget is show up and I can set it to Lock Screen, but it doesn't launch my app when I clicked it. any problem? in A.swift file, code like below: @available(iOS 18.0, *) struct LockScreenAppLaunchWidget: ControlWidget { var body: some ControlWidgetConfiguration { StaticControlConfiguration(kind: "abc") { ControlWidgetButton(action: LaunchAppIntent()) { // <-- HERE Label("Something", systemImage: "arrow.up") } } .displayName("Open app") } } @available(iOS 18, *) struct LaunchAppIntent: AppIntent { static var title: LocalizedStringResource = "ABC" static var description: IntentDescription? = "abcd" static var openAppWhenRun: Bool = true @MainActor func perform() async throws -> some IntentResult & OpensIntent { return .result() } }
2
1
285
Sep ’24
SFSafariApplication::dispatchMessage() in xcode 16
We are making Safari extension for MacOS, that uses SFSafariApplication.dispatchMessage() to communicate between native and javascript parts of extension. Until recently everything worked, however after update to xcode 16 I started getting this error: 'dispatchMessage(withName:toExtensionWithIdentifier:userInfo:completionHandler:)' is unavailable in application extensions for macOS: Not available to extensions 'dispatchMessage(withName:toExtensionWithIdentifier:userInfo:completionHandler:)' has been explicitly marked unavailable here (SafariServices.SFSafariApplication) I looked into documentation, however I did not find any hint of dispatchMessage() being replaced by something else. According to https://developer.apple.com/documentation/safariservices/messaging-between-the-app-and-javascript-in-a-safari-web-extension this is the way communication should be done. Is it a bug? Or can someone direct me to working alternative of communication?
6
0
426
Sep ’24