Dive into the world of programming languages used for app development.

All subtopics
Posts under Programming Languages topic

Post

Replies

Boosts

Views

Activity

The Peril of the Ampersand
A few years ago [1] Xcode added new warnings that help detect a nasty gotcha related to the lifetime of unsafe pointers. For example: Initialization of 'UnsafeMutablePointer<timeval>' results in a dangling pointer Inout expression creates a temporary pointer, but argument 'iov_base' should be a pointer that outlives the call to 'init(iov_base:iov_len:)' I’ve seen a lot of folks confused by these warnings, and by the lifetime of unsafe pointers in general, and this post is my attempt to clarify the topic. If you have questions about any of this, please put them in a new thread in the Programming Languages > Swift topic. Finally, I encourage you to watch the following WWDC presentations: WWDC 2020 Session 10648 Unsafe Swift WWDC 2020 Session 10167 Safely manage pointers in Swift These cover some of the same ground I’ve covered here, and a lot of other cool stuff as well. Share and Enjoy — Quinn “The Eskimo!” Apple Developer Relations, Developer Technical Support, Core OS/Hardware let myEmail = "eskimo" + "1" + "@apple.com" [1] Swift 5.2.2, as shipped in Xcode 11.4. See the discussion of SR-2790 in Xcode 11.4 Release Notes. Basics In Swift, the ampersand (&) indicates that a parameter is being passed inout. Consider this example: func addVarnish(_ product: inout String) { product += " varnish" } var waffle = "waffle" addVarnish(&waffle) // line A print(waffle) // printed: waffle varnish On line A, the ampersand tells you that waffle could be modified by addVarnish(_:). However, there is another use of ampersand that was designed to help with C interoperability. Consider this code: var tv = timeval() gettimeofday(&tv, nil) print(tv) // printed: timeval(tv_sec: 1590743104, tv_usec: 77027) The first parameter to gettimeofday is an UnsafeMutablePointer<timeval>. Here the ampersand denotes a conversion from a timeval to an UnsafeMutablePointer<timeval>. This conversion makes it much easier to call common C APIs from Swift. This also works for array values. For example: var hostName = [CChar](repeating: 0, count: 256) gethostname(&hostName, hostName.count) print(String(cString: hostName)) // printed: slimey.local. In this code the ampersand denotes a conversion from [CChar] to an UnsafeMutablePointer<CChar> that points to the base of the array. While this is convenient, it’s potentially misleading, especially if you come from a C background. In C-based languages, using ampersand in this way yields a pointer to the value that’s valid until the value gets deallocated. That’s not the case in Swift. Rather, the pointer generated by the ampersand syntax is only valid for the duration of that function call. To understand why that’s the case, consider this code: struct TimeInTwoParts { var sec: time_t = 0 var usec: Int32 = 0 var combined: timeval { get { timeval(tv_sec: sec, tv_usec: usec) } set { sec = newValue.tv_sec usec = newValue.tv_usec } } } var time = TimeInTwoParts() gettimeofday(&time.combined, nil) // line A print(time.combined) // printed: timeval(tv_sec: 1590743484, tv_usec: 89118) print(time.sec) // printed: 1590743484 print(time.usec) // printed: 89118 Here combined is a computed property that has no independent existence in memory. Thus, it simply makes no sense to take the address of it. So, how does ampersand deal with this? Under the covers the Swift compiler expands line A to something like this: var tmp = time.combined gettimeofday(&tmp, nil) time.combined = tmp Once you understand this it’s clear why the resulting pointer is only valid for the duration of the call: As soon as Swift cleans up tmp, the pointer becomes invalid. A Gotcha This automatic conversion can be a nasty gotcha. Consider this code: var tv = timeval() let tvPtr = UnsafeMutablePointer(&tv) // line A // ^~~~~~~~~~~~~~~~~~~~~~~~~ // Initialization of 'UnsafeMutablePointer<timeval>' results in a dangling pointer gettimeofday(tvPtr, nil) // line B This results in undefined behaviour because the pointer generated by the ampersand on line A is no longer valid when it’s used on line B. In some cases, like this one, the later Swift compiler is able to detect this problem and warn you about it. In other cases you’re not so lucky. Consider this code: guard let f = fopen("tmp.txt", "w") else { … } var buf = [CChar](repeating: 0, count: 1024) setvbuf(f, &buf, _IOFBF, buf.count) // line A let message = [UInt8]("Hello Crueld World!".utf8) fwrite(message, message.count, 1, f) // line B fclose(f) // line C This uses setvbuf to apply a custom buffer to the file handle. The file handle uses this buffer until after the close on line C. However, the pointer created by the ampersand on line A only exists for the duration of the setvbuf call. When the code calls fwrite on line B the buffer pointer is no longer valid and things end badly. Unfortunately the compiler isn’t able to detect this problem. Worse yet, the code might actually work initially, and then stop working as you change optimisation settings, update the compiler, change unrelated code, and so on. Another Gotcha There is another gotcha associated with the ampersand syntax. Consider this code: class AtomicCounter { var count: Int32 = 0 func increment() { OSAtomicAdd32(1, &count) } } This looks like it’ll implement an atomic counter but there’s no guarantee that the counter will be atomic. To understand why, apply the tmp transform from earlier: class AtomicCounter { var count: Int32 = 0 func increment() { var tmp = count OSAtomicAdd32(1, &tmp) count = tmp } } So each call to OSAtomicAdd32 could potentially be operating on a separate copy of the counter that’s then assigned back to count. This undermines the whole notion of atomicity. Again, this might work in some builds of your product and then fail in other builds. Note The above discussion is now theoretical because Swift 6 added a Synchronization module that includes comprehensive support for atomics. That module also has a Mutex type (if you need a mutex on older platforms, check out OSAllocatedUnfairLock). These constructs use various different mechanisms to ensure that the underlying value has a stable address. Summary So, to summarise: Swift’s ampersand syntax has very different semantics from the equivalent syntax in C. When you use an ampersand to convert from a value to a pointer as part of a function call, make sure that the called function doesn’t use the pointer after it’s returned. It is not safe to use the ampersand syntax for functions where the exact pointer matters. It’s Not Just Ampersands There’s one further gotcha related to arrays. The gethostname example above shows that you can use an ampersand to pass the base address of an array to a function that takes a mutable pointer. Swift supports two other implicit conversions like this: From String to UnsafePointer<CChar> — This allows you to pass a Swift string to an API that takes a C string. For example: let greeting = "Hello Cruel World!" let greetingLength = strlen(greeting) print(greetingLength) // printed: 18 From Array<Element> to UnsafePointer<Element> — This allows you to pass a Swift array to a C API that takes an array (in C, arrays are typically represented as a base pointer and a length). For example: let charsUTF16: [UniChar] = [72, 101, 108, 108, 111, 32, 67, 114, 117, 101, 108, 32, 87, 111, 114, 108, 100, 33] print(charsUTF16) let str = CFStringCreateWithCharacters(nil, charsUTF16, charsUTF16.count)! print(str) // prints: Hello Cruel World! Note that there’s no ampersand in either of these examples. This technique only works for UnsafePointer parameters (as opposed to UnsafeMutablePointer parameters), so the called function can’t modify its buffer. As the ampersand is there to indicate that the value might be modified, it’s not used in this immutable case. However, the same pointer lifetime restriction applies: The pointer passed to the function is only valid for the duration of that function call. If the function keeps a copy of that pointer and then uses it later on, Bad Things™ will happen. Consider this code: func printAfterDelay(_ str: UnsafePointer<CChar>) { print(strlen(str)) // printed: 18 DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { print(strlen(str)) // printed: 0 } } let greeting = ["Hello", "Cruel", "World!"].joined(separator: " ") printAfterDelay(greeting) dispatchMain() The second call to strlen yields undefined behaviour because the pointer passed to printAfterDelay(_:) becomes invalid once printAfterDelay(_:) returns. In this specific example the memory pointed to by str happened to contain a zero, and hence strlen returned 0 but that’s not guaranteed. The str pointer is dangling, so you might get any result from strlen, including a crash. Advice So, what can you do about this? There’s two basic strategies here: Extend the lifetime of the pointer Manual memory management Extending the Pointer’s Lifetime The first strategy makes sense when you have a limited number of pointers and their lifespan is limited. For example, you can fix the setvbuf code from above by changing it to: let message = [UInt8]("Hello Crueld World!".utf8) guard let f = fopen("tmp.txt", "w") else { … } var buf = [CChar](repeating: 0, count: 1024) buf.withUnsafeMutableBufferPointer { buf in setvbuf(f, buf.baseAddress!, _IOFBF, buf.count) fwrite(message, message.count, 1, f) fclose(f) } This version of the code uses withUnsafeMutableBufferPointer(_:). That calls the supplied closure and passes it a pointer (actually an UnsafeMutableBufferPointer) that’s valid for the duration of that closure. As long as you only use that pointer inside the closure, you’re safe! There are a variety of other routines like withUnsafeMutableBufferPointer(_:), including: The withUnsafeMutablePointer(to:_:) function The withUnsafeBufferPointer(_:), withUnsafeMutableBufferPointer(_:), withUnsafeBytes(_:), and withUnsafeMutableBytes(_:) methods on Array The withUnsafeBytes(_:) and withUnsafeMutableBytes(_:) methods on Data The withCString(_:) and withUTF8(_:) methods on String. Manual Memory Management If you have to wrangle an unbounded number of pointers — or the lifetime of your pointer isn’t simple, for example when calling an asynchronous call — you must revert to manual memory management. Consider the following code, which is a Swift-friendly wrapper around posix_spawn: func spawn(arguments: [String]) throws -> pid_t { var argv = arguments.map { arg -> UnsafeMutablePointer<CChar>? in strdup(arg) } argv.append(nil) defer { argv.forEach { free($0) } } var pid: pid_t = 0 let success = posix_spawn(&pid, argv[0], nil, nil, argv, environ) == 0 guard success else { throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno), userInfo: nil) } return pid } This code can’t use the withCString(_:) method on String because it has to deal with an arbitrary number of strings. Instead, it uses strdup to copy each string to its own manually managed buffer. And, as these buffers are manually managed, is has to remember to free them. Change History 2024-12-11 Added a note about the Synchronization module. Made various editorial changes. 2021-02-24 Fixed the formatting. Added links to the WWDC 2021 sessions. Fixed the feedback advice. Minor editorial changes. 2020-06-01 Initial version.
0
0
9.8k
Dec ’24
Ambiguous use of 'textField' in Xcode 26
func textField( _ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String ) -&gt; Bool { if let delegate = delegate, let shouldChangeCharactersIn = delegate.textField { return shouldChangeCharactersIn(textField, range, string) } return true } This is from an extension extension TextInput: UITextFieldDelegate, ObservableTextFieldDelegateProtocol { The delegate is already a UITextFieldDelegate, but when you click on the error, it returns 7 instances of: "Found this candidate in module 'UIKit' (UIKit.UITextFieldDelegate.textField)" This doesn't give an error in Xcode 16. Is this an Xcode 26 bug?
0
0
146
Jun ’25
AVExportSession in Xcode16 - "exportAsynchronouslyWithCompletionHandler: more than once."
I’m experiencing a crash at runtime when trying to extract audio from a video. This issue occurs on both iOS 18 and earlier versions. The crash is caused by the following error: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '*** -[AVAssetExportSession exportAsynchronouslyWithCompletionHandler:] Cannot call exportAsynchronouslyWithCompletionHandler: more than once. (0x1851435ec 0x1826dd244 0x1970c09c0 0x214d8f358 0x214d95899 0x190a1c8b9 0x214d8efd9 0x30204cef5 0x302053ab9 0x190a5ae39) libc++abi: terminating due to uncaught exception of type NSException My previous code worked fine, but it's crashing with Swift 6. Does anyone know a solution for this? Previous code: func extractAudioFromVideo(from videoURL: URL, exportHandler: ((AVAssetExportSession, CurrentValueSubject<Float, Never>?) -> Void)? = nil, completion: @escaping (Swift.Result<URL, Error>) -> Void) { let asset = AVAsset(url: videoURL) // Create an AVAssetExportSession to export the audio track guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) else { completion(.failure(NSError(domain: "com.example.app", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to create AVAssetExportSession"]))) return } // Set the output file type and path guard let filename = videoURL.lastPathComponent.components(separatedBy: ["."]).first else { return } let outputURL = VideoUtils.getTempAudioExportUrl(filename) VideoUtils.deleteFileIfExists(outputURL.path) exportSession.outputFileType = .m4a exportSession.outputURL = outputURL let audioExportProgressPublisher = CurrentValueSubject<Float, Never>(0.0) if let exportHandler = exportHandler { exportHandler(exportSession, audioExportProgressPublisher) } // Periodically check the progress of the export session let timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { _ in audioExportProgressPublisher.send(exportSession.progress) } // Export the audio track asynchronously exportSession.exportAsynchronously { switch exportSession.status { case .completed: completion(.success(outputURL)) case .failed: completion(.failure(exportSession.error ?? NSError(domain: "com.example.app", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unknown error occurred while exporting audio"]))) case .cancelled: completion(.failure(NSError(domain: "com.example.app", code: -1, userInfo: [NSLocalizedDescriptionKey: "Export session was cancelled"]))) default: completion(.failure(NSError(domain: "com.example.app", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unknown export session status"]))) } // Invalidate the timer when the export session completes or is cancelled timer.invalidate() } } ## New Code: func extractAudioFromVideo(from videoURL: URL, exportHandler: ((AVAssetExportSession, CurrentValueSubject<Float, Never>?) -> Void)? = nil, completion: @escaping (Swift.Result<URL, Error>) -> Void) { let asset = AVAsset(url: videoURL) // Create an AVAssetExportSession to export the audio track guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) else { completion(.failure(NSError(domain: "com.example.app", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to create AVAssetExportSession"]))) return } // Set the output file type and path guard let filename = videoURL.lastPathComponent.components(separatedBy: ["."]).first else { return } let outputURL = VideoUtils.getTempAudioExportUrl(filename) VideoUtils.deleteFileIfExists(outputURL.path) exportSession.outputFileType = .m4a exportSession.outputURL = outputURL let audioExportProgressPublisher = CurrentValueSubject<Float, Never>(0.0) if let exportHandler { exportHandler(exportSession, audioExportProgressPublisher) } let task = Task { if #available(iOS 18.0, *) { // Handle export for iOS 18 and later let states = exportSession.states(updateInterval: 0.1) for await state in states { switch state { case .pending, .waiting: break case .exporting(progress: let progress): print("Exporting: \(progress.fractionCompleted)") if progress.isFinished { completion(.success(outputURL)) } else if progress.isCancelled { completion(.failure(NSError(domain: "com.example.app", code: -1, userInfo: [NSLocalizedDescriptionKey: "Export session was cancelled"]))) } else { audioExportProgressPublisher.send(Float(progress.fractionCompleted)) } } } try await exportSession.export(to: outputURL, as: .m4a) // Only call export once } else { // Handle export for iOS versions below 18 let publishTimer = Timer.publish(every: 0.1, on: .main, in: .common) .autoconnect() .sink { [weak exportSession] _ in guard let exportSession = exportSession else { return } audioExportProgressPublisher.send(exportSession.progress) } // Only call export once await exportSession.export() // Handle the export session's status switch exportSession.status { case .completed: completion(.success(outputURL)) case .failed: completion(.failure(exportSession.error ?? NSError(domain: "com.example.app", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unknown error occurred while exporting audio"]))) case .cancelled: completion(.failure(NSError(domain: "com.example.app", code: -1, userInfo: [NSLocalizedDescriptionKey: "Export session was cancelled"]))) default: completion(.failure(NSError(domain: "com.example.app", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unknown export session status"]))) } // Invalidate the timer when the export session completes or is cancelled publishTimer.cancel() } } task.cancel() }
0
0
438
Dec ’24
Swift playground
Hi, I want to create a dashboard in a app using swift playgrounds with esp 32 and a led. The dashboard should have a toggle switch to toggle the switch state like on/off for the led once i get the basics i want to create a full dashboards with things like gauges, sliders, button and many more. Can someone please help/guide me. Thanks.
0
0
301
Dec ’24
App Settings Not Appearing with Xcode 16.2
I recently encountered an issue with Xcode 16.2 while attempting to integrate Settings.bundle into a new app. I added Settings.bundle as a new file (using the provided template), but when I ran the app (the standard simple "Hello World" project), the expected three default controls (Name, Enabled, Slider) did not appear in the app's settings. To troubleshoot, I downgraded my system to macOS Sonoma 14.7.2 and Xcode 15.4 (on a 2023 Mac Mini, M2). After this downgrade, everything worked as expected. With a new project, adding Settings.bundle, and running the app, the settings entry for the app appeared, including the three default fields. This behavior suggests a potential issue or incompatibility with Xcode 16.2.
0
1
438
Dec ’24
Is it possible to Add Reply of Push Notification from Airpod using Voice ?
We want to do below addition to iOS Mobile App. Airpod announces Push notification = which is workking now we want to use voice command that "Reply to this" and sending Reply to that notification but it is saying it is not supported in your app. So basically we need to use feature - Listen and respond to messages with AirPods Do we need to add any integration inside app for this or it will directly worked with Siri settings ? Is it possible to do in non messaging App? Is it possible to do without syncing contacts ?
0
0
481
Dec ’24
The compiler is unable to type-check this expression in reasonable time
This is one of the worst errors you can encounter while developing with Xcode. It looks like it's related to a problem inside the compiler itself: when there are lot of lines of code, it becomes unable to identify them all and start asking you to break down the code in smaller pieces. Sometimes you can, sometimes not. First of all, in your code there is FOR SURE an error, so in case of the second option, begin commenting entires sections of your code: this can lead to two options: You commented a section that contains the error: Xcode give you the preview and you check the commented section to find the error You commented enough code to let the compiler do its job, and you'll have the normal error reported in your code: again, fix it! Once errors have been fixed, normally you can uncomment what you excluded and all will go up and ok again. The most common errors that can lead to this behavior (but it's just a hint) are those involving parameters got or passed to other SwiftUI objects: parameters label (mistyped, missing, exceeding) parameters values (not $/& present, $/& present but not required) parameters types (you passed a wrong type) Well, I hope that this post could be useful to others that, like I did, are struggling a lot to understand the exact nature of this peculiar error. Code well and Prosper!
0
1
592
Oct ’24
Webview In-App Browser Microsoft Login Redirection Not Working
Hello, We received a rejection on one of our IOS applications because we were doing Microsoft MSAL login through the user's browser. The representative recommended that we use Webview to do in-app logins. However when we tried to handle the custom app uri redirection (looking like myapp://auth/), Webview does not seem to send the user back to the application. Does anyone have a fix for this? Thanks!
0
0
91
13h
Swift Package Manager – Support for Multiple Targets with Distinct Localization Files
I am an SDK provider working with Swift Package Manager (SPM) to deliver libraries for iOS developers. My SDK currently uses SPM targets to modularize functionality. However, SPM enforces strict resource bundling, which prevents me from efficiently offering multiple targets—each with a different set of localization files—in a single package. Current Limitation: When multiple SPM targets share the same source and resource directory but require distinct sets of .lproj localization folders (for app size or client requirements), SPM raises “overlapping sources” errors. The only workaround is to manually split resource directories or have clients prune localizations post-build, which is inefficient and error-prone. Feature Request: Please consider adding native support in Swift Package Manager for: Defining multiple targets within a single package that can process overlapping source/resource directories, Each target specifying a distinct subset of localization resource files via the exclude or a new designated parameter, Enabling efficient modular delivery of SDKs to clients needing different localization payloads, without redundant resource duplication or error-prone manual pruning. Support for this feature would greatly ease SDK distribution, lower app sizes, and improve package maintainability for iOS and all Swift platforms.
0
0
866
2w
WKWebView missing page parts
Hi guys, I've been struggling for a few days with this really weird behaviour. We made an app for our e-commerce website and found out that a part of the product page is missing. For any reason, the header and first blocks of the page and footer are displayed, but then a massive part of the content is missing. This content is not loaded through ajax; that's why I don't understand why it's not displayed. You can see here 2 screenshots of what the page should look like and what the page looks like with WKWebView. I've been inspecting this with Safari; there isn't any blocking error in the console, and html elements are just empty. There is the div with class row and nothing in it. The same website is working perfectly with native Android Webview. If anyone has any clue to find out what's going wrong
0
0
277
Jan ’25
orientation transaction token
Hello Im having an error in swiftUI project of mine. I use fullscreencover to navigate through views. Normally it s been working but one point it doesn't. I go through MainMenu -> SomeOtherView -> GameView -> AfterGameView -> SomeOtherView -> MainMenu. When it comes to mainmenu at last, it s showing main menu for a glimpse of a look and then goes back to GameView. In console an error took my notice. > A new orientation transaction token is being requested while a valid one already exists. reason=Fullscreen transition (dismissing): fromVC=<_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x10795ca00>; toVC=<_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x1071c3400>;; windowOrientation=portrait; sceneOrientation=portrait; existingTransaction=<_UIForcedOrientationTransactionToken: 0x600001804a40; state: active; originalOrientation: portrait (1)> Cant really finding the solution. Need help asap I will release a bug update to Appstore.
0
0
447
Jan ’25
Passkey Creation SDK does not return Timeout Error on FaceID authentication times out.
We would like to show a user-friendly message but can not. Description: When attempting to create a duplicate passkey using the ASAuthrorizationController in iOS, the Face ID authentication times out SDK does not return a timeout specific error. Instead, it directly returns an error stating that duplicate passkey cannot be created. SDK to first handle the FaceID timeout case and provide a distinct timeout error so we can gracefully manage this scenario before the duplicate passkey validation occurs. Steps to Reproduce: Implement passkey creation flow using ASAuthorizationController. Attempt to register a duplicate passkey (e.g., using the same user ID and challenge). Let FaceID prompt timeout (do not interact with the authentication prompt).
0
0
244
Dec ’24
AppleScriptLauncher Menu App
I'm primarily an AppleScript writer and only a novice programmer, using ChatGPT to help me with the legwork. It has helped me to write a functioning app that builds a menu structure based on the scripts I have in the Scripts directory used in the script menu and then runs the applescripts. When I distribute the app to my desktop and run it, the scripts that access other apps, like InDesign will cause it to launch, but not actually do anything. I included the ids for each app in the entitlements dictionary and have given the app full disk access in system settings, but it's not functioning as I'd expect. I know there are apps like Alfred that allow you to run scripts from a keystroke, but I'm building this for others I work with so they can also access info about each script, what it does, and how to use it from the menu, as well as key commands to run them. Not sure what else to say, but if this sounds like a simple fix to anyone, please let me know.
0
0
433
Dec ’24
Animatable AnyInsettableShape
System provides AnyShape type erasure that animates correctly. But system doesn't provide AnyInsettableShape. Here is my implementation of AnyInsettableShape (and AnyAnimatableData that is needed to support animation). Let me know if there is simpler solution. struct AnyInsettableShape: InsettableShape { private let _path: (CGRect) -> Path private let _inset: (CGFloat) -> AnyInsettableShape private let _getAnimatableData: () -> AnyAnimatableData private let _setAnimatableData: (_ data: AnyAnimatableData) -> AnyInsettableShape init<S>(_ shape: S) where S : InsettableShape { _path = { shape.path(in: $0) } _inset = { AnyInsettableShape(shape.inset(by: $0)) } _getAnimatableData = { AnyAnimatableData(shape.animatableData) } _setAnimatableData = { data in guard let otherData = data.rawValue as? S.AnimatableData else { assertionFailure(); return AnyInsettableShape(shape) } var shape = shape shape.animatableData = otherData return AnyInsettableShape(shape) } } var animatableData: AnyAnimatableData { get { _getAnimatableData() } set { self = _setAnimatableData(newValue) } } func path(in rect: CGRect) -> Path { _path(rect) } func inset(by amount: CGFloat) -> some InsettableShape { _inset(amount) } } struct AnyAnimatableData : VectorArithmetic { init<T : VectorArithmetic>(_ value: T) { self.init(optional: value) } private init<T : VectorArithmetic>(optional value: T?) { rawValue = value _scaleBy = { factor in (value != nil) ? AnyAnimatableData(value!.scaled(by: factor)) : .zero } _add = { other in AnyAnimatableData(value! + (other.rawValue as! T)) } _subtract = { other in AnyAnimatableData(value! - (other.rawValue as! T)) } _equal = { other in value! == (other.rawValue as! T) } _magnitudeSquared = { (value != nil) ? value!.magnitudeSquared : .zero } _zero = { AnyAnimatableData(T.zero) } } fileprivate let rawValue: (any VectorArithmetic)? private let _scaleBy: (_: Double) -> AnyAnimatableData private let _add: (_ other: AnyAnimatableData) -> AnyAnimatableData private let _subtract: (_ other: AnyAnimatableData) -> AnyAnimatableData private let _equal: (_ other: AnyAnimatableData) -> Bool private let _magnitudeSquared: () -> Double private let _zero: () -> AnyAnimatableData mutating func scale(by rhs: Double) { self = _scaleBy(rhs) } var magnitudeSquared: Double { _magnitudeSquared() } static let zero = AnyAnimatableData(optional: nil as Double?) @inline(__always) private var isZero: Bool { rawValue == nil } static func + (lhs: AnyAnimatableData, rhs: AnyAnimatableData) -> AnyAnimatableData { guard let (lhs, rhs) = fillZeroTypes(lhs, rhs) else { return .zero } return lhs._add(rhs) } static func - (lhs: AnyAnimatableData, rhs: AnyAnimatableData) -> AnyAnimatableData { guard let (lhs, rhs) = fillZeroTypes(lhs, rhs) else { return .zero } return lhs._subtract(rhs) } static func == (lhs: AnyAnimatableData, rhs: AnyAnimatableData) -> Bool { guard let (lhs, rhs) = fillZeroTypes(lhs, rhs) else { return true } return lhs._equal(rhs) } @inline(__always) private static func fillZeroTypes(_ lhs: AnyAnimatableData, _ rhs: AnyAnimatableData) -> (AnyAnimatableData, AnyAnimatableData)? { switch (!lhs.isZero, !rhs.isZero) { case (true, true): (lhs, rhs) case (true, false): (lhs, lhs._zero()) case (false, true): (rhs._zero(), rhs) case (false, false): nil } } }
0
0
422
Dec ’24
Decryption failure - Migrated from Objective-C to Swift (AES256 Decryption failure in swift language)
Decrypting Data to String Conversion failure Development environment: Xcode 15.4, macOS 14.7 Run-time configuration: iOS 15.8.1 & 16.0.1 DESCRIPTION OF PROBLEM We were using objective C implementation of CCCrypt(see below) in our app earlier which we migrated to swift implementation recently. We convert the byte array that CCCrypt returns into Data, and data to string to read the decrypted value. It works perfectly fine in Objective C, whereas with new swift implementation this conversion is failing, it looks like CCCrypt is returning byte array with few non UTF8 characters and that conversion is failing in swift since Objective C is more tolerant with this conversion and converts the byte array to Data and then to string even though there are few imperfect UTF characters in the array. Objective C CCCryptorStatus CCCrypt( CCOperation op, /* kCCEncrypt, etc. / CCAlgorithm alg, / kCCAlgorithmAES128, etc. / CCOptions options, / kCCOptionPKCS7Padding, etc. */ const void *key, size_t keyLength, const void iv, / optional initialization vector */ const void dataIn, / optional per op and alg */ size_t dataInLength, void dataOut, / data RETURNED here */ size_t dataOutAvailable, size_t *dataOutMoved) API_AVAILABLE(macos(10.4), ios(2.0)); Swift Code CCCrypt(_ op: CCOperation, _ alg: CCAlgorithm, _ options: CCOptions, _ key: UnsafeRawPointer!, _ keyLength: Int, _ iv: UnsafeRawPointer!, _ dataIn: UnsafeRawPointer!, _ dataInLength: Int, _ dataOut: UnsafeMutableRawPointer!, _ dataOutAvailable: Int, _ dataOutMoved: UnsafeMutablePointer!) -> CCCryptorStatus Data to String Conversion String(data: decryptedData, encoding: .utf8) STEPS TO REPRODUCE Able to reproduce on below devices iPhone - 7 OS Version 15.8.1 iPhone 14- Pro OS Version 16.0.2 iPhone 15 iOS 18.0.1 **Decryption method return "Data" and converting into string using ".utf8" but String conversion is failing on above devices and some other devices as well. Decryption failure not occurring always. ** Below code used for String conversion String(data: decryptedData, encoding: .utf8)
0
0
243
Dec ’24
Exposing Objective-C API to Swift inside a Framework (Private Framework API)
My framework has private Objective-C API that is only used within the framework. It should not be exposed in the public interface (so it shouldn't be imported in the umbrella header). To expose this API to Swift that's within the framework only the documentation seems to indicate that this needs to be imported in the umbrella header? Import Code Within a Framework Target To use the Objective-C declarations in files in the same framework target as your Swift code, configure an umbrella header as follows: 1.Under Build Settings, in Packaging, make sure the Defines Module setting for the framework target is set to Yes. 2.In the umbrella header, import every Objective-C header you want to expose to Swift. Swift sees every header you expose publicly in your umbrella header. The contents of the Objective-C files in that framework are automatically available from any Swift file within that framework target, with no import statements. Use classes and other declarations from your Objective-C code with the same Swift syntax you use for system classes. I would imagine that there must be a way to do this?
0
0
265
Jul ’25
Why Actor-isolated property cannot be passed 'inout' to 'async' function call?
Considering below dummy codes: @MainActor var globalNumber = 0 @MainActor func increase(_ number: inout Int) async { // some async code excluded number += 1 } class Dummy: @unchecked Sendable { @MainActor var number: Int { get { globalNumber } set { globalNumber = newValue } } @MainActor func change() async { await increase(&number) //Actor-isolated property 'number' cannot be passed 'inout' to 'async' function call } } I'm not really trying to make an increasing function like that, this is just an example to make everything happen. As for why number is a computed property, this is to trigger the actor-isolated condition (otherwise, if the property is stored and is a value type, this condition will not be triggered). Under these conditions, in function change(), I got the error: Actor-isolated property 'number' cannot be passed 'inout' to 'async' function call. My question is: Why Actor-isolated property cannot be passed 'inout' to 'async' function call? What is the purpose of this design? If this were allowed, what problems might it cause?
0
0
378
Feb ’25
Instance methods don't work on iOS18.2.
I am using CHCSVParser in objective-c to use the CSVString extension of the Array instance method. When I installed a new app on iOS18.1.1, the correct value (@"Application,"abc,def"") was returned for both the first and second turns, but when I installed a new app on iOS18.2, the correct value was returned for the first turn, but @"" was returned for the second turn. Even when I debug with step into, I can enter the CSVString for the first turn, but I cannot enter it for the second turn and after. It's as if the instance method is not being generated. There are in-app purchases between the first and second turns, but the view controllers that are called are also the same. Is there any change between iOS18.1.1 and iOS18.2? [Code] NSArray *application = [NSArray arrayWithObjects:KEY_APPLICATION, @"abc,def", nil]; NSString *applistring = [application CSVString]; NSString *appliStr = [application CSVString]; [Debug window 18.1.1 First] application __NSArrayI * @"2 elements" 0x0000000302118c00 [0] __NSCFConstantString * @"Application" 0x00000001005deab8 [1] __NSCFConstantString * @"abc,def" 0x00000001005deb78 applistring __NSCFString * @"Application,"abc,def"" 0x0000000302f7d050 appliStr __NSCFString * @"Application,"abc,def"" 0x0000000302f706f0 [18.1.1 Second] application __NSArrayI * @"2 elements" 0x00000003021b5200 [0] __NSCFConstantString * @"Application" 0x00000001005deab8 [1] __NSCFConstantString * @"abc,def" 0x00000001005deb78 applistring __NSCFString * @"Application,"abc,def"" 0x0000000302ff6dc0 appliStr __NSCFString * @"Application,"abc,def"" 0x0000000302fa4d20 [18.2 First] sapplication __NSArrayI * @"2 elements" 0x00000003019d7e80 [0] __NSCFConstantString * @"Application" 0x00000001041c6ab8 [1] __NSCFConstantString * @"abc,def" 0x00000001041c6b78 applistring __NSCFString * @"Application,"abc,def"" 0x000000030179e430 appliStr __NSCFString * @"Application,"abc,def"" 0x000000030179e5e0 [18.2 Second] application __NSArrayI * @"2 elements" 0x00000003019679a0 [0] __NSCFConstantString * @"Application" 0x00000001041c6ab8 [1] __NSCFConstantString * @"abc,def" 0x00000001041c6b78 applistring __NSCFConstantString * @"" 0x00000001efa04768 appliStr __NSCFConstantString * @"" 0x00000001efa04768
0
0
487
Dec ’24