Posts

Post not yet marked as solved
0 Replies
605 Views
I'm trying to invite an Apple ID as a search ads api user, however when I try to accept the invitation from the invited Apple ID, I get the error "Unable to create Search Ads Basic account". When I try to login directly to search ads using that account, I get the message "We're sorry. This Apple ID is no longer authorized for Apple Search Ads." I've also tried this with a separate Apple ID account, and the same problems happened. I've followed the steps in this article: https://searchads.apple.com/help/campaigns/0022-use-the-campaign-management-api Is there something I'm missing? Do I need to create a brand new Apple ID for this to work?
Posted
by FuzzyCap.
Last updated
.
Post not yet marked as solved
1 Replies
2.4k Views
To avoid using file URLs, I'm using the WKURLSchemeHandler to create a custom url to load my assets into a webview. This works great, except that certain ways of loading assets from the custom URL results in the error: Failed to load resource: Origin null is not allowed by Access-Control-Allow-Origin. Loading an asset in an image tag, css background property, or using a javascript import works. But using css mask, or javascript fetch does not. You can see the problem by right-clicking in the window, and clicking show developer tools. Css masks are used widely throughout the content in my webview, and I'm also using fetch. So I need both of these to work. What is causing this error? Why does it only happen when using certain methods of loading resources? import SwiftUI import WebKit struct ContentView: View {     var body: some View {         HTMLView().frame(maxWidth: .infinity, maxHeight: .infinity)     } } struct HTMLView: NSViewRepresentable {     func makeNSView(context: Context) -> WKWebView {         /* Create the custom url handler and webview */         let config = WKWebViewConfiguration()         config.setURLSchemeHandler(CustomURLHandler(), forURLScheme: "asset")         let webview = WKWebView(frame: .zero, configuration: config)         /* Enable developer tools so we can right click and show the inspector */     webview.configuration.preferences.setValue(true, forKey: "developerExtrasEnabled")         /* Example html that does and doesn't work: */         let html = """ <style> #box {     width: 100px;     height: 100px;     border: 1px solid green;     /* This works: */     background: url(asset://test.svg); } #box2 {     width: 100px;     height: 100px;     border: 1px solid red;     background: blue;     /* This does not work: */     -webkit-mask-image: url(asset://test.svg); } </style> <p>This box loads the asset using the background property:</p> <div id="box"></div> <p>This box results in the error, and doesn't show the image with the css mask:</p> <div id="box2"></div> <script> // Using javascript fetch also doesn't work: fetch('asset://test.svg')     .then(data => {         console.log('Success:', data);     })     .catch((error) => {         console.error('Error:', error);     }); </script> """         webview.loadHTMLString(html, baseURL: nil)         return webview     }     func updateNSView(_ nsView: WKWebView, context: Context) {} } class CustomURLHandler: NSObject, WKURLSchemeHandler {     func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {         guard let url = urlSchemeTask.request.url else {             return         }         /* Handle the custom url assets here. In this example I'm just returning a test svg: */         let testImage = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"><svg width=\"100%\" height=\"100%\" viewBox=\"0 0 19 18\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:space=\"preserve\" xmlns:serif=\"http://www.serif.com/\" style=\"fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;\"><g transform=\"matrix(1,0,0,1,-540,-709.618)\"><g transform=\"matrix(0.5,0,0,0.666667,467,536)\"><g transform=\"matrix(2,0,0,1.5,-934,-804)\"><path d=\"M549,712.6C550.895,709 554.684,709 556.579,710.8C558.474,712.6 558.474,716.2 556.579,719.8C555.253,722.5 551.842,725.2 549,727C546.158,725.2 542.747,722.5 541.421,719.8C539.526,716.2 539.526,712.6 541.421,710.8C543.316,709 547.105,709 549,712.6Z\" style=\"fill:rgb(255,0,0);\"/></g></g></g></svg>"         guard let data = testImage.data(using: .utf8) else { return }         let urlResponse = URLResponse(url: url, mimeType: "image/svg+xml", expectedContentLength: data.count, textEncodingName: nil)         urlSchemeTask.didReceive(urlResponse)         urlSchemeTask.didReceive(data)         urlSchemeTask.didFinish()     }     func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {} }
Posted
by FuzzyCap.
Last updated
.
Post not yet marked as solved
8 Replies
5.4k Views
I have a view which sends its size to a child, so the child can update its size relative to its parent. (The child needs to be able to respond to the parents size, and also update its own size from a drag event.) In the example below, the child sets its width to 40% of the parent in it's init. When the window is first shown, the child updates its width correctly. When you resize the window, however, the initializer is called and the size is recalculated, but the child never updates its width. The state seems to never update. When the code is called outside of the initializer (such as pressing a button) then the state updates correctly. Why doesn't the state update in the init after its called more than once? How would I accomplish this? struct ContentView: View {     var body: some View {         GeometryReader { geo in             ZStack {                 MyView(containerSize: geo.size)             }             .frame(maxWidth: .infinity, maxHeight: .infinity)             .border(Color.green, width: 1)         }     } } struct MyView: View {     let containerSize: CGSize     @State var realSize: CGSize     init(containerSize: CGSize) {         self.containerSize = containerSize         let newSize = CGSize(width: containerSize.width * 0.4, height: containerSize.height)         print("INIT", newSize)         _realSize = State(initialValue: newSize)     }     func updateWidth() {         realSize = CGSize(width: containerSize.width * 0.4, height: containerSize.height)     }     var body: some View {         ZStack {             Button(action: {                 self.updateWidth()             }) {                 Text("Update Width")             }         }         .frame(width: realSize.width, height: realSize.height)         .background(Color.blue)     } }
Posted
by FuzzyCap.
Last updated
.
Post not yet marked as solved
0 Replies
675 Views
I'm trying to create a note-taking like app that uses NSPersistentCloudKitContainer and core data. The store uses the NSMergeByPropertyObjectTrumpMergePolicy, which is fine for almost every property. For example, if the name of a file is changed on two different devices, then it's fine to use the latest value. The problem is that the note text cannot be overridden by the latest value if it's changed on two devices at once. It needs to be detected as a conflict so the user can choose which version they want to keep. I can replicate the behavior by turning off wifi on one device and writing content, then writing content on a different device at the same time. When I turn the wifi back on, whichever device saved the changes last completely overrides the other device's text. What I'd like to accomplish is detect when there is a conflict of text, then create a duplicate file called "Conflicted Copy." Bonus points if someone can tell me how Apple Notes magically merges text without ever creating a conflict. I really only need a simple solution though that prevents data loss. Any help in the right direction would be appreciated!
Posted
by FuzzyCap.
Last updated
.
Post not yet marked as solved
1 Replies
1.6k Views
I’m using the new StoreKit 2 APIs in my production app that sells a non-consumable iap. I’ve tested restoring purchases with a StorekitConfiguration in development, along with my own personal Apple ID in production and it works.  The problem is that I’m getting lots of users reporting that restore purchase does’t work on a consistent basis. So my question is, is there something in my production code that is wrong or broken? Or is this a common problem with end users themselves and not my app? My app used the old version of store kit previously, so could that cause this issue? I always recommend they make sure they’re signed in with the same Apple ID they purchased the app with. Sometimes recommending the user to quit and relaunch the app, or restart there computer fixes the issue. I’ve gotten multiple reports that the only fix was completely deleting then reinstalling the app. And there’s a good portion which non of the above work. Here’s the code that handles restoring purchases: /// Attempts to restore any purchases by the user. /// This is called by the restore purchase button public func restorePurchase() {     Task {         try? await AppStore.sync()         await updateActiveProducts()     } } /// Updates the status of which products have been purchased/are an active subscription @MainActor public func updateActiveProducts() async {     var purchasedIds: [String] = []     // Iterate through all of the user's purchased products.     for await result in Transaction.currentEntitlements {         do {             let transaction = try checkVerified(result)             // Has the App Store revoked this transaction?             // If it is upgraded do nothing, there is an active transaction for a higher level of service             if transaction.revocationDate != nil || transaction.isUpgraded {                 continue             }             // Check if the subscription is expired             if let expirationDate = transaction.expirationDate, expirationDate < Date() {                 continue             }             if transaction.productType == .nonConsumable || transaction.productType == .autoRenewable {                 purchasedIds.append(transaction.productID)             }         } catch { // Transaction not verified, don't do anything         }     } // This is a published property which unlocks the features of the app     self.purchasedIdentifiers = purchasedIds } Any advice would be appreciated!
Posted
by FuzzyCap.
Last updated
.
Post not yet marked as solved
0 Replies
1.3k Views
I'm trying to create a wrapper around a WKWebView for SwiftUI, and I'm not sure how to prevent a memory leak. I've created an ObservableObject which handles controlling the WebView, and a custom view that displays it: public class WebViewStore: ObservableObject { var webView: WKWebView = WKWebView() // List of event handlers that will be called from the WebView var eventHandlers: [String: () -> Void] = [:] deinit { // This is never called once an action has been set with the view, // and the content view is destroyed print("deinit") } // All the WebView code, including custom JavaScript message handlers, custom scheme handlers, etc... func reloadWebView() { } } The web view needs to be able to communicate with JavaScript, so I've added an onAction() method which gets called when the WebView gets a javascript event. View wrapper: struct WebView: NSViewRepresentable { let store: WebViewStore func makeNSView(context: Context) -> WKWebView { return store.webView } func updateNSView(_ view: WKWebView, context: Context) {} } extension WebView { /// Action event called from the WebView public func onAction(name: String, action: @escaping () -> Void) -> WebView { self.store.eventHandlers[name] = action return self } } Usage that creates the retain cycle: struct ContentView: View { @StateObject var store = WebViewStore() var body: some View { VStack { // Example of interacting with the WebView Button("Reload") { store.reloadWebView() } WebView(store: store) // This action closure captures the WebViewStore, causing the retain cycle. .onAction(name: "javascriptMessage") { print("Event!") } } } } Is there a way to prevent the retain cycle from happening, or is there a different SwiftUI pattern that can to handle this use case? I can't use [weak self] because the view is a struct. I need to be able to receive events from the WebView and vice versa.
Posted
by FuzzyCap.
Last updated
.
Post not yet marked as solved
0 Replies
733 Views
I have wrapped an NSOutlineView with NSViewRepresentable which works great. The problem is that when an item is expanded, the outline view doesn't change height and the animation doesn't work properly (see gif below). When I put the outline view in an NSScrollView, it works correctly, but I need to be able to put multiple outline views within a single SwiftUI scrollview. struct Test: View { var body: some View { ScrollView { SwiftUiOutline() // Ultimately I need multiple outline views here } } } struct SwiftUiOutline: NSViewRepresentable { func makeNSView(context: Context) -> NSOutlineView { let view = NSOutlineView() // Outline view is set up here, and connected to the coordinator delegate return view } class Coordinator: CustomOutlineViewController { // The coordinator handles all the outline view delegation, etc. } // ... } The problem: How it should work:
Posted
by FuzzyCap.
Last updated
.
Post marked as solved
1 Replies
1.2k Views
I need to be able to load an heic image and extract and output all of the sub images as pngs similar to how preview does it. For example, if you open a dynamic heic wallpaper in preview, it shows all the images in the sidebar with their names. How do you do this? I've tried to use NSImage like below. But that only outputs a single image: let image = NSImage(byReferencing: url) image.writePNG(toURL: newUrl)
Posted
by FuzzyCap.
Last updated
.
Post marked as solved
1 Replies
1.2k Views
My app lets you create projects which can hold images, and a file watcher watches the folders for changes. By default the images are stored in the application support folder, but I'm adding the ability to choose an external folder to save them too. The user chooses a folder with an NSOpenPanel, and the project loads the images in the folder. The folder location is then saved to a json file in the app's support folder. This works great, until the app is quit. When it launches again it can't read the contents of the folder anymore due to app sandbox. How do you retain the permission to read from a folder even after the app is quit? I've been searching for over a day, but can't find any current information. Any help would be appreciated!
Posted
by FuzzyCap.
Last updated
.
Post not yet marked as solved
0 Replies
816 Views
I've added iCloud into my SwiftUI app and everything seems to be working great, however I need to implement an on off toggle for it. After searching, I found a couple forums posts that suggested to re-create the container when icloud is toggled on off. Here's the code: lazy var persistentContainer: NSPersistentContainer = { &#9;&#9;return setupContainer() }() /* This is called when the iCloud setting is turned on and off */ func refreshCoreDataContainer() { &#9;&#9;/* Save changes before reloading */ &#9;&#9;try? self.persistentContainer.viewContext.save() &#9;&#9;/* Reload the container */ &#9;&#9;self.persistentContainer = self.setupContainer() } private func setupContainer() -> NSPersistentContainer { &#9;&#9;let useCloudSync = UserSettings.shared.enableiCloudSync &#9;&#9;let container: NSPersistentContainer! &#9;&#9;/* Use the icloud container if the user enables icloud, otherwise use the regular container */ &#9;&#9;if useCloudSync { &#9;&#9;&#9;&#9;container = NSPersistentCloudKitContainer(name: "App") &#9;&#9;} else { &#9;&#9;&#9;&#9;container = NSPersistentContainer(name: "App") &#9;&#9;&#9;&#9;let description = container.persistentStoreDescriptions.first &#9;&#9;&#9;&#9;description?.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) &#9;&#9;} &#9;&#9;container.persistentStoreDescriptions.first?.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) &#9;&#9;/* Load the data */ &#9;&#9;container.loadPersistentStores(completionHandler: { (storeDescription, error) in &#9;&#9;&#9;&#9;if let error = error as NSError? { &#9;&#9;&#9;&#9;&#9;&#9;fatalError("Unresolved error \(error), \(error.userInfo)") &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;container.viewContext.automaticallyMergesChangesFromParent = true &#9;&#9;}) &#9;&#9;return container } The problem is that once I reload the container, the app crashes with this error: Thread 1: "executeFetchRequest:error: A fetch request must have an entity." Multiple NSEntityDescriptions claim the NSManagedObject subclass 'App.ColorCollection' so +entity is unable to disambiguate. 'ColorCollection' (0x60f000022000) from NSManagedObjectModel (0x607000067260) claims 'App.ColorCollection'. I think the problem has to do with SwiftUI keeping a reference to the old container. When the window is created it is passing the container to it using the enviroment: let contentView = MyContentView().environment(\.managedObjectContext, persistentContainer.viewContext) So I tried to close the window, reload the container, then re create the window below, but the app still crashes. func refreshCoreDataContainer() { &#9;&#9;print("reload") &#9;&#9;windowController.window?.close() &#9;&#9;/* Save changes before continuing */ &#9;&#9;try? self.persistentContainer.viewContext.save() &#9;&#9;self.persistentContainer = self.setupContainer() &#9;&#9;self.createAndShowMainWindow() } How do I implement a iCloud toggle in SwiftUI without it crashing?
Posted
by FuzzyCap.
Last updated
.
Post not yet marked as solved
5 Replies
958 Views
We're working on an app that will need to access and manipulate the user's current desktop wallpaper.I can get the wallpaper path using NSWorkspace. The problem is that it's not readable when the app is sandboxed.guard let wallpaperUrl = NSWorkspace.shared.desktopImageURL(for: NSScreen.main!) else { return "" } // This doesn't read the wallpaper image print(NSImage(byReferencing: wallpaperUrl))The app will always need to get the wallpaper, so using an open file modal will not work, especially since the user might not know where the wallpaper is.I'd prefer not to require users to enable disk access before they can even use the app, because it's not a great first experience.Is there a way to do this without full disk access?
Posted
by FuzzyCap.
Last updated
.