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

FileDescriptor writing to an unexpected file
I'm using a file descriptor to write into a file. I've encountered a problem where if the underlying file is removed or recreated, the file descriptor becomes unstable. I have no reliable way to confirm if it's writing on the expected file. let url = URL(fileURLWithPath: "/path/") try FileManager.default.removeItem(at: url) FileManager.default.createFile(atPath: url.path, contents: .empty) let filePath = FilePath(url.path) var fileDescriptor = try FileDescriptor.open(filePath, .readWrite) // The file is recreated - may be done from a different process. try FileManager.default.removeItem(at: url) // L9 FileManager.default.createFile(atPath: url.path, contents: .empty) // L10 let dataToWrite = Data([1,1,1,1]) try fileDescriptor.writeAll(dataToWrite) // L13 let dataWritten = try Data(contentsOf: url) print(dataToWrite == dataWritten) // false I would expect L13 to result in an error. Given it doesn't: Is there a way to determine where fileDescriptor is writing? Is there a way to ensure that fileDescriptor is writing the content in the expected filePath?
8
0
516
Jun ’24
"Unexpectedly found nil while unwrapping an Optional value" in URL
Before anyone rants and raves about checking documentation - I have spent the last 4 hours trying to solve this issue on my own before asking for help. Coding in Swift is VERY new for me and I'm banging my head against the wall trying to teach myself. I am very humbly asking for help. If you refer me to documentation, that's fine but I need examples or it's going to go right over my head. Teaching myself is hard, please don't make it more difficult. I have ONE swift file with everything in it. import Foundation import Cocoa import Observation class GlobalString: ObservableObject { @Published var apiKey = "" @Published var link = "" } struct ContentView: View { @EnvironmentObject var globalString: GlobalString var body: some View { Form { Section(header: Text("WallTaker for macOS").font(.title)) { TextField( "Link ID:", text: $globalString.link ) .disableAutocorrection(true) TextField( "API Key:", text: $globalString.apiKey ) .disableAutocorrection(true) Button("Take My Wallpaper!") { } } .padding() } .task { await Wallpaper().fetchLink() } } } @main struct WallTaker_for_macOSApp: App { @AppStorage("showMenuBarExtra") private var showMenuBarExtra = true @EnvironmentObject var globalString: GlobalString var body: some Scene { WindowGroup { ContentView() .environmentObject(GlobalString()) } // MenuBarExtra("WallTaker for macOS", systemImage: "WarrenHead.png", isInserted: $showMenuBarExtra) { // Button("Refresh") { //// currentNumber = "1" // } // Button("Love It!") { //// currentNumber = "2" // } // Button("Hate It!") { //// currentNumber = "3" // } // Button("EXPLOSION!") { // // currentNumber = "3" // } //// // } } } class Wallpaper { var url: URL? = nil var lastPostUrl: URL? = nil let mainMonitor: NSScreen init() { mainMonitor = NSScreen.main! } struct LinkResponse: Codable { var post_url: String? var set_by: String? var updated_at: String } struct Link { var postUrl: URL? var setBy: String var updatedAt: Date } func parseIsoDate(timestamp: String) -> Date? { let formatter = DateFormatter() formatter.locale = Locale(identifier: "en_US_POSIX") formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" return formatter.date(from: timestamp) } func fetchLink() async { do { url = URL(string: GlobalString().link) let (data, _) = try await URLSession.shared.data(from: url!) let decoder = JSONDecoder() let linkResponse = try decoder.decode(LinkResponse.self, from: data) let postUrl: URL? = linkResponse.post_url != nil ? URL(string: linkResponse.post_url!) : nil let date = parseIsoDate(timestamp: linkResponse.updated_at) let link = Link( postUrl: postUrl, setBy: linkResponse.set_by ?? "anon", updatedAt: date ?? Date() ) try update(link: link) } catch { } } func update(link: Link) throws { guard let newPostUrl = link.postUrl else { return } if (newPostUrl != lastPostUrl) { lastPostUrl = newPostUrl let tempFilePath = try getTempFilePath() try downloadImageTo(sourceURL: newPostUrl, destinationURL: tempFilePath) try applyWallpaper(url: tempFilePath) } else { } } private func applyWallpaper(url: URL) throws { try NSWorkspace.shared.setDesktopImageURL(url, for: mainMonitor, options: [:]) } private func getTempFilePath() throws -> URL { let directory = NSTemporaryDirectory() let fileName = NSUUID().uuidString let fullURL = NSURL.fileURL(withPathComponents: [directory, fileName])! return fullURL } private func downloadImageTo(sourceURL: URL, destinationURL: URL) throws { let data = try Data(contentsOf: sourceURL) try data.write(to: destinationURL) } } The 'fetchLink' function is where things explode, specifically when setting the URL. I do not know what I'm doing wrong.
5
0
490
Jun ’24
Using AppConfig and Network Extension
We are using Manged App Configurations to dynamically push values to our app. We eventually want these values to reach our Network Extension process (specifically PacketTunnelProvider). However, there's some problems here: MDM providers only allow us to send configurations to app, not the extension. There's not really a way for us to reach the app configuration from the extension (even if the extension and app are in the same app group), because the app config is placed in [NSUserDefaults standardUserDefaults] A workaround would then be for the app to monitor for any AppConfig changes using NSUserDefaultsDidChangeNotification, and then write the app config settings to a shared NSUserDefaults instance. But when the app is in the background (most of the time for network extension apps), those notifications don't fire. I've attempted to use KVO to notify on any changes such as below: [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"com.apple.configuration.managed" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:NULL]; - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { NSLog(@"%@", [change description]); } But I am not seeing any KVO notifications here, even when NSUserDefaultsDidChangeNotification fires. This would be a workaround, but if the app is not running (due to connect-on-demand) or some other reason, this still would not work. Is there any possible workarounds or things that we can do here? Any help would be appreciated. Thanks
1
0
349
May ’24
Are Open OutputStreams Buffered or Unbuffered?
I am working on an app that is streaming data from a bluetooth device to an iPhone. As data constantly arrives to the phone, I am repeatedly decoding data segments and sending it to a file through a OutputStream (from Foundation). Trying to streamline this background work, I want to make sure the data I/O is using a buffered write. Looking over documentation for the OutputStream class, I cannot find any mention of how to flush the buffer if needed, and am unsure if the Stream object is using a buffer across my repeated calls. Are OutputStreams sending binary data to a file buffered or unbuffered? Thank you in advance for clarifying this mechanic! I am using XCode Version 15.3, and Swift 5.10
1
0
206
May ’24
What kind of eviction policy the disk Cache follows and it does not work when it is less than 5 MB
If I set the capacity of the disk cache to less than 5MB, It doesn't work. Through the print statement, I checked that the value of the currentDiskUsage did not rise at all, and I also checked that the image has been making network requests every time because there is no cached data even if I shut down and run the app again. I'm simply wondering why this is happening. Also, I wonder what kind of eviction policy the disk cache follows. I was so curious that I tried to find out through the link [here], but there seems to be no implementation of disk cache at all. Below is the code I used. I'm attaching it together just in case. import UIKit protocol Cacheable { func getCachedResponse( for path: String, completion: @escaping (Result<Data, CacheError>) -> Void ) func save( for path: String, data: Data ) } final class CacheManager { static let shared = CacheManager() private let imageCache: URLCache init() { imageCache = URLCache( memoryCapacity: 4 * 1024 * 1024, // 4MB diskCapacity: 4 * 1024 * 1024 // 4MB ) } } extension CacheManager: Cacheable { func getCachedResponse( for path: String, completion: @escaping (Result<Data, CacheError>) -> Void ) { if let url = URL(string: path), let cachedResponse = imageCache.cachedResponse(for: URLRequest(url: url)) { completion(.success(cachedResponse.data)) return } completion(.failure(.noCachedResponse)) } func save( for path: String, data: Data ) { guard let url = URL(string: path) else { return } let response = URLResponse( url: url, mimeType: nil, expectedContentLength: 0, textEncodingName: nil ) if let uiImage = UIImage(data: data), let compressedData = uiImage.jpegData(compressionQuality: 0.8) { #if DEBUG let formmatter = ByteCountFormatter() formmatter.allowedUnits = [.useMB] formmatter.countStyle = .file print(""" === Original size: \(formmatter.string(fromByteCount: Int64(data.count))) === Cached size: \(formmatter.string(fromByteCount: Int64(compressedData.count))) """) #endif let cachedResponse = CachedURLResponse( response: response, data: compressedData ) imageCache.storeCachedResponse( cachedResponse, for: URLRequest(url: url) ) } } }
1
0
313
May ’24
Background NSURLSession when uploads must be prompt
I have an app with which users take photos and upload them in batches. It's used often on older devices, in areas with less than ideal network, and for durations of a full workday - so often the device has low power. The current implementation of uploads uses an NSURLSession configured for the foreground, and as a result my users are used to having to keep the app in the foreground while an upload completes. However, these uploads are big and connectivity is often low, so this takes a long time - often users are stuck waiting with the app foregrounded for 15 minutes or so while the upload completes. So, I created a build which uses an NSURLSession configured for the background. In the ideal case, users could start the upload, put the device in their pocket and continue their workday, and the next time they open their device it will be complete. For some users this ideal case has come true. However, for others, the uploads sit in progress for an indeterminate amount of time, making no progress. My suspicion is that this is because the OS is deferring them until a time when network and power is more available. However, my users are using work devices at a work location - reliable power and network might never be available. Being able to background the app and continue working is valuable for these users, but having the upload complete promptly is essential for them. My questions are: Is it true that background configured NSURLSessions will defer network requests when connectivity or power is low, even if discretionary = NO? Is the exact behavior for when requests will be attempted in the background documented? Is there a way to reliably test background configured NSURLSessions in XCode? I've attempted throttling my connection with Charles Proxy, and using my device in Low Power Mode, but I'm unable to reproduce the request stalling behavior my users are experiencing in the wild. Is there a way to create an NSURLSession that will muscle through difficult or inefficient uploads in the background, with the same reliability as a foreground session? If not, what is Apple's recommended approach to situations like mine? I've considered queueing both a background and foreground upload, and cancelling the other once one completes, but this seems disrespectful to the user's resources. Will setting timeoutIntervalForResource to a lower value cause the OS to more aggressively attempt uploads? Or simply to throw an error sooner? I want the OS to give the upload a long time to complete, but I also want it to attempt it right away. Thanks for any information!
1
0
318
May ’24
User Data is getting randomly deleted
this is an email I have sent to Apple with no luck: Dear Apple Developer Support Team, I am writing to seek urgent assistance with a persistent issue I have been encountering with Xcode. For several months now, every time I connect my iPhone to Xcode for development purposes, it automatically overwrites the user data of my apps with an old, seemingly random container. This issue is severely impacting my ability to continue development, as I cannot test new changes effectively. This occurs since a few months in every iOS and Xcode/macOS Version. I tried it with different Apps and Devices. Sometimes the entire Container (Documents) gets read only access so no new data can be created or changed by the user. I frequently used the replace container feature on Xcode so maybe this has something to do with it. This problem persists despite numerous attempts to resolve it on my end. I am at a critical point in my development timeline, and it is crucial for me to resolve this as soon as possible. Could you please advise on the next steps I should take to address this issue? If there are any logs or further information you require, I am more than willing to provide them. Thank you for your attention to this matter. I look forward to your prompt response and hope for a resolution soon. Best regards, Victor Lobe
7
0
610
Jun ’24
Central American NSTimeZone instances returning CST rather than permanently CDT
I had some support tickets about dates not showing properly for customers based in the America/Merida timezone. Essentially America/Merida permanently changed to -0500 (CDT) on October 31, 2021, and it appears that the NSTimeZone does not respect this change, and reports times as -0600 (CST). Creating a little test tool with the following code: +(void) run { NSArray<NSString *> * args = [[NSProcessInfo processInfo] arguments]; if ([args count] > 1) { NSString *timezone = args[1]; NSLog(@"custom TZ: %@", timezone); NSTimeZone * tz = [NSTimeZone timeZoneWithName:timezone]; [NSTimeZone setDefaultTimeZone:tz]; } NSDate * now = [NSDate date]; NSLog(@"Testing Dates: (local timezone : %@)", [NSTimeZone localTimeZone]); NSLog(@" (default timezone: %@)", [NSTimeZone defaultTimeZone]); NSLog(@" (is DST : %@)", [[NSTimeZone defaultTimeZone] isDaylightSavingTimeForDate:now] ? @"YES" : @"NO"); NSLog(@" (current cal-tz : %@)", [[NSCalendar currentCalendar] timeZone]); NSLog(@" (current locale : %@)", [[NSLocale currentLocale] localeIdentifier]); NSLog(@"Now: %@", now); } And running with the America/Merida timezone passed in, I'm getting the following output: custom TZ: America/Merida Testing Dates: (local timezone : Local Time Zone (America/New_York (EDT) offset -14400 (Daylight))) (default timezone: America/Merida (CST) offset -21600) (is DST : NO) (current cal-tz : America/Merida (CST) offset -21600) (current locale : en_US) Now: Tue May 14 15:06:14 2024 Running the same code on Linux via the GNUStep implementation of Objective-C, I get the correct output with America/Merida showing up as CDT (ie (is DST : YES)). Are there any good ways to work around this?
3
0
390
May ’24
How to calculate CAMetalDisplayLink Update timestamp
Hello, I am using CAMetalDisplayLink to render my metal layer and i am trying to calculate timestamp for next render to compare with current timestamp. I did notice that timestamp from display link Update is not like Date timestamp. Looks like it depends on some kind of phone boot or another kernel process start. I did try func bootTime() -> TimeInterval? { var tv = timeval() var tvSize = MemoryLayout<timeval>.size let err = sysctlbyname("kern.boottime", &tv, &tvSize, nil, 0); guard err == 0, tvSize == MemoryLayout<timeval>.size else { return nil } return Double(tv.tv_sec) + Double(tv.tv_usec) / 1_000_000.0 } And i got calc 1715680889.6883893 real 1715680878.01257 It's close but still 10 seconds different so probably it's not kern.boottime but something similar. Anybody knows what should i use to get correct timestamp?
1
0
257
May ’24
How does SwiftData and Decimal Works?
Hi! Not sure if this is a swift data or more a Decimal in general type of question. What's going on: I have a SwiftUI app using SwiftData, I have persisted a Model with a property "reducedPrice" of type Decimal. It's stores correctly the value. Now, I have read the value during automated tests and tried comparing the values: let reducedPrice = model.reducedPrice // swift data property let target = Decimal(4.98) // expected target value to compare to swift data value. Now if I just print the result of the comparison between those 2 I get a false result. print(reducedPrice == target) //output : false The swift data model was populated from a direct copy of another struct that comes from an JSON import using Codable+CodingKeys (I used Decimal type). What I expected: I expected it to be true. Debug Observations I did noticed that on the variable inspector both had the same magnitudes but in reality the mantissa are different. I'm attaching a screenshot. My Theory They are different just because something under SwiftData stores different way the decimal as in comparison on how I am creating the Decimal for the comparison inside the automated tests. My question Is this expected behavior? Any suggestion on best practices on how to handle this? Thank you in advance any relevant guidance is very appreciated!
2
1
290
May ’24
NSKeyedArchiver + NSKeyedUnarchiver deprecated
My Objective-C app contains several hundreds lines of deprecated code like these: NSData *tmp = [NSKeyedArchiver archivedDataWithRootObject:singleTaskCleanUserArrayItem]; singleTaskUserArrayItem = [NSKeyedUnarchiver unarchiveObjectWithData:tmp]; New recommended methods: +archivedDataWithRootObject:requiringSecureCoding:error: +unarchivedObjectOfClass:fromData:error: How to implement the new methods in Objective-C? Forums and Documentation refer to Swift but not to Objective-C. Please give me a sample code for the two lines of code Best regards, Gerhard
1
0
283
May ’24
Decoding dynamic json
Hey there, I'm trying to decode an json with an dynamic dict as value. eg. "results": [ { "id": 1799, "created_at": "2024-05-09T14:21:13.289655Z", "updated_at": "2024-05-10T11:54:25.484537Z", "email": "test@test.testh", "name": "Test", "attributes": { "name": { "firstname": "max", "lastname": "mustermann" }, "anboolen": false, "anNumber": 1, "anString": "Test" } } ] The dictionary "attributes" is always an dictionary but the content inside could be everything. for the container of results I already created an struct and using JSONDecoder to decode, but now I have the issue with the attributes part. Can anyone help me with this issue? Thanks in advance!
2
0
252
May ’24
NSTask not running properly when compiled
HI i have coded an App for Mac OSX that has embedded a Command line tool, the problem is that everything works fine while i am running from the xcode compiler, after build the final product, the app is not working properly and i can see messages like this in the console. Task .<251932> not allowed to create a new connection (existing Connection 224) Task <37752B7F-5827-4160-83C4-773B17AE72DF>.<255990> resuming, timeouts(60.0, 604800.0) QOS(0x21) Voucher (null) i was reading a link posted here but the solution is not working, some ideas are appreciated. My guess is that maybe is something related with a security setting. This is the code: NSTask *task; NSString *executableName = @"websocat"; NSString *executablePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:executableName]; task = [[NSTask alloc] init]; [task setLaunchPath:executablePath]; Quinn “The Eskimo!" please help!
2
0
247
May ’24
Trouble parsing JSON data, codable structs
Im making an API call using notions API to access and retrieve data from my Notion page and I'm successfully making the url request and accessing the page, however I seem to be struggling with returning the actual data that I have in that page and parsing the JSON data as right now, my console only outputs the makeup of my notion page rather than the formatted and parsed data. I made a codable struct meant to replicate the structure of a notion page based off their documentation then I'm passing that struct to my JSON parsing function but my data still is not being parsed and returned. heres what I have. import Foundation struct Page: Codable, Hashable { //Codable struct for notion "Page" for defining content aswell as object representation in a codable struct of all the basic components that make up a notion page per notion's documentation let created_time: String let created_by: String let last_edited_time: String let object: String let cover: String let emoji: String let icon: String struct properties: Codable, Hashable { let title: String let dueDate: String let status: String } struct dueDate: Codable, Hashable { let id: String let type: String let date: String let start: String let end: String? //optionals added to "end" and "time_zone" as these values are set to null in the documentation let time_zone: String? } struct Title: Codable,Hashable { let id: String let type: String let title: [String] } struct annotations: Codable, Hashable { let bold: Bool let italic: Bool let strikethrough: Bool let underline: Bool let code: Bool let color: String } let English: String let Korean: String let Pronounciation: String let in_trash: Bool let public_url: String? let annotations: Bool } let url = URL(string: "https://api.notion.com/v1/pages/8efc0ca3d9cc44fbb1f34383b794b817") let apiKey = "secret_Olc3LXnpDW6gI8o0Eu11lQr2krU4b870ryjFPJGCZs4" let session = URLSession.shared func makeRequest() { if let url = url { var request = URLRequest(url: url) let header = "Bearer " + apiKey //authorization header declaration request.addValue(header, forHTTPHeaderField: "authorization") //append apikey request.addValue("2022-06-28",forHTTPHeaderField: "Notion-Version") //specify version per notions requirments let task = URLSession.shared.dataTask(with: request) { data, response, error in if let httpError = error { print("could not establish HTTP connection:\(httpError)") } else { if let httpResponse = response as? HTTPURLResponse { if httpResponse.statusCode == 200 { } else { print("invalid api key:\(httpResponse.statusCode)") } } } if let unwrapData = data { //safely unwrapping the data value using if let if let makeString = String(data: unwrapData, encoding: .utf8) { print(makeString) } else { print("no data is being returned:") } do { let decoder = JSONDecoder() //JSONDecoder method to decode api data, let codeUnwrappedData = try decoder.decode(Page.self,from: unwrapData) //Page. specifies its a struct, from: passes the data parmeter that contains the api data to be decoded //PASS STRUCTURESDATABASE STRUCT print("data:\(codeUnwrappedData)") } catch { print("could not parse json data") } if let httpResponse = response as? HTTPURLResponse { if httpResponse.statusCode == 200 { print(String(data: unwrapData, encoding: .utf8)!) } else { print("unsuccessful http response:\(httpResponse)") } } } } task.resume() } }
3
0
324
May ’24
Crashes on the Toll-Free Bridge
Over the years I’ve helped a lot of folks investigate a lot of crashes. In some cases those crashes only make sense if you know a little about how Foundation and Core Foundation types are toll-free bridged. This post is my attempt to explain that. If you have questions or comments, please put them in a new thread. Tag it with Foundation and Debugging so that I see it. Share and Enjoy — Quinn “The Eskimo!” @ Devel oper Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Crashes on the Toll-Free Bridge Certain Core Foundation (CF) types are toll-free bridged to their Foundation equivalent. That allows you to pass the Foundation object to a CF routine and vice versa [1]. For example, NSData and CFData are toll-free bridged, allowing you to pass an NSData object to a CF routine like CFDataGetBytePtr. For more information on this topic, see Toll-Free Bridged Types within Core Foundation Design Concepts in the Documentation Archive. This is cool, but it does present some interesting challenges. One of these relates to subclassing. Many of the toll-free bridge Foundation types support subclassing and, if you create a instance of your subclass and pass it to CF, CF has to do the right thing. Continuing the NSData example above, it’s legal [2] to create your own subclass of NSData with a completely custom implementation. As long as you implement the -bytes method and the length property, all the other NSData methods will just work. Moreover, this class works with CFData routines as well. If you pass an instance of your subclass to CFDataGetBytePtr, CF detects that it’s an Objective-C object and calls your -bytes method. Exciting! So, how does this actually work? It relies on the fact that CF and Objective-C types share a common object header. That object header is an implementation detail, but the first word of the header is always an indication of the class [3]. CF uses this word to distinguish between CF and Objective-C objects. Note This basic technique is used by other Objective-C compatible types, including Swift objects and XPC objects. If, for example, you call CFRetain on Swift object, it detects that this is an Objective-C compatible object and calls objc_retain, which in turns detects that this is a Swift object and calls swift_retain. To see this in action, check out the Swift Foundation open source. Continuing our NSData example, the first line of CFDataGetBytePtr uses the CF_OBJC_FUNCDISPATCHV macro to check if this is an Objective-C object and, if so, call -bytes on it. Sadly, the open source trail goes cold here, because Objective-C integration is only supported on Apple platforms. However, some disassembly reveals the presence of an internal routine called CF_IS_OBJC. (lldb) disas -n CFDataGetBytePtr CoreFoundation`CFDataGetBytePtr: … <+0>: pacibsp … <+4>: stp x20, x19, [sp, #-0x20]! … <+8>: stp x29, x30, [sp, #0x10] … <+12>: add x29, sp, #0x10 … <+16>: mov x19, x0 … <+20>: mov w0, #0x14 … <+24>: mov x1, x19 … <+28>: bl 0x19cc60100 ; CF_IS_OBJC … WARNING Do not rely on the presence or behaviour of CF_IS_OBJC. This is an implementation detail. It has changed many times in the past and may well change in the future [4]. While this is an implementation detail, it’s useful to know about when debugging. If you pass something that’s not a valid object to CFDataGetBytePtr, you might see it crash in CF_IS_OBJC. For example, this code: void test(void) { struct { int i; } s = { 0 }; CFDataGetBytePtr( (const struct __CFData *) &s ); } crashes like this: Exception Type: EXC_BREAKPOINT (SIGTRAP) … Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 CoreFoundation … CF_IS_OBJC + 76 1 CoreFoundation … CFDataGetBytePtr + 32 2 xxot … test + 24 … … In this case CF_IS_OBJC has detected the problem and trapped, resulting in an EXC_BREAKPOINT crash. However, if you pass it a pointer that looks more like an object, this might crash trying to dereference a bad pointer, which will result in a EXC_BAD_ACCESS crash. The other common failure you see occurs when you pass it an Objective-C object of the wrong type. Consider code like this: void test(void) { id str = [NSString stringWithFormat:@"Hello Cruel World!-%d", (int) getpid()]; const void * ptr = CFDataGetBytePtr( (__bridge CFDataRef) str); … } When you run this code, it throws a language exception like this: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString bytes]: unrecognized selector sent to instance 0x6000028545a0' *** First throw call stack: ( 0 CoreFoundation … __exceptionPreprocess + 176 1 libobjc.A.dylib … objc_exception_throw + 60 2 CoreFoundation … -[NSObject(NSObject) __retain_OA] + 0 3 CoreFoundation … ___forwarding___ + 1580 4 CoreFoundation … _CF_forwarding_prep_0 + 96 5 xxot … test + 92 … ) CFDataGetBytePtr has detected this is an Objective-C object and called -bytes on it. However, this is actually an NSString [5] and NSString doesn’t implement the -bytes method. The end result is an unrecognized selector exception. [1] To be clear, when using CF objects in Objective-C you first cast the CF object to its Foundation equivalent and then call Objective-C methods on it. [2] While it’s legal to do this, it’s probably not very sensible. Subclassing Foundation types is something that might’ve made sense back in the day, but these days there are generally better ways to solve your problems. [3] Historically this word was called isa and was of type Class, that is, a pointer to the actual Objective-C class. These days things are much more complex (-: [4] Historically, CF_IS_OBJC was very simple: If the object’s isa word was 0, it was a CF object, otherwise it was an Objective-C object. That’s no longer the case. [5] The actual type is __NSCFString. That’s because NSString is a class cluster. For more about that, see Class Clusters within Cocoa Fundamentals Guide in the Documentation Archive.
0
0
205
May ’24