Swift is a powerful and intuitive programming language for Apple platforms and beyond.

Posts under Swift tag

200 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

ToolbarItemGroup(placement: .keyboard) is not showed with Sheet
struct ContentView: View {   @State var isPresented = false   var body: some View {     Button {       isPresented.toggle()     } label: {       Text("Button")     }     .sheet(isPresented: $isPresented) {       SubView()     }   } } struct SubView: View {   @State var text = ""   var body: some View {     NavigationStack {       TextEditor(text: $text)         .toolbar {           ToolbarItemGroup(placement: .bottomBar) {             Button("Click") {             }           }           ToolbarItemGroup(placement: .keyboard) {             Button("Click") {             }           }         }     }   } }
9
3
2.9k
Oct ’23
A bug in Xcode lldb debugger for swift
In some particular situation, Xcode debugger or lldb cli cannot correctly extract some value that returned by a async throw function and handled by guard let try?. Here is the minimum example: import Dispatch func test() async throws -> [Int] {   return [369] } let group = DispatchGroup() group.enter() let task = Task {   guard let res = try? await test() else { return }   print(res)   group.leave() } group.wait() If added a break point at print(res), the debugger cannot show the value of res. Due to forum limitation, I cannot paste a screenshot here... if use p res or po res at lldb cli, it shows: (lldb) p res error: expression failed to parse: error: <EXPR>:3:1: error: cannot find 'res' in scope res ^~~ (lldb) po res error: expression failed to parse: error: <EXPR>:3:1: error: cannot find 'res' in scope res ^~~ If test() returns a dict, or a costom struct, the issue retains. But if returned a trivial value like Int, it acts normally. Also, if remove the guard statement, make res a optional value(use let res = try? await test()), debugger can extract the value. Above results are compiled and run in this environment: Swift 5.6.1 Xcode 13.4.1 (13F100) lldb-1316.0.9.46 macOS 12.4 x86_64 arch
5
3
3.9k
Jul ’23
Calling Security Framework from Swift
I spend way too much time interacting with the Security framework. Most Security framework APIs are kinda clunky to call from Swift, largely because they use Core Foundation conventions. However, I see a lot of folks working much harder than they should to call these APIs. This post contains two tips to make your life easier. Many Security framework APIs work in terms of CFDictionary. I regularly see folks create these dictionaries like so: let query: [String: Any] = [ kSecClass as String: kSecClassKey, kSecMatchLimit as String: kSecMatchLimitAll, kSecReturnRef as String: true, ] var copyResult: CFTypeRef? let status = SecItemCopyMatching(query as CFDictionary, &copyResult) That’s much too hard. Try this instead: let query = [ kSecClass: kSecClassKey, kSecMatchLimit: kSecMatchLimitAll, kSecReturnRef: true, ] as NSDictionary var copyResult: CFTypeRef? let status = SecItemCopyMatching(query, &copyResult) Much nicer. Security framework APIs have a wide variety of ways to indicate an error: Some routines return an OSStatus and that’s it. Some routines return an OSStatus and an ‘out’ value. Some routines return a pointer, where nil indicates an error. Some routines return a pointer, where nil indicates an error, with a CFError ‘out’ value. Some routines return a Boolean, where false indicates an error, with a CFError ‘out’ value. In Swift you really just want to call the API and have it throw. The code pasted in at the end of this post helps with that. It declares a bunch of overloaded secCall(…) functions, one for each of the cases outlined above. It takes code like this: let query = [ kSecClass: kSecClassKey, kSecMatchLimit: kSecMatchLimitAll, kSecReturnRef: true, ] as NSDictionary var copyResult: CFTypeRef? = nil let err = SecItemCopyMatching(query, &copyResult) guard err == errSecSuccess else { throw NSError(domain: NSOSStatusErrorDomain, code: Int(err)) } let keys = copyResult! as! [SecKey] and turns it into this: let query = [ kSecClass: kSecClassKey, kSecMatchLimit: kSecMatchLimitAll, kSecReturnRef: true, ] as NSDictionary let keys = try secCall { SecItemCopyMatching(query, $0) } as! [SecKey] Still not exactly pretty, but definitely an improvement. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History 2023-11-27 Fixed a polarity bug with the Bool routine. As the saying goes “Real programmers can get the branch backwards in any language!” |-: /// Calls a Security framework function, throwing if it returns an error. /// /// For example, the `SecACLRemove` function has a signature like this: /// /// ``` /// func SecACLRemove(…) -> OSStatus /// ``` /// /// and so you call it like this: /// /// ``` /// try secCall { SecACLRemove(acl) } /// ``` /// /// - Parameter body: A function that returns an `OSStatus` value. /// - Throws: If `body` returns anything other than `errSecSuccess`. func secCall(_ body: () -> OSStatus) throws { let err = body() guard err == errSecSuccess else { throw NSError(domain: NSOSStatusErrorDomain, code: Int(err), userInfo: nil) } } /// Calls a Security framework function that returns an error and a value indirectly. /// /// For example, the `SecItemCopyMatching` function has a signature like this: /// /// ``` /// func SecItemCopyMatching(…, _ result: UnsafeMutablePointer<CFTypeRef?>?) -> OSStatus /// ``` /// /// and so you call it like this: /// /// ``` /// let keys = try secCall { SecItemCopyMatching([ /// kSecClass: kSecClassKey, /// kSecMatchLimit: kSecMatchLimitAll, /// kSecReturnRef: true, /// ] as NSDictionary, $0) } /// ``` /// /// - Parameter body: A function that returns an `OSStatus` value and takes a /// ‘out’ pointer to return the result indirectly. /// - Throws: If `body` returns anything other than `errSecSuccess`. /// - Returns: The value returned indirectly by the function. func secCall<Result>(_ body: (_ resultPtr: UnsafeMutablePointer<Result?>) -> OSStatus) throws -> Result { var result: Result? = nil let err = body(&result) guard err == errSecSuccess else { throw NSError(domain: NSOSStatusErrorDomain, code: Int(err), userInfo: nil) } return result! } /// Calls a Security framework function that returns `nil` on error. /// /// For example, the `SecKeyCopyPublicKey` function has a signature like this: /// /// ``` /// func SecKeyCopyPublicKey(…) -> SecKey? /// ``` /// /// and so you call it like this: /// /// ``` /// let publicKey = try secCall { SecKeyCopyPublicKey(privateKey) } /// ``` /// /// - Parameters: /// - code: An `OSStatus` value to throw if there’s an error; defaults to `errSecParam`. /// - body: A function that returns a value, or `nil` if there’s an error. /// - Throws: If `body` returns `nil`. /// - Returns: On success, the non-`nil` value returned by `body`. func secCall<Result>(_ code: Int = Int(errSecParam), _ body: () -> Result?) throws -> Result { guard let result = body() else { throw NSError(domain: NSOSStatusErrorDomain, code: code, userInfo: nil) } return result } /// Calls a Security framework function that returns `nil` on error along with a `CFError` indirectly. /// /// For example, the `SecKeyCreateDecryptedData` function has a signature like this: /// /// ``` /// func SecKeyCreateDecryptedData(…, _ error: UnsafeMutablePointer<Unmanaged<CFError>?>?) -> CFData? /// ``` /// /// and so you call it like this: /// /// ``` /// let plainText = try secCall { SecKeyCreateDecryptedData(privateKey, .rsaEncryptionPKCS1, cypherText, $0) } /// ``` /// /// - Parameter body: A function that returns a value, which returns `nil` if /// there’s an error and, in that case, places a `CFError` value in the ‘out’ parameter. /// - Throws: If `body` returns `nil`. /// - Returns: On success, the non-`nil` value returned by `body`. func secCall<Result>(_ body: (_ resultPtr: UnsafeMutablePointer<Unmanaged<CFError>?>) -> Result?) throws -> Result { var errorQ: Unmanaged<CFError>? = nil guard let result = body(&errorQ) else { throw errorQ!.takeRetainedValue() as Error } return result } /// Calls a Security framework function that returns false on error along with a `CFError` indirectly. /// /// For example, the `SecKeyVerifySignature` function has a signature like this: /// /// ``` /// func SecKeyVerifySignature(…, _ error: UnsafeMutablePointer<Unmanaged<CFError>?>?) -> Bool /// ``` /// /// and so you call it like this: /// /// ``` /// try secCall { SecKeyVerifySignature(publicKey, .ecdsaSignatureMessageX962SHA1, signedData, signature, $0) } /// ``` /// /// - Parameter body: A function that returns a false if there’s an error and, /// in that case, places a `CFError` value in the ‘out’ parameter. /// - Throws: If `body` returns false. func secCall(_ body: (_ resultPtr: UnsafeMutablePointer<Unmanaged<CFError>?>) -> Bool) throws { var errorQ: Unmanaged<CFError>? = nil guard body(&errorQ) else { throw errorQ!.takeRetainedValue() as Error } }
0
0
2.4k
Nov ’23
`NSVisualEffectView` not working in `SwiftUI`
Bellows are the codes in Swift Playground. import PlaygroundSupport import SwiftUI struct VisualEffectView: NSViewRepresentable { let material: NSVisualEffectView.Material = .contentBackground let blendingMode: NSVisualEffectView.BlendingMode = .withinWindow func makeNSView(context: Context) -> NSVisualEffectView { let visualEffectView = NSVisualEffectView() visualEffectView.material = material visualEffectView.blendingMode = blendingMode visualEffectView.state = NSVisualEffectView.State.active return visualEffectView } func updateNSView(_ visualEffectView: NSVisualEffectView, context: Context) { visualEffectView.material = material visualEffectView.blendingMode = blendingMode } } struct ContentView: View { var body: some View { ZStack { Image(nsImage: #imageLiteral(resourceName: "background.jpg")) .resizable() .aspectRatio(contentMode: .fill) .frame(width: 400, height: nil, alignment: .center) VisualEffectView() } } } PlaygroundPage.current.setLiveView(ContentView()) The codes result in white area with the Image invisible.
1
0
622
Jul ’23
Why use async/await vs completion handlers?
I'm pretty sure I'm missing something completely obvious, but I can't see what. I watched WWDC session, read the Swift evolution blog, and they all make sense, but still it doesn't click for me. Please help me out here :) . I'm diving into adopting the 'new' async/await style of coding (I know, it's old news at this point, but I could only get to it now), and so I'm all pumped to get my code to go eleven and therefore I wrote a small data-downloader class. It has one method, well two: one oldskool function with a completionHandler, and one new style async/await one. When using the oldskool one, it works as everyone would expect: print(1) dataFetcher.fetchSomeData { print(2) let data = $0 // process data ... print(3) } print(4) The output is, unsurprisingly: 1 4 2 3 Now, when I use my new style function: let data = await dataFetcher.fetchSomeData() // process data ... Xcode gives me an error: 'async' call in a function that does not support concurrency That makes sense, I am calling this in the viewDidLoad() method of a UIViewController subclass. Can't mark viewDidLoad() as await, as super's implementation is not async. No problem, let me wrap it in Task: print(1) Task { print(2) let data = await dataFetcher.fetchSomeData() // process data ... print(3) } print(4) No errors, and this code works exactly as expected, the output is: 1 4 2 3 So now I am wondering: why take the effort of changing/adding code for async/await style function that ultimately end up requiring exactly the same amount of code, and is exactly as non-linear as completionHandlers? Note that the dataFetcher only has one property, an instance ofURLSession, so I am also not even managing my own queues or threads in the oldskool method vs the new one. They just wrap URLSession's functions: func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask and func download(for request: URLRequest, delegate: URLSessionTaskDelegate? = nil) async throws -> (URL, URLResponse) Is async/await useful only with SwiftUI maybe? What am I missing here? Please help me see the light.
8
0
4.8k
4d
Email validation using RegEx and TextField text color
Hello, I wrote a simple email validation test: struct ContentView: View {     @State private var email: String     @State var emailIsValid: Bool = true          public init(email: String = "")     {         self.email = email     }          var body: some View {         Text("Hello, world!")             .padding()                  TextField("Email", text: $email)             .onChange(of: email) { newValue in                 if(newValue.range(of:"^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$", options: .regularExpression) != nil) {                     self.emailIsValid = true                     print("valid")                 } else {                     self.emailIsValid = false                     print("invalid")                 }             }             .foregroundColor(emailIsValid ? Color.green : Color.red)     } } And it works for the email like Test@gmail.com. Text is green. But if I type something like Testerka@gmail.com text stays red. But the print output says 'valid'.
3
0
2.9k
Aug ’23
Swift Concurrency, Core Data, "partially thread-safe" types & Sendable conformance
Hi, Xcode warns me that NSPersistentContainer, NSManagedObjectContext, NSPersistentHistoryTransaction and NSPersistentHistoryToken are non-Sendable types and therefore cannot cross actor boundaries. These warnings occur even when I use @preconcurrency import CoreData (only works with Xcode 14.0 Beta, in Xcode 13.4.1, it says '@preconcurrency' attribute on module 'CoreData' is unused) I understand that types in Core Data have yet to be marked as Sendable when it makes sense. Although NSPersistentHistoryTransaction, and NSPersistentHistoryToken are reference types, they should qualify to be marked as Sendable in the future since these are immutable types, am I right? NSPersistentContainer provides variables and methods like viewContext and newBackgroundContext(). It would make sense that this type is thread-safe. However, I'm not sure about it, especially regarding its loadPersistentStores(completionHandler:) method. Is NSPersistentContainer (and its subclass NSPersistentCloudKitContainer) thread-safe and should it be marked as Sendable in the future? The case of and NSManagedObjectContext confuses me the most. Indeed, it has both thread-safe methods like perform(_:) and thread-unsafe methods like save(). Still, it should be possible to cross actor boundaries. Would such a "partially thread-safe" type quality to be marked as Sendable? If not, how can it cross actor boundaries? The reason I'm asking these questions is that I have a CoreDataStack type. It has mutable variables, such as var lastHistoryToken: NSPersistentHistoryToken?, needs to perform work without blocking the main thread, such as writing the token to a file, has async methods, uses notification observers, and needs to be marked as Sendable to be used by other controllers running on different actors. Since this type is related to back-end work, I made it an Actor. This type exposes the persistent container, and a method to create new background threads. However, I need to explicitly annotate all methods using await context.perform { ... } as nonisolated in this actor. Not doing so causes a data race to be detected at runtime. Is this a bug, and is making a Core Data stack an Actor the proper way to do it or is there a better solution? Any help would be greatly appreciated. Thanks. Xcode Configuration Xcode 13.4.1, Xcode 14.0 beta 5 The Xcode project is configured with Other Swift Flags set to -Xfrontend -warn-concurrency -Xfrontend -enable-actor-data-race-checks.
4
2
2.6k
Oct ’23
ScrollViewProxy scrollTo will crash when scrolling outside of bounds of previous (not current) List data source/array in iPad and iOS 16 beta
Hi, It seems that there's a bug in the iOS and iPadOS 16 betas (i've not test in macOS 13 yet), that when after updating a List data source with a bigger array, scrolling to a row of an offset bigger than the previous data array, with ScrollViewProxy, will crash the app with an EXC_BREAKPOINT (code=1, subcode=0x1099d6004) error. Below I attached a sample code to reproduce the crash. In it when opening there's an empty list. When pressing the "Randomize & Select Last" button at the top, the list will be filled with 5 random UUIDs, followed by scrolling to the last row. The app will crash on the second try, when it will try to scroll to an offset bigger than the previous data array (the last row). As a control there's an "Randomize & Select Random" button that will behave more or less like the "Randomize & Select Last" button but will choose a random row to select and scroll. It will only crash if this select row if of an offset bigger that the size of the previous array. This doesn't happen in iOS 15. I've already posted the Radar as FB11302966, however if someone has any toughs on how to solve this problem (or what I'm doing wrong) they are welcome. Sample code: ///A simple data model for the demo. Only stores an UUID. struct DataModel: Identifiable, Hashable { let id: UUID = UUID() var nameUUID: String { id.uuidString } } struct ContentView: View { ///Array with some data to show @State private var data: [DataModel] = [] ///Selected row @State private var selection: DataModel? var body: some View { VStack(alignment: .leading) { HStack { //Create a new array for showing in the list. //This array will be bigger than the last one. //The selection will be the last element of the array (triggering the bug) Button { //Increment the size of the new List by 5 let numberElements = data.count + 5 //Create a new Array of DataModel with more 5 elements that the previous one let newData = (0 ..< numberElements).map { _ in DataModel() } //Select the last element of the array/list. //This will make sure that the scrollTo will go to the end let newSelection = newData.last //Update STate for the new values data = newData selection = newSelection } label: { Text("Randomize & Select Last") } Spacer() //Create a new array for showing in the list. //This array will be bigger than the last one. //The selection will be the a random element of the array (only triggering the bug when the element is ) Button { //Increment the size of the new List by 5 //If empty will start with 40 (reducing the odds of triggering the bug) let numberElements = data.count == 0 ? 40 : data.count + 5 //Create a new Array of DataModel with more 5 elements that the previous one let newData = (0 ..< numberElements).map { _ in DataModel() } //Select a random element of the array/list. //This will scroll if the element is 'inside' the previous list //Otherwise will crash let newSelection = newData.randomElement() //Update State for the new values data = newData selection = newSelection } label: { Text("Randomize & Select Random") } } .padding() //MARK: ScrollViewReader and List ScrollViewReader { proxy in List(data, selection: $selection) { dataElement in //Row (is only the UUID for the rows Text(dataElement.id.uuidString) .id(dataElement) .tag(dataElement) } //action that fires when data changes //it will scroll to the selection .onChange(of: data, perform: { newValue in if let selection { proxy.scrollTo(selection) } }) } } } }
15
17
6.0k
Sep ’23
[CarPlay] CarPlay Simulator with external accessories
Hi all, I am trying to use the new CarPlay Simulator (the one provided with the Xcode Additional Tools) to test an application that uses a protocol string. My question is: is there a way to edit this protocol string on this application? Because as of right now, my app is not shown in the CarPlay Simulator, as it does not have the required protocol string. I've used the Xcode simulator, and protocol strings can be added using: defaults write com.apple.iphonesimulator CarPlayProtocols -array-add <protocol-string> But I've not found a way to do this on the standalone application. Thank you all in advance
1
0
774
Jul ’23
NWPathMonitor returns .unsatisfied the WiFi is back on simulator
I'm testing network loss handling in my app on the simulator. Turning WiFi OFF triggers pathUpdateHandler with .unsatisfied status. Turning WiFi back to ON triggers pathUpdateHandler with .unsatisfied status again. I noticed that pathUpdateHandler is triggered right after I enabled WiFi, but before WiFi actually connects to the network. When the laptop is actually connected to the WiFi network - pathUpdateHandler isn't triggered, so my app stays in "offline" mode permanently. networkMonitor.pathUpdateHandler = { [weak self] path in guard let self = self else { return } DispatchQueue.main.async { if path.status == .satisfied { self.status = .connected } else { print(path.unsatisfiedReason) self.status = .disconnected } } } monitor.start(queue: queue) networkMonitor is retained by my DIContainer
2
0
2k
Aug ’23
xcode14:Library not loaded: /usr/lib/swift/libswiftCoreGraphics.dylib
Xcode13.4.1 is running properly, but after upgrading Xcode14, the debugging device reports an error: Library not loaded: / usr/lib/swift/libswiftCoreGraphics dylib, I according to the online solutions are tried, can't solve my problem, problem is ios10.3.3 equipment, unable to debug, also is unable to start the application success after packaging, Is this a problem with xcode14 itself?
33
14
25k
Jun ’24
Error throws while using the speech recognition service in my app
Recently I updated to Xcode 14.0. I am building an iOS app to convert recorded audio into text. I got an exception while testing the application from the simulator(iOS 16.0). [SpeechFramework] -[SFSpeechRecognitionTask handleSpeechRecognitionDidFailWithError:]_block_invoke Ignoring subsequent recongition error: Error Domain=kAFAssistantErrorDomain Code=1101 "(null)" Error Domain=kAFAssistantErrorDomain Code=1107 "(null)" I have to know what does the error code means and why this error occurred.
19
3
7.9k
Feb ’24
Error using file importer in SwiftUI app in combination with Firebase Storage
Trying to use file importer in a swift app to upload documents into firebase Storage and getting error when running on live device but works perfectly fine on emulator. error: BackgroundSession <***...> Failed to issue sandbox extension for file file:///private/var/mobile/Library/Mobile%20Documents/comappleCloudDocs/Sample.pdf, errno = [1: Operation not permitted] UNKNOWN ERROR Error Domain=FIRStorageErrorDomain Code=-13000 "An unknown error occurred, please check the server response." UserInfo={object=Repository/Sample.pdf, ResponseBody=Can not finalize upload. Current size is 0. Expected final size is 2665098., bucket=bucket, data={length = 77, bytes = 0x43616e20 6e6f7420 66696e61 6c697a65 ... 32363635 3039382e }, data_content_type=text/plain; charset=utf-8, NSLocalizedDescription=An unknown error occurred, please check the server response., ResponseErrorDomain=com.google.HTTPStatus, ResponseErrorCode=400} I tried separating all the logic from selectedFile.startAccessingSecurityScopedResource() all the way through the end into a function of its own using @MainActor based on another post I found around here and issue persisted.. Below is the implementation: .fileImporter( isPresented: $fileImporterIsPresented, allowedContentTypes: [.pdf], allowsMultipleSelection: false ) { result in switch result { case .success(let url): print(url) guard let selectedFile:URL = url.first else { return } guard selectedFile.startAccessingSecurityScopedResource() else { return } let firebaseRepository = Storage.storage().reference().child("Repository/Sample.pdf") let uploadTask = firebaseRepository.putFile(from: selectedFile) uploadTask.observe(.progress) { snapshot in // Upload reported progress percentComplete = 100.0 * Double(snapshot.progress!.completedUnitCount) / Double(snapshot.progress!.totalUnitCount) } uploadTask.observe(.success) { snapshot in selectedFile.stopAccessingSecurityScopedResource() uploadTask.removeAllObservers() print("SUCCESS") // Upload completed successfully } uploadTask.observe(.failure) { snapshot in if let error = snapshot.error as? NSError { switch (StorageErrorCode(rawValue: error.code)!) { case .objectNotFound: print("NOT FOUND") // File doesn't exist break case .unauthorized: print("UNAUTHORIZED") // User doesn't have permission to access file break case .cancelled: print("CANCELLED") // User canceled the upload break /* ... */ case .unknown: print("UNKNOWN ERROR \(error.description)") print("UNKNOWN ERROR \(error.localizedDescription)") print("UNKNOWN ERROR \(error.underlyingErrors)") // Unknown error occurred, inspect the server response break default: print("UNSPECIFIED ERROR") // A separate error occurred. This is a good place to retry the upload. break } } } case .failure(let error): print(error) } }
1
0
1.8k
Aug ’23
'Application tried to present modally a view controller <_SFAppPasswordSavingViewController: 0x11fb2ac60> that is already being presented by <UIKeyboardHiddenViewController_Save: 0x118f7fde0>.'
Hi, I am working on an iPad application that has both Portrait and Landscape orientation. The issue that I am facing is regarding the the popup presentation that iPad shows you for saving password while you log-in in the application. Now, when the pop-up is presented, at that moment if I try to rotate the device, the application crashes with the message Application tried to present modally a view controller <_SFAppPasswordSavingViewController: 0x107be7230> that is already being presented by <UIKeyboardHiddenViewController_Save: 0x107a49190>. Now, the problem is that SFAppPasswordSavingViewController presentation is not controlled by me. Also UIKeyboardHiddenViewController_Save,is something I am not controlling. Please help me out on how to solve this issue or let me know if I am missing anything.
2
1
2.9k
Jul ’23