Post

Replies

Boosts

Views

Activity

Reply to Background Audio Recording
I don't think there is a workaround. They tell you when you are allowed to use the background mode. https://developer.apple.com/documentation/xcode/configuring-background-execution-modes If you use the background mode for a different purpose, it seems that you violate the Guideline 2.5.4. Also, if you make an audio recording without user's consent, you may violate Guideline 2.5.14.
Mar ’25
Reply to Guideline 4.0 - Design
Your use of SignInWithAppleButton is not clear. AuthenticationServices lets you find out whether or not the user is able to sign in on their device. In other words, it tells you whether the app is being used by the valid owner of the device. AuthenticationServices does not necessarily disclose user's e-mail address. So why are you using it?
Mar ’25
Reply to Different Build Schemes -> Error: -Onone Swift optimization level to use previews
Hello, Paris and DTS. My sample iOS app doesn't crash if I run it with a simulator or an actual device although the preview canvas shows an error for a selective build scheme. So I am afraid that I have nothing to report to you. I have installed the said profile as shown below. It's hard to locate the one that I need to look for since the list has several dozen items. Yet, based on Today's date, I don't find one. So what's next?
Feb ’25
Reply to Guideline 4.3(a) - Design - Spam - automatic rejection
You are not going to get anywhere by seeking advice here when it comes to getting your app rejected. It's true that the reviewers can get wrong occasionally. So do I and get my software titles rejected occasionally with mistakes on my side. If your app is rejected for the spam reason, listen to the reviewer and ask them questions. If you already have a similar app at App Store or Mac App Store, you are likely to be advised to provide it as an add-on feature to an existing title. If you have sold a similar product to one retailer and are trying to sell a similar one to another retailer, you are not going anywhere. I'm sure you are not telling us the whole story. So, again, read what the reviewer has said. It's up to you to listen to the reviewer and make changes to software.
Topic: Design SubTopic: General Tags:
Jan ’25
Reply to Showing SwiftUI Below NSStatusItem When Button is Clicked on Over SwiftUI View
I've gotten the following lines of code working. import SwiftUI @main struct MyStatusApp_App: App { #if os(macOS) @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate #endif @StateObject private var statusBarViewModel = StatusBarViewModel() var body: some Scene { WindowGroup { ContentView() .onDisappear { NSApplication.shared.terminate(self) } .environmentObject(statusBarViewModel) } .defaultSize(width: 640, height: 360) } } #if os(macOS) class AppDelegate: NSObject, NSApplicationDelegate { let fileManager = FileManager.default func applicationDidFinishLaunching(_ notification: Notification) { hideTitleBar() NSApp.setActivationPolicy(.accessory) } func applicationWillFinishLaunching(_ notification: Notification) { NSWindow.allowsAutomaticWindowTabbing = false } } #endif // ContentView.swift // import SwiftUI struct ContentView: View { @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate @EnvironmentObject var statusBarViewModel: StatusBarViewModel var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Button("Click me!") { if let statusItem = statusBarViewModel.statusItem { if let button = statusItem.button { if statusBarViewModel.popover == nil { let popover = NSPopover() statusBarViewModel.popover = popover popover.behavior = .transient popover.animates = false popover.contentViewController = NSHostingController(rootView: NotificationView()) } statusBarViewModel.popover?.show(relativeTo: button.bounds, of: button, preferredEdge: .minY) } } } } .frame(width: 200, height: 100) .onAppear { statusBarViewModel.makeStatusMenu() } } } class StatusBarViewModel: ObservableObject { @Published var statusItem: NSStatusItem! @Published var popover: NSPopover? func makeStatusMenu() { statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) if let button = statusItem.button { if let image = NSImage(named: "statusImage") { button.image = image } } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’24
Reply to Unarchiving an object with custom classes
Thank you for your kind assistance, The Eskimo. Your unarchivedObject(ofClasses:from:) doesn't even include NSDictionary, NSArray, NSString? The unarchivedObject guy is quite confusing. I have minimized my work like the following to see how the guy works. import Cocoa class ViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() } @IBAction func saveClicked(_ sender: NSButton) { showSavePanel() } @IBAction func openClicked(_ sender: NSButton) { showOpenPanel() } func showSavePanel() { let panel: NSSavePanel = NSSavePanel() ... if (panel.runModal().rawValue == NSApplication.ModalResponse.cancel.rawValue) { return } else { showSavePanelNext(fileURL: panel.url!) } } func showSavePanelNext(fileURL: URL) { let codeModel = CodeModel2(identifier: UUID().uuidString, highlightIndex: 1) NSKeyedArchiver.setClassName("CodeModel2", for: CodeModel2.self) do { let data = try NSKeyedArchiver.archivedData(withRootObject: codeModel, requiringSecureCoding: false) try data.write(to: fileURL, options: .atomicWrite) } catch { print("Error: \(error.localizedDescription)") } } func showOpenPanel() { let panel = NSOpenPanel() ... if (panel.runModal().rawValue == NSApplication.ModalResponse.cancel.rawValue) { return } else { showOpenPanelNext(fileURL: panel.url!) } } func showOpenPanelNext(fileURL: URL) { do { NSKeyedUnarchiver.setClass(CodeModel2.self, forClassName: "CodeModel2") let data = try! Data(contentsOf: fileURL) if let dict = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSDictionary.self, NSString.self, CodeModel2.self], from: data) { if let model = dict as? CodeModel2 { let id = model.identifier print("**** \(id)") } } else { print("What!?") } } } } class CodeModel2: NSObject, NSSecureCoding { class var supportsSecureCoding: Bool { true } let identifier: String let highlightIndex: Int init(identifier: String, highlightIndex: Int) { self.identifier = identifier self.highlightIndex = highlightIndex } required init(coder decoder: NSCoder) { self.identifier = decoder.decodeObject(forKey: "identifier") as! String self.highlightIndex = decoder.decodeInteger(forKey: "highlightIndex") } func encode(with coder: NSCoder) { coder.encode(identifier, forKey: "identifier") coder.encode(highlightIndex, forKey: "highlightIndex") } } It's a simple example, and it works. The following doesn't. dict doesn't return a value. import Cocoa class ViewController: NSViewController { func showSavePanelNext(fileURL: URL) { let codeDataModel = CodeDataModel(lastComponent: "hello.png", data: Data("World!".utf8)) let codeModel = CodeReadModel(identifier: UUID().uuidString, highlightIndex: 2, codeDataModels: [codeDataModel]) NSKeyedArchiver.setClassName("CodeReadModel", for: CodeReadModel.self) NSKeyedArchiver.setClassName("CodeDataModel", for: CodeDataModel.self) do { let data = try NSKeyedArchiver.archivedData(withRootObject: codeModel, requiringSecureCoding: false) try data.write(to: fileURL, options: .atomicWrite) } catch { print("Error: \(error.localizedDescription)") } } func showOpenPanel() { let panel = NSOpenPanel() panel.allowsMultipleSelection = false panel.canChooseDirectories = false panel.canCreateDirectories = false panel.canChooseFiles = true panel.allowedContentTypes = [.text] panel.title = "Open me!" panel.message = "" //panel.directoryURL = NSURL.fileURL(withPath: openPath) if (panel.runModal().rawValue == NSApplication.ModalResponse.cancel.rawValue) { return } else { showOpenPanelNext(fileURL: panel.url!) } } func showOpenPanelNext(fileURL: URL) { do { NSKeyedUnarchiver.setClass(CodeReadModel.self, forClassName: "CodeReadModel") NSKeyedUnarchiver.setClass(CodeDataModel.self, forClassName: "CodeDataModel") let data = try! Data(contentsOf: fileURL) if let dict = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSDictionary.self, NSArray.self, NSString.self, CodeReadModel.self, CodeDataModel.self], from: data) { if let model = dict as? CodeReadModel { let id = model.identifier print("**** \(id)") } } else { print("What!?") } } } } class CodeDataModel: NSObject, NSSecureCoding { class var supportsSecureCoding: Bool { true } let lastComponent: String let data: Data init(lastComponent: String, data: Data) { self.lastComponent = lastComponent self.data = data } required init(coder decoder: NSCoder) { self.lastComponent = decoder.decodeObject(forKey: "lastComponent") as! String self.data = decoder.decodeObject(forKey: "data") as! Data } func encode(with coder: NSCoder) { coder.encode(lastComponent, forKey: "lastComponent") coder.encode(data, forKey: "data") } } class CodeReadModel: NSObject, NSSecureCoding { class var supportsSecureCoding: Bool { true } let identifier: String let highlightIndex: Int let codeDataModels: [CodeDataModel] init(identifier: String, highlightIndex: Int, codeDataModels: [CodeDataModel]) { self.identifier = identifier self.highlightIndex = highlightIndex self.codeDataModels = codeDataModels } required init(coder decoder: NSCoder) { self.identifier = decoder.decodeObject(forKey: "identifier") as! String self.highlightIndex = decoder.decodeInteger(forKey: "highlightIndex") self.codeDataModels = decoder.decodeObject(forKey: "codeDataModels") as! [CodeDataModel] } func encode(with coder: NSCoder) { coder.encode(identifier, forKey: "identifier") coder.encode(highlightIndex, forKey: "highlightIndex") coder.encode(codeDataModels, forKey: "codeDataModels") } }
Topic: App & System Services SubTopic: General Tags:
Jul ’24
Reply to Unarchiving an object with custom classes
Silly me... I would have been more productive if I have taken a closer look at the topic that I have accepted as an answer here. Nonetheless, I still don't get it. I have done many variations like the following. if let dict = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSDictionary.self, NSArray.self, NSString.self, CodeReadModel.self, CodeDataModel.self, NSString.self], from: data) { print("**** \(dict)") } else { print("What!?") } They all go to the second print.
Topic: App & System Services SubTopic: General Tags:
Jul ’24
Reply to Does it possible to release another online version of exist app
If you publish a software title that shares same features with an existing one, it can be rejected. Some reviewers check and see if you already have one or more similar titles. You can get a flat rejection. Or they may suggest that you provide new features as add-ons to an existing software title. So you may consider offering in-app purchases. Of course, you can play dumb and submit a new title, which carries a risk of being rejected not now but later on.
Feb ’24
Reply to Background Audio Recording
I don't think there is a workaround. They tell you when you are allowed to use the background mode. https://developer.apple.com/documentation/xcode/configuring-background-execution-modes If you use the background mode for a different purpose, it seems that you violate the Guideline 2.5.4. Also, if you make an audio recording without user's consent, you may violate Guideline 2.5.14.
Replies
Boosts
Views
Activity
Mar ’25
Reply to Apple Developer Certificate not recognized for codesigning
Have you double-clicked on the certificate after opening it with Keychain and clicked on the Trust disclosure button to make it certified?
Replies
Boosts
Views
Activity
Mar ’25
Reply to Guideline 4.0 - Design
Your use of SignInWithAppleButton is not clear. AuthenticationServices lets you find out whether or not the user is able to sign in on their device. In other words, it tells you whether the app is being used by the valid owner of the device. AuthenticationServices does not necessarily disclose user's e-mail address. So why are you using it?
Replies
Boosts
Views
Activity
Mar ’25
Reply to Release Build Configuration as Release Fails Preview
I guess I know what needs -Onone Swift optimization level to use previews means. I need to select No Optimization [-Onone] under Swift Compiler -Code Generation in Build Settings. Yet, it doesn't resolve the preview issue.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Mar ’25
Reply to Different Build Schemes -> Error: -Onone Swift optimization level to use previews
Hello, Paris and DTS. My sample iOS app doesn't crash if I run it with a simulator or an actual device although the preview canvas shows an error for a selective build scheme. So I am afraid that I have nothing to report to you. I have installed the said profile as shown below. It's hard to locate the one that I need to look for since the list has several dozen items. Yet, based on Today's date, I don't find one. So what's next?
Replies
Boosts
Views
Activity
Feb ’25
Reply to Guideline 4.3(a) - Design - Spam - automatic rejection
You are not going to get anywhere by seeking advice here when it comes to getting your app rejected. It's true that the reviewers can get wrong occasionally. So do I and get my software titles rejected occasionally with mistakes on my side. If your app is rejected for the spam reason, listen to the reviewer and ask them questions. If you already have a similar app at App Store or Mac App Store, you are likely to be advised to provide it as an add-on feature to an existing title. If you have sold a similar product to one retailer and are trying to sell a similar one to another retailer, you are not going anywhere. I'm sure you are not telling us the whole story. So, again, read what the reviewer has said. It's up to you to listen to the reviewer and make changes to software.
Topic: Design SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jan ’25
Reply to Showing SwiftUI Below NSStatusItem When Button is Clicked on Over SwiftUI View
I've gotten the following lines of code working. import SwiftUI @main struct MyStatusApp_App: App { #if os(macOS) @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate #endif @StateObject private var statusBarViewModel = StatusBarViewModel() var body: some Scene { WindowGroup { ContentView() .onDisappear { NSApplication.shared.terminate(self) } .environmentObject(statusBarViewModel) } .defaultSize(width: 640, height: 360) } } #if os(macOS) class AppDelegate: NSObject, NSApplicationDelegate { let fileManager = FileManager.default func applicationDidFinishLaunching(_ notification: Notification) { hideTitleBar() NSApp.setActivationPolicy(.accessory) } func applicationWillFinishLaunching(_ notification: Notification) { NSWindow.allowsAutomaticWindowTabbing = false } } #endif // ContentView.swift // import SwiftUI struct ContentView: View { @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate @EnvironmentObject var statusBarViewModel: StatusBarViewModel var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Button("Click me!") { if let statusItem = statusBarViewModel.statusItem { if let button = statusItem.button { if statusBarViewModel.popover == nil { let popover = NSPopover() statusBarViewModel.popover = popover popover.behavior = .transient popover.animates = false popover.contentViewController = NSHostingController(rootView: NotificationView()) } statusBarViewModel.popover?.show(relativeTo: button.bounds, of: button, preferredEdge: .minY) } } } } .frame(width: 200, height: 100) .onAppear { statusBarViewModel.makeStatusMenu() } } } class StatusBarViewModel: ObservableObject { @Published var statusItem: NSStatusItem! @Published var popover: NSPopover? func makeStatusMenu() { statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) if let button = statusItem.button { if let image = NSImage(named: "statusImage") { button.image = image } } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Aug ’24
Reply to All Item Row Positions After List onMove(perform:)
Actually, all I have to do is enumerate an array inside the onMove(perform:) guy.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
Boosts
Views
Activity
Aug ’24
Reply to The Mystery of an Array of Strings and Escaped Characters
Mistake... I meant to leave a comment.
Replies
Boosts
Views
Activity
Aug ’24
Reply to Unarchiving an object with custom classes
Oops... I've changed class CodeReadModel: NSObject, NSCoding {} to class CodeReadModel: NSObject, NSSecureCoding {} The dict guy now returns a value.
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jul ’24
Reply to Unarchiving an object with custom classes
Thank you for your kind assistance, The Eskimo. Your unarchivedObject(ofClasses:from:) doesn't even include NSDictionary, NSArray, NSString? The unarchivedObject guy is quite confusing. I have minimized my work like the following to see how the guy works. import Cocoa class ViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() } @IBAction func saveClicked(_ sender: NSButton) { showSavePanel() } @IBAction func openClicked(_ sender: NSButton) { showOpenPanel() } func showSavePanel() { let panel: NSSavePanel = NSSavePanel() ... if (panel.runModal().rawValue == NSApplication.ModalResponse.cancel.rawValue) { return } else { showSavePanelNext(fileURL: panel.url!) } } func showSavePanelNext(fileURL: URL) { let codeModel = CodeModel2(identifier: UUID().uuidString, highlightIndex: 1) NSKeyedArchiver.setClassName("CodeModel2", for: CodeModel2.self) do { let data = try NSKeyedArchiver.archivedData(withRootObject: codeModel, requiringSecureCoding: false) try data.write(to: fileURL, options: .atomicWrite) } catch { print("Error: \(error.localizedDescription)") } } func showOpenPanel() { let panel = NSOpenPanel() ... if (panel.runModal().rawValue == NSApplication.ModalResponse.cancel.rawValue) { return } else { showOpenPanelNext(fileURL: panel.url!) } } func showOpenPanelNext(fileURL: URL) { do { NSKeyedUnarchiver.setClass(CodeModel2.self, forClassName: "CodeModel2") let data = try! Data(contentsOf: fileURL) if let dict = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSDictionary.self, NSString.self, CodeModel2.self], from: data) { if let model = dict as? CodeModel2 { let id = model.identifier print("**** \(id)") } } else { print("What!?") } } } } class CodeModel2: NSObject, NSSecureCoding { class var supportsSecureCoding: Bool { true } let identifier: String let highlightIndex: Int init(identifier: String, highlightIndex: Int) { self.identifier = identifier self.highlightIndex = highlightIndex } required init(coder decoder: NSCoder) { self.identifier = decoder.decodeObject(forKey: "identifier") as! String self.highlightIndex = decoder.decodeInteger(forKey: "highlightIndex") } func encode(with coder: NSCoder) { coder.encode(identifier, forKey: "identifier") coder.encode(highlightIndex, forKey: "highlightIndex") } } It's a simple example, and it works. The following doesn't. dict doesn't return a value. import Cocoa class ViewController: NSViewController { func showSavePanelNext(fileURL: URL) { let codeDataModel = CodeDataModel(lastComponent: "hello.png", data: Data("World!".utf8)) let codeModel = CodeReadModel(identifier: UUID().uuidString, highlightIndex: 2, codeDataModels: [codeDataModel]) NSKeyedArchiver.setClassName("CodeReadModel", for: CodeReadModel.self) NSKeyedArchiver.setClassName("CodeDataModel", for: CodeDataModel.self) do { let data = try NSKeyedArchiver.archivedData(withRootObject: codeModel, requiringSecureCoding: false) try data.write(to: fileURL, options: .atomicWrite) } catch { print("Error: \(error.localizedDescription)") } } func showOpenPanel() { let panel = NSOpenPanel() panel.allowsMultipleSelection = false panel.canChooseDirectories = false panel.canCreateDirectories = false panel.canChooseFiles = true panel.allowedContentTypes = [.text] panel.title = "Open me!" panel.message = "" //panel.directoryURL = NSURL.fileURL(withPath: openPath) if (panel.runModal().rawValue == NSApplication.ModalResponse.cancel.rawValue) { return } else { showOpenPanelNext(fileURL: panel.url!) } } func showOpenPanelNext(fileURL: URL) { do { NSKeyedUnarchiver.setClass(CodeReadModel.self, forClassName: "CodeReadModel") NSKeyedUnarchiver.setClass(CodeDataModel.self, forClassName: "CodeDataModel") let data = try! Data(contentsOf: fileURL) if let dict = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSDictionary.self, NSArray.self, NSString.self, CodeReadModel.self, CodeDataModel.self], from: data) { if let model = dict as? CodeReadModel { let id = model.identifier print("**** \(id)") } } else { print("What!?") } } } } class CodeDataModel: NSObject, NSSecureCoding { class var supportsSecureCoding: Bool { true } let lastComponent: String let data: Data init(lastComponent: String, data: Data) { self.lastComponent = lastComponent self.data = data } required init(coder decoder: NSCoder) { self.lastComponent = decoder.decodeObject(forKey: "lastComponent") as! String self.data = decoder.decodeObject(forKey: "data") as! Data } func encode(with coder: NSCoder) { coder.encode(lastComponent, forKey: "lastComponent") coder.encode(data, forKey: "data") } } class CodeReadModel: NSObject, NSSecureCoding { class var supportsSecureCoding: Bool { true } let identifier: String let highlightIndex: Int let codeDataModels: [CodeDataModel] init(identifier: String, highlightIndex: Int, codeDataModels: [CodeDataModel]) { self.identifier = identifier self.highlightIndex = highlightIndex self.codeDataModels = codeDataModels } required init(coder decoder: NSCoder) { self.identifier = decoder.decodeObject(forKey: "identifier") as! String self.highlightIndex = decoder.decodeInteger(forKey: "highlightIndex") self.codeDataModels = decoder.decodeObject(forKey: "codeDataModels") as! [CodeDataModel] } func encode(with coder: NSCoder) { coder.encode(identifier, forKey: "identifier") coder.encode(highlightIndex, forKey: "highlightIndex") coder.encode(codeDataModels, forKey: "codeDataModels") } }
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jul ’24
Reply to Unarchiving an object with custom classes
Silly me... I would have been more productive if I have taken a closer look at the topic that I have accepted as an answer here. Nonetheless, I still don't get it. I have done many variations like the following. if let dict = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSDictionary.self, NSArray.self, NSString.self, CodeReadModel.self, CodeDataModel.self, NSString.self], from: data) { print("**** \(dict)") } else { print("What!?") } They all go to the second print.
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jul ’24
Reply to Unarchiving an object with custom classes
Thank you for your kind reply, Eskimo. The first topic that you have mentioned is mine. And it deals with a [String : Any] object. This topic doesn't. codeReadModel is not a [String : Any] object. I suppose that the second one deals with an array of objects. I don't know about the third one, though.
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jul ’24
Reply to CoreBluetooth Central, Observing Multiple Peripherals
Actually, I'm not so sure if I should use CoreBluetooth for my objective.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Mar ’24
Reply to Does it possible to release another online version of exist app
If you publish a software title that shares same features with an existing one, it can be rejected. Some reviewers check and see if you already have one or more similar titles. You can get a flat rejection. Or they may suggest that you provide new features as add-ons to an existing software title. So you may consider offering in-app purchases. Of course, you can play dumb and submit a new title, which carries a risk of being rejected not now but later on.
Replies
Boosts
Views
Activity
Feb ’24