Foundation

RSS for tag

Access essential data types, collections, and operating-system services to define the base layer of functionality for your app using Foundation.

Posts under Foundation tag

200 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Networking Resources
General: TN3151 Choosing the right networking API Networking Overview document — Despite the fact that this is in the archive, this is still really useful. TLS for App Developers DevForums post Choosing a Network Debugging Tool documentation WWDC 2019 Session 712 Advances in Networking, Part 1 — This explains the concept of constrained networking, which is Apple’s preferred solution to questions like How do I check whether I’m on Wi-Fi? TN3135 Low-level networking on watchOS Adapt to changing network conditions tech talk Foundation networking: DevForums tags: Foundation, CFNetwork URL Loading System documentation — NSURLSession, or URLSession in Swift, is the recommended API for HTTP[S] on Apple platforms. Network framework: DevForums tag: Network Network framework documentation — Network framework is the recommended API for TCP, UDP, and QUIC on Apple platforms. Network Extension (including Wi-Fi on iOS): See Network Extension Resources Wi-Fi Fundamentals Wi-Fi on macOS: DevForums tag: Core WLAN Core WLAN framework documentation Wi-Fi Fundamentals Secure networking: DevForums tags: Security Apple Platform Security support document Preventing Insecure Network Connections documentation — This is all about App Transport Security (ATS). Available trusted root certificates for Apple operating systems support article Requirements for trusted certificates in iOS 13 and macOS 10.15 support article About upcoming limits on trusted certificates support article Apple’s Certificate Transparency policy support article Technote 2232 HTTPS Server Trust Evaluation Technote 2326 Creating Certificates for TLS Testing QA1948 HTTPS and Test Servers Miscellaneous: More network-related DevForums tags: 5G, QUIC, Bonjour On FTP DevForums post Using the Multicast Networking Additional Capability DevForums post Investigating Network Latency Problems DevForums post Local Network Privacy FAQ DevForums post Extra-ordinary Networking DevForums post Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com"
0
0
2.2k
Feb ’24
Background Transfer Service and Client Certificates
I can't get NSURLSession background tasks to use client certificates.I have a simple app that creates an NSURLSessionDownloadTask from an NSURLSession that uses NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(...).I have a custom delegate that implements:"func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void)". For NSURLAuthenticationMethodServerTrust, I accept any server. For NSURLAuthenticationMethodClientCertificate, I have a hardcoded PKCS12 bundle with a single certificate and key from which I successfully create an NSURLCredential (using SecPKCS12Import), then pass that credential to the completion handler with .UseCredential.At runtime, I get the didReceiveChallenge callback for ClientCertificate, then another for NSURLAuthenticationMethodServerTrust, then URLSessionDidFinishEventsForBackgroundURLSession right away without completing the TLS handshake.If I change the NSURLSessionConfiguration to use NSURLSessionConfiguration.defaultSessionConfiguration(), the client cert is presented correctly and the download proceeds.Both tests are done with the app in the foreground.
17
0
7.7k
2w
Networking in a Short-Lived Extension
There are many cases where you want to do long-running network operations in a short-lived app extension. For example, you might be creating a share extension that needs to upload a large image to an Internet server. Doing this correctly is quite tricky. The rest of this post describes some of these pitfalls and explains how to get around them. Just by way of context: Most of the following was written during the iOS 8.1 timeframe, although AFAIK there’s been no specific changes in this space since then. The specific focus here is a share extension, although the behaviour is likely to be similar for other short-lived extensions. I wasn’t using SLComposeServiceViewController, although I have no reason to believe that makes a difference. I was testing on a device, not the simulator. In my experience the simulator is much less likely to terminate a share extension, which affects how things behave as I’ll explain later. My app and its share extension have an app group in common. I started by verifying that this app group was working as expected (using UserDefaults). The URLSession must be in that app group; set this via the sharedContainerIdentifier property of the URLSessionConfiguration object you use to create the session. The app and the share extension must use the same URLSession background session identifier (the value you pass in to background(withIdentifier:) when creating the configuration that you use to create the session). When an URLSession background session is shared like this, it’s critical to understand that the session only allows one process to ‘connect’ to it at a time. If a process is connected to the session and another tries to connect, the second process has its session immediately invalidated with NSURLErrorBackgroundSessionInUseByAnotherProcess. The connected session is the one that receives the session’s delegate callbacks. IMPORTANT If callbacks are generated when no process is connected, the background session resumes (or relaunches) the app rather than the extension. If a process is connected to a session and is then suspended or terminates, the session disconnects internally. If the process was terminated, the reconnection happens when your code creates its URLSession object on next launch. If the process was suspended, the reconnect happens when the app is resumed with the application(_:handleEventsForBackgroundURLSession:completionHandler:) delegate callback (and remember that this is always the app, not the extension, per the previous paragraph). The only way to programmatically disconnect from a session is to invalidate it. The expected behaviour here is that the extension will start an URLSession task and then immediately quit (by calling completeRequest(returningItems:completionHandler:)). The system will then resume (or relaunch) the container app to handle any delegate callbacks. When the system resumes or relaunches the container app to handle background session events, it calls application(_:handleEventsForBackgroundURLSession:completionHandler:). The container app is expected to: Save away the completion handler. Reconnect to the session, if necessary. This involves creating the URLSession object if it doesn’t currently exist. Handle delegate events from that session. Invalidate the session when those events are all done. The app knows this because the session calls the urlSessionDidFinishEvents(forBackgroundURLSession:) delegate callback. Call the completion handler that was saved in step 1. This leaves the app disconnected from the session, so future invocations of the extension don’t have to worry about the NSURLErrorBackgroundSessionInUseByAnotherProcess problem I mentioned earlier. This design works best if each extension hosted by the app has its own shared session. If the app hosts multiple extensions, and they all used the same shared session, they could end up stomping on each other. In my tests I’ve noticed that some annoying behaviour falls out of this design: If you start a task from an extension, it’s non-deterministic as to whether the app or extension gets the ‘did complete’ callback. If the task runs super quickly, the extension typically gets the callback. If the task takes longer, the system has time to terminate the extension and the app is resumed to handle it. There’s really no way around this. The workaround is to put the code that handles request completion in both your app and your extension (possibly sharing the code via a framework). It would be nice if the extension could disconnect from the session immediately upon starting its request. Alas, that’s not currently possible (r. 18748008). The only way to programmatically disconnect from the session is to invalidate it, and that either cancels all the running tasks (invalidateAndCancel()) or waits for them to complete (finishTasksAndInvalidate()), neither of which is appropriate. One interesting edge case occurs when the app is in the foreground while the share extension comes up. For example, the app might have a share button, from which the user can invoke the share extension. If the share extension starts an URLSession task in that case, it can result in the app’s application(_:handleEventsForBackgroundURLSession:completionHandler:) callback being called while the app is in the foreground. The app doesn’t need to behave differently in this case, but it’s a little unusual. Xcode’s debugger prevents the system from suspending the process being debugged. So, if you run your extension from Xcode, or you attach to its process some time after launch, the process will continue to execute in situations where the system would otherwise have suspended it. This makes it tricky to investigate problems with the ‘extension was suspended before the network request finished’ case. The best way to investigate any issues you encounter is via logging. Note For more information about debugging problems with background networking, see Testing Background Session Code. Keep in mind that not all networking done by your extension has to use a background session. You should use a background session for long-running requests, but if you have short-running requests then it’s best to run them in a standard session. For example, imagine you have a share extension that needs to make two requests: The first request simply gets an upload authorisation token from the server. This request is expected to finish very quickly. The second request actually uploads the file (including the upload authorisation token from the previous request), and is expected to take a long time. It makes sense to only use a background session for the second request. The first request, being short-running, can be done in a standard session, and that will definitely simplify your code. When doing this you have to prevent your extension from suspending while the short-lived request is in flight. You can use ProcessInfo.performExpiringActivity(withReason:using:) for this. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History 2023-08-30 Fixed the formatting. Adopted Swift terminology throughout. Made other minor editorial changes. 2017-04-26 Moved to the new DevForums. Made many editorial changes. Added the section on Xcode’s debugger. Added a section on short-running network requests. 2014-12-05 First posted on the old DevForums.
0
0
3.4k
Aug ’23
NSURLSessionDownloadDelegate Methods on iPhone iOS 10.3.1
I've recently been integrating Background Transfer Service into an application so that the user is able to download files in the background.I did most of my building/testing on an old iPhone 6 device that was running iOS 9.3.5 (I try to keep my previous device back a version of iOS). Background Transfer Service works great on this device. I am able to put 100+ download tasks into the queue and they all finish and report progress as expected after sending the application into the background and then re-opening the application.This also appears to work great on a new 5th generation iPad running iOS 10.3.Where things get weird is on my iPhone 7 Plus which is running iOS 10.3.1. The downloads kick off fine, progress is reported as expected in the didWriteData method, however if I background the application and wait ~10 seconds and re-open the application the progress never catches back up to what progress would have been done in the background and the progress never increments at all (it stays where it was when it was backgrounded). The didFinishDownloading method does end up getting called however it appears to wait until the very end of all the download tasks completions for that method to fire for all of the remaining tasks. So the didWriteData, didFinishDownloading, didCompleteWithError, etc. all happen right at the end in one burst. I have however had a few instances where my iPhone 7 Plus device running iOS 10.3.1 did show progress after bringing the app back into the foreground however those instances I could could on one hand. More often than not (9 times out of 10) the progress is never reported on this device after re-opening the application.I am at a bit of a loss and am wondering if there is a known bug we should be looking out for, and if so when we could expect a fix? Or if there are currently any known work arounds. From my testing/debugging I cannot get progress to work in my application on the iPhone 7 Plus running 10.3.1. I also had a co-worker test this as well and they also experienced this.In fact they went a step further and opened the Netflix application on their 10.3.1 iPhone 7 Plus device and began downloading a movie. Progress incremented as expected, they then backgrounded the application and waited ~20 seconds and re-opened the application, only to find the progress get stuck where it was when the app was initially backgrounded and it never moves. After a given amount of time of the progress not moving the download does eventually finish (the progress indicator disappears) and the Netflix movie is downloaded and able to be played. This is the same behavior I see above in my application.Any help with this would be greatly appreciated.Thanks in advance!Adam
29
0
11k
Oct ’23
EAAccessoryManager notifyObserversThatAccessoryDisconnectedWithUserInfo crashes iOS 11.1.2
App is crashing while a bluetooth device is disconnected. I've seen few related threads and they say "A notification delegate was not reset to nil. A fix has been applied at version 10.3.79."Following is crash log:Triggered by Thread: 0 Thread 0 name: Thread 0 Crashed: 0 libobjc.A.dylib 0x000000018544c430 objc_msgSend + 16 1 ExternalAccessory 0x000000019c07c4dc -[EAAccessoryManager _notifyObserversThatAccessoryDisconnectedWithUserInfo:] + 104 (EAAccessoryManager.m:909) 2 ExternalAccessory 0x000000019c07eddc -[EAAccessoryManager _externalAccessoryDisconnected:] + 928 (EAAccessoryManager.m:1537) 3 CoreAccessories 0x00000001a7892ccc __54-[ACCExternalAccessoryProvider ExternalAccessoryLeft:]_block_invoke + 316 (ACCExternalAccessoryProvider.m:453) 4 libdispatch.dylib 0x0000000185b6d088 _dispatch_call_block_and_release + 24 (init.c:994) 5 libdispatch.dylib 0x0000000185b6d048 _dispatch_client_callout + 16 (object.m:502) 6 libdispatch.dylib 0x0000000185b79b74 _dispatch_main_queue_callback_4CF$VARIANT$mp + 1016 (inline_internal.h:2500) 7 CoreFoundation 0x0000000186191eb0 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12 (CFRunLoop.c:1815) 8 CoreFoundation 0x000000018618fa8c __CFRunLoopRun + 2012 (CFRunLoop.c:3111) 9 CoreFoundation 0x00000001860affb8 CFRunLoopRunSpecific + 436 (CFRunLoop.c:3245) 10 GraphicsServices 0x0000000187f47f84 GSEventRunModal + 100 (GSEvent.c:2245) 11 UIKit 0x000000018f6842e8 UIApplicationMain + 208 (UIApplication.m:3949) 12 MYAPP 0x0000000100ab8d58 main + 172 (main.m:16) 13 libdyld.dylib 0x0000000185bd256c start + 4
7
1
2.3k
Aug ’23
iOS 14 CoreFoundation crash with EXC_BREAKPOINT
Hi, I am facing a strange issue in my app with iOS14 there is a intermittent crash, i am using NetServiceBrowser for MDNS discovery not sure if that is causing the problem crash log has below information: Crashed: com.apple.main-thread 0 CoreFoundation 0x1a906c4c4 CFAssertMismatchedTypeID + 108 1 CoreFoundation 0x1a8f7db0c CFRunLoopSourceRemoveFromRunLoop + 298 2 CFNetwork 0x1a96255b0 CFNetServiceBrowserStopSearch + 460 3 CoreFoundation 0x1a8f81240 CFRUNLOOPISCALLINGOUTTOASOURCE0PERFORMFUNCTION + 24 4 CoreFoundation 0x1a8f81140 CFRunLoopDoSource0 + 204 5 CoreFoundation 0x1a8f80488 CFRunLoopDoSources0 + 256 6 CoreFoundation 0x1a8f7aa40 CFRunLoopRun + 776 7 CoreFoundation 0x1a8f7a200 CFRunLoopRunSpecific + 572 8 GraphicsServices 0x1bf075598 GSEventRunModal + 160 9 UIKitCore 0x1ab840004 -[UIApplication run] + 1052 10 UIKitCore 0x1ab8455d8 UIApplicationMain + 164
29
1
11k
May ’24
-[NSURLSessionWebSocketTask cancelWithCloseCode:reason:] reliability issue
Hello, For our iOS app, we're switching WebSocket client implementation from one using Poco project - https://github.com/pocoproject/poco to one based on NSURLSessionWebSocketTask. We are observing one regression which prevents us from shipping this solution though: 5-7% of calls to -[NSURLSessionWebSocketTask cancelWithCloseCode:reason:] fail to deliver given close code to server and 1006 close code (AbnormalClosure) is used instead. Our test consist of following steps: Create WebSocket using NSURLSessionWebSocketTask Send "Hello" message Close WebSocket with 1011 close code Destroy NSURLSessionWebSocketTask instance Check whether server received 1011 close code We do not perform those steps line by line, but rather use delays (~100-200ms) between each step. We perform such test 1000 times and observe 5-7% failure rate consistently. Distribution of failures is random. We did perform test on both iOS simulator and iOS devices with no observable differences. We did perform test on multiple server implementations (tornado- and node.js based ones) running on local machine (same as Xcode) and remote one We always receive "Hello" message on server 1011 close code is arbitrarily chosen for testing, but results are same for different ones, too. We did setup mitmproxy and for failed tests see following log: Error in WebSocket connection to 20.16.12.131:8080: WebSocket connection closed unexpectedly by client: TcpDisconnect(None) We did enable CFNetwork diagnostic using CFNETWORK_DIAGNOSTICS and found one difference between success and failure cases. For successful cases we see log which looks like this: default 16:27:15.831193+0200 Playground-ObjC tcp_close [C7.1:2] TCP Packets: snd 0.000s seq 1092086878:1092086879 ack 0 win 65535 len 0 [SEC] rcv 0.004s seq 3101059099:3101059100 ack 1092086879 win 65535 len 0 [S.] snd 0.000s seq 1092086879:1092086879 ack 3101059100 win 4117 len 0 [.] snd 0.002s seq 1092086879:1092087279 ack 3101059100 win 4117 len 400 [P.] rcv 0.001s seq 3101059100:3101059100 ack 1092086879 win 2058 len 0 [.] rcv 0.000s seq 3101059100:3101059100 ack 1092087279 win 2052 len 0 [.] rcv 0.015s seq 3101059100:3101059229 ack 1092087279 win 2052 len 129 [P.] ECT0 snd 0.000s seq 1092087279:1092087279 ack 3101059229 win 4113 len 0 [.] snd 0.003s seq 1092087279:1092087289 ack 3101059229 win 4113 len 10 [P.] rcv 0.002s seq 3101059229:3101059229 ack 1092087289 win 2052 len 0 [.] snd 0.017s seq 1092087289:1092087297 ack 3101059229 win 4113 len 8 [P.] snd 0.001s seq 1092087297:1092087298 ack 3101059229 win 4113 len 0 [F.] rcv 0.000s seq 3101059229:3101059229 ack 1092087297 win 2052 len 0 [.] rcv 0.001s seq 3101059229:3101059233 ack 1092087297 win 2052 len 4 [P.] ECT0 Last packet 0ms ago. So it's something related to "tcp_close" and seems to log whole TCP packets that were exchanged during connection. For failed cases such log is not present. One additional log we see potentially interesting (but were not able to confirm its meaning or relation to failed cases) comes from runningboardd: default 16:27:15.830447+0200 runningboardd Invalidating assertion 33-1364-23682 (target:[applicationorg.example.app:1364]) from originator [applicationorg.example.app:1364] So that's where we are right now and we have no idea where to dig next. We wonder if anyone else have seen such problem or can point us to any direction we could try next. Thanks much, Damian & Maciek
3
1
1k
Nov ’23
Check if Background URLSession with identifier exists
I have a working background URLSession. I know that upon creating an URLSession with the same session identifier I get a "background URLSession with identifier x already exists" message. I know that I can store the session and call .finishTasksAndInvalidate() on it if needed. My use case is that if the application terminates, and the user relaunches the application before the background task completes, I need to be able to check if a background URLSession with the same identifier exists, and if it does, restitute the application state with the same handlers (so that I can update a UIProgressView for example). I have two questions: How do I check that a background URLSession with a given identifier already exists? Does the AppDelegate completion handler still get called if the application was terminated and relaunched?
5
0
2.0k
Aug ’23
Swift Process with Psuedo Terminal (PTY)
Hi! I'm looking for some insight and guidance on using the Foundation.Process type with a PTY (Psuedo Terminal) so that the subprocess can accept input and behave as if it was running via a terminal. The reason for needing a PTY is that for programs like ssh or in my case (xcodes) which ask for user input including passwords, running these via Foundation.Process does not display the prompts to the user as the output is usually buffered (this works fine in the Xcode debugger console but when running via a real terminal that is buffered the prompts are never displayed in the terminal) Looking at other threads it seems like correct approach here is create a PTY and use the filehandles to attach to the Process. While I've got this to work to the point where prompts are now shown, I cant seem to figure out how to pass input back to the process as these are being controlled by the PTY. Here is my Process setup: let process = Process() // Setup the process with path, args, etc... // Setup the PTY handles var parentDescriptor: Int32 = 0 var childDescriptor: Int32 = 0 guard Darwin.openpty(&parentDescriptor, &childDescriptor, nil, nil, nil) != -1 else {   fatalError("Failed to spawn PTY") } parentHandle = FileHandle(fileDescriptor: parentDescriptor, closeOnDealloc: true) childHandle = FileHandle(fileDescriptor: childDescriptor, closeOnDealloc: true) process.standardInput = childHandle process.standardOutput = childHandle process.standardError = childHandle With this setup I then read the parent handle and output any result it gets (such as the input prompts): parentHandle?.readabilityHandler = { handle in   guard let line = String(data: handle.availableData, encoding: .utf8), !line.isEmpty else {     return   }   logger.notice("\(line)") } When process.run() is executed the program runs and I can see it asks for Apple ID: input in my terminal, however, when typing input into the terminal the process does not seem to react to this input. I've tried forwarding the FileHandle.standardInput: FileHandle.standardInput.readabilityHandler = { handle in   parentHandle?.write(handle.availableData) } But this doesn't seem to work either. What is the recommended way to setup a PTY with Foundation.Process for executing arbitrary programs and having them behave as if they were being run in a terminal context? Most of the resources I found online are about other languages and I'd like to stick with Foundation.Process vs. doing anything custom in C/C++ if possible as it just makes it easier to reason about / maintain. The resources for Swift on this topic are very lacking and I've checked out some open source projects that claim to do this but most require manually sending input to the PTY handle vs. accepting them from the user in a terminal. Any insight / help is very much appreciated!
9
0
2.9k
Mar ’24
New iOS String Initializer can't get correct localized String for specific locale
I tried to build LocalizedKeyString using String's new Initializer. String(localized: "hello",locale: locale) When I change the language setting of the device, everything works as expected. However, when I try to get the string in a specific language using the specified Locale, I can only ever get the string in .current. String(localized: "hello",locale: Locale(identifier: "zh-cn"))     func getString(locale:Locale) -> String{          String(localized: "hello",locale: locale)     } If you change the display language of the project (or the language setting of the device), the text in Text is always displayed correctly. Text(getString(locale:.current)) However, the code in onAppear print(getString(locale:Locale(identifier: "zh-cn"))) It only displays the same content as Text, but not the specified Chinese. Is it my fault that the new Initializer The understanding is not correct, or the bug of String init(localized keyAndValue: String.LocalizationValue, table: String? = nil, bundle: Bundle? = nil, locale: Locale = .current, comment: StaticString? = nil) FB number: FB9675845
7
0
3.6k
Mar ’24
UserDefaults not being saved in Simulator only
In Xcode 13, using the 14.5 and 15.0 simulators, when I use UserDefaults to save preferences for the user, the defaults seem to go away when the app quits (I am using the home button / app switcher / slide up gesture to quit the app in the simulator). This problem does not occur when using my actual devices (iPad and iPhone). [userDefaults synchronize] returns YES, however I am getting nil for the key I saved upon next launch. Note: I am using NSKeyedArchiver archivedDataWithRootObject with requiresSecureCoding set to YES for some keys, however the first key is not using NSKeyedArchiver and is also returning nil.
3
0
1.4k
Oct ’23
CFNetwork crash in CFURLRequestSetMainDocumentURL
I have received two strange crash reports from an iPad11,7 running iPadOS 15.1 and an iPad11,2 running iPadOS 15.2. On both occasions, the crashed thread calls CFURLRequestSetMainDocumentURL, which in turn calls _dispatch_source_set_runloop_timer_4CF in libdispatch, after which the application crashes with SIGSEGV and SEGV_MAPERR. The crashed thread's call stack is displayed below. Full crash logs are attached as well. What could this be? Exception Type: SIGSEGV Exception Codes: SEGV_MAPERR at 0x21d Crashed Thread: 20 Thread 20 Crashed: 0 libdispatch.dylib 0x00000001829e1784 _dispatch_source_set_runloop_timer_4CF + 36 1 CFNetwork 0x00000001834fc824 CFURLRequestSetMainDocumentURL + 2240 2 CFNetwork 0x00000001836b89a8 _CFNetworkErrorGetLocalizedDescription + 693652 3 CFNetwork 0x00000001834fdb1c CFURLRequestSetMainDocumentURL + 7096 4 CFNetwork 0x00000001834f3c34 CFURLRequestSetURL + 9668 5 libdispatch.dylib 0x00000001829ca914 _dispatch_call_block_and_release + 28 6 libdispatch.dylib 0x00000001829cc660 _dispatch_client_callout + 16 7 libdispatch.dylib 0x00000001829d3de4 _dispatch_lane_serial_drain + 668 8 libdispatch.dylib 0x00000001829d498c _dispatch_lane_invoke + 440 9 libdispatch.dylib 0x00000001829d5c74 _dispatch_workloop_invoke + 1792 10 libdispatch.dylib 0x00000001829df1a8 _dispatch_workloop_worker_thread + 652 11 libsystem_pthread.dylib 0x00000001f1eea0f4 _pthread_wqthread + 284 12 libsystem_pthread.dylib 0x00000001f1ee9e94 start_wqthread + 4 second_crashlog.txt report-2517628380750009999-e4d7ea06-6f22-4b7e-b129-045599e1dee5.txt
9
1
4k
Dec ’23
Set 12 vs 24 hour with the new date formatting API in iOS 15
Using the new date formatting API available in iOS 15, I would like to respect the 12 vs 24 hour setting on a user-by-user basis. With DateFormatter it can be done as follows, for example, to force a 24 hour time irrespective of the user locale. let formatter = DateFormatter() formatter.dateFormat = "HH:mm" // or hh:mm for 12 h However, I cannot figure out how to force the new date formatting API in iOS 15 to do the same thing, i.e. force displaying 12 vs 24 h. I'm using a format style like this: var formatStyle = dateTime formatStyle.calendar = calendar if let timeZone = timeZone { formatStyle.timeZone = timeZone } return formatStyle And applying it like this, for example, for a given Date instance: date.formatted(formatStyle.hour(.defaultDigits(amPM: .abbreviated))) However, this seems to always give a formatted string relevant to the locale, for example, it's always 12h for the US and always 24h for the UK. This is not the behaviour I really need though, and I'd like to allow each individual user to control what they see irrespective of the locale setting. (Note that there is an in-app setting that allows the user to toggle between the 12 and 24 hour preference, which is the value I'd like to use to set the preference.)
7
0
8.4k
Nov ’23
Problem decoding AttributedString containing emoji
I am trying to encode an AttributedString to JSON and then decode it back to an AttributedString. But when the AttributedString both (1) contains emoji, and (2) has any attributes assigned, the decoding seems to fail, producing a truncated AttributedString. By dump-ing the decoded value, I can see that the full string is still in there (in the guts property) but it is missing in normal uses of the AttributedString. Below is an example that reproduces the problem. import Foundation // An arbitrary AttributedString with emoji var attrString = AttributedString("12345💕☺️💕☺️💕☺️12345") // Set an attribute (doesn't seem to matter which one) attrString.imageURL = URL(string: "http://www.dummy.com/dummy.jpg")! // Encode the AttributedString var encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted let data = try! encoder.encode(attrString) // Print the encoded JSON print("encoded JSON for AttributedString:") print(String(data: data, encoding: .utf8)!) // Output from above omitted, but it looks correct with the full string represented // Decode the AttributedString and print it let decoder = JSONDecoder() let decodedAttrString = try! decoder.decode(AttributedString.self, from: data) print("decoded AttributedString:") print(decodedAttrString) // Output from above is a truncated AttributedString: // // 12345💕☺️ { // NSImageURL = http://www.dummy.com/dummy.jpg // } print("dump of AttributedString:") dump(decodedAttrString) // Interestingly, `dump` shows that the full string is still in there: // // ▿ 12345💕☺️ { // NSImageURL = http://www.dummy.com/dummy.jpg // } // ▿ _guts: Foundation.AttributedString.Guts #0 // - string: "12345💕☺️💕☺️💕☺️12345" // ▿ runs: 1 element // ... //
9
0
1.3k
Jun ’24
SecureCoding roadblock?
Attached is an entire project (4 files) that mirrors my actual project including the failure to save to file. Am I: missing some syntax in this code? failing to config a defaults file? not set the necessary parameters in " "Build Settings" or "Build Rules etc.? I was writing to JSON files, but now that I must append to files directly, and JSON doesn't do that easily, I am trying to write using native macOS tools. WELL, IT SEEMS I CAN'T SEND YOU THE CODE, TOO MANY CHARS. I CAN'T ATTACH ANY FILE EITHER. WHY OFFER IT IF IT IS NOT ALLOWED? ANYWAY, CAN YOU GLEAN ANYTHING FROM THIS... Thanks. My debugger area: 2022-05-28 12:03:11.827372-0500 exampleClassInClassSecureCoding[1508:29981] Metal API Validation Enabled 2022-05-28 12:03:11.940123-0500 exampleClassInClassSecureCoding[1508:29981] *** NSForwarding: warning: object 0x600003cf7090 of class 'exampleClassInClassSecureCoding.classOne' does not implement methodSignatureForSelector: -- trouble ahead Unrecognized selector -[exampleClassInClassSecureCoding.classOne replacementObjectForKeyedArchiver:] 2022-05-28 12:03:11.940416-0500 exampleClassInClassSecureCoding[1508:29981] Unrecognized selector -[exampleClassInClassSecureCoding.classOne replacementObjectForKeyedArchiver:] Unrecognized selector -[exampleClassInClassSecureCoding.classOne replacementObjectForKeyedArchiver:] Performing @selector(didPressButton:) from sender _TtC7SwiftUIP33_9FEBA96B0BC70E1682E82D239F242E7319SwiftUIAppKitButton 0x7ff08ab06480
9
0
1.5k
Feb ’24
How to handle IPv6 link-local addresses in iOS 16?
Our (legacy) code to communicate with peripherals on local IPv6 networks (LAN) adds the zone identifier / interface name ("%en0") to link-local IP addresses (FE80::/10) discovered via SSDP. SSDP is implemented using CocoaAsyncSocket - yes, that part of our code is old... (from before the introduction of the iOS 12+ Network framework). We use these modified IP addresses as the host component of a URL in a URLSession.dataTask. To insert the zone identifier we are using URLComponents (we modify the host and then request the string). This worked fine in iOS 15 and below, but no longer works in iOS 16 (Beta 1/2/3); the host is empty after inserting %en0 in the most recent beta. We have reported this via FB10549269, but from the answer it is unclear to me whether Apple is planning to fix this ("Resolution: Potential fix identified"), or we are doing it wrong. How should we handle IPv6 link-local addresses in iOS 16? (when using URLSession instead of Network) PS: We recently dropped support for iOS 12, but we still need to support iOS 13 and up
3
0
1.9k
Aug ’23
App group shared user defaults
In iOS 16 beta 3, my iOS app sets some strings in the shared user defaults of the app group. The iOS widget extension reads the strings from the shared user defaults correctly, but the watchOS app and watchOS widget extension could not read them (get nil). Integers stored in the shared user defaults can be read everywhere. All targets are in the same app group. Does anyone have similar problems?
7
0
4.2k
Aug ’23