Post

Replies

Boosts

Views

Activity

What restrictions does didReceiveRemoteNotification have when the app is started in background by the system?
I previously posted a topic about receiving application(_:didReceiveRemoteNotification:fetchCompletionHandler:) callback when my app is not running, and the system starts the app in the background to respond to a notification. While I receive the callback reliably, the work performed by the callback seems to have different restrictions whether the app is in the background or not running. When the app is running in the background, the work started in this callback completes reliably (in my case it takes no more than a few seconds), and I can post the result back to the system via the completion handler. When the app is not running and the system starts it in the background, the app starts the same work, but this work seems to be terminated quickly without being able to complete, and without me being able to call the completion handler passed to the callback. I’m not talking about 30 seconds - the termination seems to happen after less than a second, which is not enough for my app. The nature of the work shouldn’t matter, but just in case: I start a Task in the callback for some asynchronous work, which stores the completion handler, and calls back to it when the work is finished. This happens completely reliably when the app is running in the background, and not at all reliably when the app is not running and is started by the system. Why would application(_:didReceiveRemoteNotification:fetchCompletionHandler:) behave differently based on if it is ran when the app is already running, vs not running and started by the system? Is there anything I can do on my side to make it more reliable?
2
0
337
Sep ’24
How do I test if my app is restarted correctly when receiving push notifications?
To receive silent push notifications in the background, I need to include content-available payload into my APNS push notification, and have application(_:didReceiveRemoteNotification:fetchCompletionHandler:) implemented. When I send a push notification, my app receives and handles it with the above method. This works correctly and is straightforward to test when the app is running in foreground or background on my device. I would like to test if my app is woken up correctly from scratch and does the above work. But how do I do this? How do I get my app into the state where it is started when it receives a silent push notification? When the user force-kills the app, the notification is not delivered. This is also the case when I as a developer force-kill the app which I am testing. I assume it also applies when I force-stop the app running on my device from within Xcode. Is there any way for me as a developer to terminate the app, which does not count as “force killing”, and would reliably start the app when it receives the background notification?
3
0
351
Sep ’24
Xcode Cloud build gets stuck after completion?
Recently, I have trouble with my Xcode Cloud builds, where they seemingly complete, but the very final step does not happen. I am building from the same codebase for both macOS and iOS (I have two “Archive” steps in my workflow, one for iOS and one for macOS). The iOS one usually completes fast without problems. The macOS log ending looks like this, and remains stuck forever, with the macOS build in the “spinning progress” state and never completing. Is there something I can do on my end to make this work better? I would not want to go back to manual builds, Xcode Cloud is convenient and was working well for a while, but this is really annoying lately.
2
0
2.1k
Nov ’22
Can I use OSLogStore to access logs from earlier runs of my app?
I understand that in iOS 15 and macOS Monterey, I can easily access the log system to get log entries for my app like this: let store = try OSLogStore(scope: .currentProcessIdentifier) I can then query store for the log entries. However, as it says right in the name, the store is only for current process, i.e current run of my app. When I try to get entries, I only get entries from the current run, even if I specify an earlier time like this: guard let positionDate = Calendar.current.date(byAdding: .day, value: -7, to: Date()) else { return } let position = store.position(date: positionDate) let predicate = NSPredicate(format: "subsystem == 'com.exampl.emyAppSubsystem'") let entries = try store.getEntries(with: [], at: position, matching: predicate) for entry in entries { print("Entry: \(entry.date) \(entry.composedMessage)") } Is there any way to access log entries for earlier runs of my app, e.g from days or weeks ago? Either on macOS or iOS?
7
0
3.8k
Sep ’21
How do CloudKit containers handle app transfers?
I’m slightly confused about how are CloudKit containers supposed to handle app transfers. I’m seeing some strange too-permissive security behavior, and I am not sure whether this is a feature or a bug 🙂Here’s the setup:I had an app with bundleID com.example.something, talking to a CloudKit container also called com.example.something, all under the same developer account A. All was well.I then transferred the app from developer account A to developer account B. The bundle ID or anything else about the app did not change, just the ownership. Must now also sign new builds of the app with credentials for account B, as expected. HOWEVER: the CK container also did not change at all, and remained under development account A.What I am seeing now: the app signed by developer account B can still access the CK container under developer account A. No bundle IDs or CK ID-s changed, so I can sort of understand this, but at the same time, it seems strange.There is no security risk to my data, as this app only uses "read" operation of the public database. I didn’t try any other operations or private databases.Is this a bug and could it stop working? Or is this a feature which will remain working? This tells me that under certain conditions, any app can read the CK container of any other app from any developer account, if they know the correct CK container ID to talk to. Is this expected? (Or maybe it only keeps working because they were previously under the same developer account, and the system knows to keep this connection? And if I were try to randomly read any other app’s container, it would fail?) Any docs or guidance from Apple?
8
0
3.4k
Nov ’19
Driving NavigationSplitView with something other than List?
Is it possible to drive NavigationSplitView navigation with a view in sidebar (left column) that is not a List? All examples that I have seen from this year only contain List in sidebar. I ask this because I would like to have a more complex layout in sidebar (or first view on iOS) that contains a mix of elements, some of them non-interactive and not targeting navigation. Here’s what I would like to do: import SwiftUI struct Thing: Identifiable, Hashable {     let id: UUID     let name: String } struct ContentView: View {     let things: [Thing]     @State private var selectedThingId: UUID?          var body: some View {         NavigationSplitView {             ScrollView(.vertical) {                 VStack {                     ForEach(things) { thing in                         Button("Thing: \(thing.name) \( selectedThingId == thing.id ? "selected" : "" )") {                             selectedThingId = thing.id                         }                     } SomeOtherViewHere() Button("Navigate to something else") { selectedThingId = someSpecificId }                 }             }         } detail: {             // ZStack is workaround for known SDK bug             ZStack {                 if let selectedThingId {                     Text("There is a thing ID: \(selectedThingId)")                 } else {                     Text("There is no thing.")                 }             }         }     } } This actually works as expected on iPadOS and macOS, but not iOS (iPhone). Tapping changes the selection as I see in the button label, but does not push anything to navigation stack, I remain stuck at home screen. Also filed as FB10332749.
12
5
5.9k
Jun ’22
CloudKit key and encryption errors on iOS 15 beta 1 on Simulator?
I am having trouble with my existing CloudKit app on iOS 15 beta simulator. Tried with Xcode 13 beta 1 on both Big Sur and Monterey. When I try to set up CloudKit record zones, I get the error: <CKError 0x600000ad34e0: "Partial Failure" (2/1011); "Failed to modify some record zones"; partial errors: { Zone1:__defaultOwner__ = <CKError 0x600000aab990: "Internal Error" (1/5000); "Failed to sync user keys"> Zone2:__defaultOwner__ = <CKError 0x600000aac180: "Internal Error" (1/5000); "Failed to sync user keys"> }> And when I try to retrieve some records: <CKError 0x600000aa6670: "Partial Failure" (2/1011); "Failed to fetch some query results"; partial errors: { 17E15463-28D9-4A8F-9C00-13864C0B1922:(Zone1:__defaultOwner__) = <CKError 0x600000a74120: "Internal Error" (1/5001); "Record <CKRecordID: 0x7fea11997820; recordName=17E15463-28D9-4A8F-9C00-13864C0B1922, zoneID=Zone1:__defaultOwner__> has items that require encryption but no zone protection data was found: <CKError 0x7fea105c6b40: "Internal Error" (5000/com.apple.protectedcloudstorage:97); "Failed to sync user keys">"> 4CADA078-7040-4633-9321-C1FF6C5BF80C:(Zone1:__defaultOwner__) = <CKError 0x600000a6c570: "Internal Error" (1/5001); "Record <CKRecordID: 0x7fea1198d250; recordName=4CADA078-7040-4633-9321-C1FF6C5BF80C, zoneID=Zone1:__defaultOwner__> has items that require encryption but no zone protection data was found: <CKError 0x7fea105c6b40: "Internal Error" (5000/com.apple.protectedcloudstorage:97); "Failed to sync user keys">"> E1558266-C19A-4A46-BC1A-B11303DA87FC:(Zone1:__defaultOwner__) = <CKError 0x600000a60210: "Internal Error" (1/5001); "Record <CKRecordID: 0x7fea132dfb80; recordName=E1558266-C19A-4A46-BC1A-B11303DA87FC, zoneID=Zone1:__defaultOwner__> has items that require encryption but no zone protection data was found: <CKError 0x7fea13263e60: "Internal Error" (5000/com.apple.protectedcloudstorage:97); "Failed to sync user keys">"> }> <CKError 0x600000af8d50: "Partial Failure" (2/1011); "Failed to fetch some query results"; partial errors: { BE1508B0-20C1-483A-B536-FFA1949E758A:(Zone1:_9b181defada871111c80080a15254790) = <CKError 0x600000aec7b0: "Internal Error" (1/5001); "Record <CKRecordID: 0x7fea1198cf00; recordName=BE1508B0-20C1-483A-B536-FFA1949E758A, zoneID=Zone1:_9b181defada871111c80080a15254790> has items that require encryption but no share protection data was found: <CKError 0x7fea105980b0: "Internal Error" (5004/5004); "Couldn't create share PCS data for share <CKRecordID: 0x7fea119910d0; recordName=Share-7347C086-8BA5-47C6-96AD-1DD12B1AAC8D, zoneID=Zone1:_9b181defada871111c80080a15254790>">"> F1D604B6-A4BC-4F2E-A23E-5B50A2D7C82D:(Zone1:_9b181defada871111c80080a15254790) = <CKError 0x600000a740f0: "Internal Error" (1/5001); "Record <CKRecordID: 0x7fea11985170; recordName=F1D604B6-A4BC-4F2E-A23E-5B50A2D7C82D, zoneID=Zone1:_9b181defada871111c80080a15254790> has items that require encryption but no share protection data was found: <CKError 0x7fea107bfb10: "Internal Error" (5004/5004); "Couldn't create share PCS data for share <CKRecordID: 0x7fea10416370; recordName=Share-C990C533-D709-4B7D-B916-418336386366, zoneID=Zone1:_9b181defada871111c80080a15254790>">"> }> I wonder if anyone else has experienced the same? Or if I can do something on my end to fix it? I’ve filed FB9144546 about this.
12
1
4.5k
Jun ’21
cktool: parent, reference, and record name fields
A few questions about advanced use of cktool for record creation and filtering. Is it possible to filter by record name? I.e query for a record with a specific recordName? Is there any way to specify record parent and reference fields when creating a record? All the examples of JSON fields so far that I have seen are of simple value types. Is there any way to filter/query by reference-type field?
1
0
1.1k
Sep ’21
Why can’t I use @Binding to manage NavigationList selection state?
Consider this view: import SwiftUI struct ContentView: View { &#9;&#9;@State var selection: ListObject? &#9;&#9;var objects: [ListObject] &#9;&#9;var body: some View { &#9;&#9;&#9;&#9;NavigationView { &#9;&#9;&#9;&#9;&#9;&#9;List { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;ForEach(objects) { object in &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;NavigationLink( &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;destination: &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;ListObjectView(object: object), tag: object, selection: $selection, &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;label: { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;Text(object.text) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;}) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;}.listStyle(SidebarListStyle()) &#9;&#9;&#9;&#9;&#9;&#9;.toolbar { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;ToolbarItem { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;Button("Push item") { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;selection = objects.first &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;Text("Empty view, pick something.").padding() &#9;&#9;&#9;&#9;}.onAppear { &#9;&#9;&#9;&#9;&#9;&#9;DispatchQueue.main.asyncAfter(deadline: .now() + 2) { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;selection = objects.first &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;} &#9;&#9;} } This is a simple list, where I can programmatically control the selection, and push another view into the navigation stack. I demonstrate two ways of doing this here, both with a timer and then with a button. Everything works as expected. Now, when I change the @State variable to @Binding, and pass it in from outside, this suddenly stops working. No matter what I do, I can no longer programmatically change the selection. What’s more, the list UI itself stops working: when I tap on a list item, nothing happens, and no detail view appears. Why do @State and @Binding behave differently here? Why does navigation link selection work with one, but not the other?
5
0
3.2k
Jul ’20
registerForRemoteNotifications not working at all in Big Sur?
I am working on a macOS app that involves remote notifications. In my app delegate appDidFinishLaunching, I simply call NSApplication.shared.registerForRemoteNotifications() I then get one of two callbacks in the app delegate, either didRegisterForRemoteNotificationsWithDeviceToken or didFailToRegisterForRemoteNotificationsWithError. This has worked fine forever in previous versions. In Big Sur, this does not seem to work at all. I call the registerForRemoteNotifications, but I never get either callback called. My hypothesis was that this is because of the new app lifecycle (which is where I originally tried this out). I built a small test app with AppKit app delegate lifecycle. It is equally broken there. What gives? Why cannot I register for remote notifications in Big Sur?
21
1
5.7k
Sep ’20
How do I add items to NSToolbar with SwiftUI?
Consider this macOS app code implemented with app delegate lifecycle: App delegate: func applicationDidFinishLaunching(_ aNotification: Notification) {         let contentView = ContentView()         window = NSWindow(             contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),             styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],             backing: .buffered, defer: false)         window.toolbar = NSToolbar(identifier: "toolbar")         window.title = "hello title"         window.subtitle = "hello subtitle"         window.isReleasedWhenClosed = false         window.center()         window.setFrameAutosaveName("Main Window")         window.contentView = NSHostingView(rootView: contentView)         window.makeKeyAndOrderFront(nil)     } SwiftUI: struct ContentView: View {     var body: some View {         NavigationView {             List {                 NavigationLink(                     destination: ItemView(),                     label: {                         Label("Something", systemImage: "folder.circle")                     })                 NavigationLink(                     destination: ItemView(),                     label: {                         Label("Another", systemImage: "pencil.tip.crop.circle")                     })             }.listStyle(SidebarListStyle())         }         .frame(maxWidth: .infinity, maxHeight: .infinity)         .toolbar {             ToolbarItem {                 Button(action: {                     print("Button clicked")                 }, label: {                     Label("Hello", systemImage: "pencil.circle")                 })             }         }     } } struct ItemView: View {     var body: some View {         Text("Hello, World!")             .frame(maxWidth: .infinity, maxHeight: .infinity)             .toolbar {                 ToolbarItem {                     Button(action: {                         print("Item button")                     }, label: {                         Label("Itemtool", systemImage: "lock.doc")                     })                 }             }     } } What this does: correctly sets up the window and toolbar look. Toolbar has no buttons though. What I would like to do: get the toolbar items added from SwiftUI added to the toolbar. Everything works as expected when I have the window managed by the SwiftUI app lifecycle. However, I need to stick with the app delegate lifecycle for unrelated reasons. Is this possible? How do I add toolbar buttons from SwiftUI to the toolbar of window that is created by app delegate?
1
0
1.3k
Aug ’20
How to auto-resize a SwiftUI sheet on macOS to fit its content?
Consider this code that presents a sheet on macOS: struct ContentView: View {     @State var showSheet = false     var body: some View {         VStack {             Text("Hello, world!").padding()             Button("Show sheet") {                 showSheet = true             }         }         .sheet(isPresented: $showSheet) {             SheetView()         }     } } struct SheetView: View {     @State var greenBiggerBox = false     var body: some View {         VStack {             Toggle("Show bigger box", isOn: $greenBiggerBox)             if greenBiggerBox {                 Rectangle().frame(width: 640, height: 480).foregroundColor(.green)             } else {                 Rectangle().frame(width: 320, height: 240).foregroundColor(.red)             }         }.padding()     } } The problem: initially, the sheet is presented, sized correctly to its contents (good). However, when something happens inside the sheet that resizes the content (like the toggle in the sheet), the sheet window is not resized, yielding a sheet size that is either too large or too small. How do I make the sheet resize correctly and automatically if its the size of its content changes?
2
0
5.3k
Aug ’20
How to accept CloudKit shares with the new SwiftUI app lifecycle?
In the iOS 13 world, I had code like this: class SceneDelegate: UIResponder, UIWindowSceneDelegate { &#9;&#9;func windowScene(_ windowScene: UIWindowScene, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) { &#9;&#9;&#9;&#9;// do stuff with the metadata, eventually call CKAcceptSharesOperation &#9;&#9;} } I am migrating my app to the new SwiftUI app lifecycle, and can’t figure out where to put this method. It used to live in AppDelegate pre-iOS13, and I tried going back to that, but the AppDelegate version never gets called. There doesn’t seem to be a SceneDelegateAdaptor akin to UIApplicationDelegateAdaptor available, which would provide a bridge to the old code. So, I’m lost. How do I accept CloudKit shares with SwiftUI app lifecycle? 🙈
2
0
1.2k
Aug ’20
How to render multiline text in SwiftUI List with correct height?
I would like to have a SwiftUI view that shows many lines of text, with the following requirements:Works on both macOS and iOS.Shows a large number of strings (each string is backed by a separate model object).I can do arbitrary styling to the multiline text.Each string of text can be of arbitrary length, possibly spanning multiple lines and paragraphs.The maximum width of each string of text is fixed to the width of the container. Height is variable according to the actual length of text.There is no scrolling for each individual text, only the whole list.Links in the text must be tappable/clickable.Text is read-only, does not have to be editable.Feels like the most appropriate solution would be to have a List view, with the individual rows wrapping native UITextView/NSTextView.Here’s what I have so far. It implements most of the requirements EXCEPT having the correct height for the rows.import SwiftUI let number = 20 struct ListWithNativeTexts: View { var body: some View { List(texts(count: number), id: \.self) { text in NativeTextView(string: text) } } } struct ListWithNativeTexts_Previews: PreviewProvider { static var previews: some View { ListWithNativeTexts() } } func texts(count: Int) -&gt; [String] { return (1...count).map { (1...$0).reduce("Hello https://example.com:", { $0 + " " + String($1) }) } } #if os(iOS) typealias NativeFont = UIFont typealias NativeColor = UIColor struct NativeTextView: UIViewRepresentable { var string: String func makeUIView(context: Context) -&gt; UITextView { let textView = UITextView() textView.isEditable = false textView.isScrollEnabled = false textView.dataDetectorTypes = .link textView.textContainerInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) textView.textContainer.lineFragmentPadding = 0 let attributed = attributedString(for: string) textView.attributedText = attributed return textView } func updateUIView(_ textView: UITextView, context: Context) { } } #else typealias NativeFont = NSFont typealias NativeColor = NSColor struct NativeTextView: NSViewRepresentable { var string: String func makeNSView(context: Context) -&gt; NSTextView { let textView = NSTextView() textView.isEditable = false textView.isAutomaticLinkDetectionEnabled = true textView.isAutomaticDataDetectionEnabled = true textView.textContainer?.lineFragmentPadding = 0 textView.backgroundColor = NSColor.clear textView.textStorage?.append(attributedString(for: string)) textView.isEditable = true textView.checkTextInDocument(nil) // make links clickable textView.isEditable = false return textView } func updateNSView(_ textView: NSTextView, context: Context) { } } #endif func attributedString(for string: String) -&gt; NSAttributedString { let attributedString = NSMutableAttributedString(string: string) let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 4 let range = NSMakeRange(0, (string as NSString).length) attributedString.addAttribute(.font, value: NativeFont.systemFont(ofSize: 24, weight: .regular), range: range) attributedString.addAttribute(.foregroundColor, value: NativeColor.red, range: range) attributedString.addAttribute(.backgroundColor, value: NativeColor.yellow, range: range) attributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: range) return attributedString }This mostly does what I need, except wrapping the text to multiple lines and scaling the height of each list row. Each list row remains at its default height.How do I get this solution to wrap the text to multiple lines and size the text views with correct heights?One approach that I have tried, but not shown here, is to give the height “from outside in” - to specify the height on the list row itself with frame. I can calculate the height of an NSAttributedString when I know the width, which I can obtain with geoReader. This almost works, but is buggy, and does not feel right, so I’m not showing it here.
8
0
9.5k
May ’20
macOS complaining about SceneStorage
Using Xcode 12 beta 2 on Big Sur beta. Having a view like this: import SwiftUI struct ContentView: View {     @SceneStorage("selectedItem") var selection: String?     var body: some View {         NavigationView {             List(selection: $selection) { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;… list contents             }.listStyle(SidebarListStyle())         }     } } When I try to compile and build this on macOS, I get this fatal error: Fatal error: @SceneStorage is only for use with SwiftUI App Lifecycle.: file SwiftUI, line 0 I am definitely using the SwiftUI App Lifecycle because this is a fresh new project created with Multiplatform app template. Why do I get this error? Can I fix it somehow?
2
0
1.3k
Jul ’20