Objective-C

RSS for tag

Objective-C is a programming language for writing iOS, iPad OS, and macOS apps.

Posts under Objective-C tag

115 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

locale in Objective-C++ is confusing
hi all, i wrote my tool app using ObjC++, find some problems while messing with "locale". here's the problems: I invoke a C++ function, std::string ws2s(const std::wstring& ws) { if (ws.empty()) return ""; NSLog(@"%s %s", setlocale(LC_ALL, NULL), std::locale().name().c_str()); ... output is "C C", and i try to set locale to "zh_CN.UTF8", but it's still "C". another is an Objc Class Method + (NSString*)getNSStrFromWCharStr:(const wchar_t*)wcstr { if (wcstr == NULL) return nil; char *curLocale = setlocale(LC_ALL, NULL); ... this time, curLocale is the same as system default ——"zh_CN.UTF8" I try to set locale in main function, first one succeed, second made process crash. setlocale(LC_ALL, "zh_CN.UTF-8"); std::locale::global(std::locale("zh_CN.UTF8")); crash info:libc++abi: terminating due to uncaught exception of type std::runtime_error: collate_byname::collate_byname failed to construct for zh_CN.UTF8 after all this, it's OK to handle CN character with C and objc, but it's not OK with C++. and I'm confused, I don't know much about 'locale'. I thought it was a per-process setting, now it seems to be a per-language setting... OS version: macOS 14.4, system default locale is "zh_CN.UTF8".
1
0
489
Aug ’24
Deadlock in UIKit while injecting test bundle
Platform and Version iOS Development environment: Xcode 16.0 beta 5 (16A5221g), macOS 14.6.1 (23G93) Run-time configuration: iOS 18.0 beta 5 (22A5326g) Description of Problem Starting with iOS 18 SDK, test bundles containing a +load method that accesses UIScreen.mainScreen result in deadlock during test bundle injection. Also filed as FB14703057 I'm looking for clarity on whether this behavior is considered a bug in iOS or whether we will need to change the implementation of our app. Steps to Reproduce Create a new iOS app project using Objective-C and including unit tests Add the following code snippet to any .m file in the test target: @interface Foo: NSObject @end @implementation Foo + (void)load { UIScreen * const mainScreen = UIScreen.mainScreen; NSLog(@"%@", mainScreen); } @end Run the tests Expected Behavior As with iOS 17 & Xcode 15, the tests run to completion. Actual Behavior With iOS 18 & Xcode 16, deadlock during test bundle injection. stack_trace.txt
2
0
840
Sep ’24
Merge results from NSURLSession back on to the main thread UI
I have apps that send requests for route between 2 locations and search, filter then display facilities near the route. The apps first send a request for the route on a background thread, then based on route, search for facilities near certain locations on or near the route. There maybe multiple searches on the same route, each on a different location. Suitable results then are displayed on the map. Apps also do live updates. However, since I have switched to using NSURLSession to search for the route on a background thread, not all suitable results/pin are displayed. Certain pins only show up upon the next didUpdateToLocation call. So my question is, what is the best practice to sync the results on the UI? Why do only some of the results show up on the UI, and others don't.
1
0
440
Aug ’24
Objective-C++ confuses two private classes with the same name
I think I found a bug in the Objective-C++ compiler, linker, or runtime. Here’s the scenario: We have a macOS app written in Swift. To control hardware from a 3rd party manufacturer, we use a couple SDKs provided by the manufacturer. The SDKs use dynamically loaded libraries and the interface is defined in C++ headers. To bridge between our Swift code and the C++ APIs we have a private Cocoapod that wraps the 3rd party interface with Objective-C++ classes. The two SDKs each provide an interface for discovering attached devices using a callback class that the programmer provides. By accident we named both callback implementations DiscoveryCallback, but this was not a compiler error because neither class was publicly declared, and each was defined in the .mm file where it was used. However, the problem we’re seeing is this: We want to discover Videohub devices, so we register a new instance of DiscoveryCallback (defined in the same .mm file as this code) with the Videohub SDK. A Videohub device is connected and the SDK calls a method on our callback. Surprise! The callback we registered in step 1 was actually the one intended for Decklink devices, defined in a completely different .mm file. This violates all sorts of assumptions and our app quickly crashes. The funny thing is, the two implementations of DiscoveryCallback have completely different method names. The Videohub SDK is supposed to be calling NewVideohubDevice, yet somehow it successfully calls DeckLinkDeviceArrived on an instance of a class it shouldn’t even know about. So the compiler has checked that our intended DiscoveryCallback matches the protocol that the SDK expects, but at runtime the compiled code instantiates a completely different implementation of DiscoveryCallback and somehow doesn’t immediately fail; we still call a method on it that doesn’t even share a name with the intended target. I imagine at this point the method names are long forgotten and are just pointers in a table. I don’t know if this is a bug in the compiler, the Objective-C++ runtime, or if this is just “working as designed” undefined behavior that I should have avoided by not giving two private classes the same name. I know it’s possible to use a private API simply by redeclaring it in my own code, and this seems related to that, but I feel like the compiler or linker should have warned me that I had two implementations of the same class, or if that is not an error, then the runtime should have instantiated the class that was privately defined in the same source file where it was used. Obviously I can’t share our entire project; I’d like to provide some sample code that replicates the issue, but I don’t have time to do that right now. I’m posting this to see if other developers have had a similar experience.
2
1
976
Jul ’24
Issue with 24-hour time format in UIDatePicker and possible workarounds
Dear Apple Support Team, I am currently developing a control in my app that uses UIDatePicker for time input. To ensure that the time display format is consistently in 24-hour notation regardless of the region, I have set the locale of UIDatePicker to ‘systemLocale’. However, while this worked as expected up to iPadOS15, displaying the time in 24-hour format, it has switched to a 12-hour format from iPadOS16 onwards. I am wondering if there have been any changes in the behavior of UIDatePicker’s locale between the updates from iPadOS15 to iPadOS16? Additionally, I would like to know if there are any workarounds to this issue that do not involve modifying the program. In other words, is there a way to revert back to the 24-hour format without changing the code? Any information you could provide on this issue would be greatly appreciated. Thank you for your assistance.
2
0
974
Aug ’24
About "SIMInserted" API
I am using the SIMInserted API on Xcode 16 beta. However, when I checked with a SIM card inserted, it returned "No". [Enviroment] Xcode:16beta iOS:18beta1,18beta2 [The modified implementation area is as follows] 1.Add "CarrierDescriptors" to the plist. <key>CarrierDescriptors</key> <array> <dict> <key>MCC</key> <string>440</string> <key>MNC</key> <string>10</string> </dict> </array> 2.Add "SIM Inserted for Wireless Carriers" to the capabilities. <key>com.apple.developer.coretelephony.sim-inserted</key> <true/> 3.In case of iOS 18 and above, perform SIM detection using "isSIMInserted" of CTSubscriber. - (BOOL)isSIMInseted { if(@available(iOS 18.0,*)){ CTSubscriber* ctSubscriber = [CTSubscriber new]; return = ctSubscriber.isSIMInserted; } return NO; } Is there any mistake in the implementation steps you provided? Why is it not possible to retrieve the desired information with this implementation? Please assistant me.
6
2
1.7k
Jul ’24
Can't establish mTLS on iOS with WKWebView and ProxyConfiguration
I have a sample iOS app in Xcode that I run in the iOS 17.5 Simulator. It creates a WKWebView and configures a proxy via the ProxyConfiguration API, it works as expected unless the proxy tries to establish mTLS. It seems there is no way to handle the client certificate request when using a proxy. If I navigate to a page that requests mTLS without a proxy configured, it works as expected. Here is a minimal repro: #import "ViewController.h" #import &lt;WebKit/WebKit.h&gt; @import Foundation; @import WebKit; @interface ViewController () &lt;WKNavigationDelegate&gt; @property (nonatomic,strong) WKWebView* webView; @property (nonatomic, strong) WKWebViewConfiguration * webConfig; @end @implementation ViewController - (void)loadView { [super loadView]; nw_protocol_options_t tls_options = nw_tls_create_options(); sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options); sec_protocol_options_set_challenge_block( sec_options, ^(sec_protocol_metadata_t metadata, sec_protocol_challenge_complete_t challenge_complete) { NSLog(@"Inside of challenge block"); challenge_complete(nil); }, dispatch_get_main_queue()); nw_endpoint_t proxy_endpoint = nw_endpoint_create_host(GetHost(), GetPort()); nw_relay_hop_t relay = nw_relay_hop_create(nil, proxy_endpoint, tls_options); nw_proxy_config_t proxy_config = nw_proxy_config_create_relay(relay, nil); nw_proxy_config_add_match_domain(proxy_config, "api.ipify.org"); self.webConfig = [[WKWebViewConfiguration alloc] init]; self.webConfig.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore]; self.webConfig.websiteDataStore.proxyConfigurations = @[ proxy_config ]; self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:self.webConfig]; self.webView.navigationDelegate = self; [self.view addSubview:self.webView]; } - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"%s",__func__); NSURL* url = [[NSURL alloc] initWithString:@"https://api.ipify.org"]; NSURLRequest* request = [[NSURLRequest alloc] initWithURL:url]; [self.webView loadRequest:request]; } - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { NSLog(@"%s",__func__); } - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error { NSLog(@"%s. Error %@",__func__,error); } - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler { NSLog(@"%s",__func__); NSLog(@"protection space: %@", challenge.protectionSpace.authenticationMethod); completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); } @end The logs for this code show: -[ViewController viewDidLoad] -[ViewController webView:didStartProvisionalNavigation:] -[ViewController webView:didFailProvisionalNavigation:withError:]. Error Error Domain=NSURLErrorDomain Code=-1206 "The server “api.ipify.org” requires a client certificate." If we don't set up the ProxyConfiguration and navigate to a site that requires mTLS, the logs look like this: -[ViewController viewDidLoad] -[ViewController webView:didReceiveAuthenticationChallenge:completionHandler:] protection space: NSURLAuthenticationMethodServerTrust -[ViewController webView:didReceiveAuthenticationChallenge:completionHandler:] protection space: NSURLAuthenticationMethodClientCertificate -[ViewController webView:didStartProvisionalNavigation:] //... Eventually the request fails but the key difference is that didReceiveAuthenticationChallenge was invoked. When using the ProxyConfiguration neither that function nor the block we set via sec_protocol_options_set_challenge_block were run. I also tried to provide the client identity via sec_protocol_options_set_local_identity to no avail, and I've tried configuring these options too but they had no effect sec_protocol_options_add_tls_application_protocol(sec_options, "h2"); sec_protocol_options_set_max_tls_protocol_version(sec_options, tls_protocol_version_TLSv13); sec_protocol_options_set_peer_authentication_required(sec_options, true); Am I missing something? Or is this a bug in the ProxyConfiguration API?
15
2
2k
Sep ’24
Unable to import ObjC interface from a package in a public ObjC file in a framework
Problem Statement: Unable to import .h file from an ObjC SPM to a .h file in an ObjC file in a framework with mix of ObjC and Swift code The issue is: in order to support access of ObjC file in Swift code in a framework we need to use umbrella header (in place of bridging header). Once the file is imported in Umbrella header and made public it will no longer allow import of .h file from package in its interface Project Structure: a. Package: ObjCPackage ObjCPackage |- Package.swift |- ObjCPackage MathsUtilities.h (class interface) MathsUtilities.m (class implementation) NiceLogs.h (protocol) b. Project: ObjCSwiftFramework ObjCSwiftFramework |- ObjCSwiftFramework.h (umbrella header) |- Calculation.h (objc class interface) |- Calculation.m (objc class implementation) |- SwiftCalci.swift (swift class) Details: #import <ObjCSwiftFramework/Calculation.h> added in ObjCSwiftFramework.h as Calculation has to be used in SwiftCalci Calculation.h marked as public in target membership in Xcode so that it can be added in umbrella header ObjCSwiftFramework.h #import "NiceLogs.h" in Calculation.h gives error Here is a small sample which I created to demonstrate the problem: ObjCSwiftFramework
1
0
653
Jul ’24
Mac app crashing in CF_IS_OBJC function on macOS Sonoma
I have an Electron app on macOS Sonoma (Intel arch). It has a native addon (app.node) using node-addon-api. Recently it crashed, with the stack trace (given below). What is the CF_IS_OBJC function inside the CFDataGetBytePtr function, and why did it crash there? [NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskKeyDown handler:^(NSEvent *event) { // code using CFDataGetBytePtr function }]; [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown handler:^NSEvent *_Nullable(NSEvent *event) { // code using CFDataGetBytePtr function return event; }]; I have key events monitors attached using addGlobalMonitorForEventsMatchingMask and addLocalMonitorForEventsMatchingMask in my native code and they use the CFDataGetBytePtr function there. So I think the issue happened in the key event monitor handler when calling the CFDataGetBytePtr function because my native addon app.node is also present in the trace. Also from the third and fourth entry in the stack trace, it seems like it happened while the app was updating. OS Version: macOS 14.4 (23E214) Report Version: 104 Crashed Thread: 5490 Application Specific Information: Fatal Error: EXC_BAD_ACCESS / KERN_INVALID_ADDRESS / 0x0 Thread 5490 Crashed: 0 CoreFoundation 0x19c970118 CF_IS_OBJC 1 CoreFoundation 0x19c83b280 CFDataGetBytePtr 2 .app.desktop.1inmRz 0x104a5bec0 &lt;unknown&gt; 3 .app.desktop.1inmRz 0x104a57b28 &lt;unknown&gt; 4 app.node 0x104a80a7c [inlined] Napi::details::CallbackData&lt;T&gt;::Wrapper::lambda::operator() (napi-inl.h:117) 5 app.node 0x104a80a7c Napi::details::WrapCallback&lt;T&gt; (napi-inl.h:79) 6 app.node 0x104a80a24 Napi::details::CallbackData&lt;T&gt;::Wrapper (napi-inl.h:112) 7 Electron Framework 0x11472e5e0 v8impl::(anonymous namespace)::FunctionCallbackWrapper::Invoke (js_native_api_v8.cc:441) 8 &lt;unknown&gt; 0x147e105f8 &lt;unknown&gt; 9 &lt;unknown&gt; 0x1401d0814 &lt;unknown&gt; 10 &lt;unknown&gt; 0x1401d0a9c &lt;unknown&gt; 11 &lt;unknown&gt; 0x147f19368 &lt;unknown&gt; 12 &lt;unknown&gt; 0x147e0aab0 &lt;unknown&gt; 13 &lt;unknown&gt; 0x1401d0e00 &lt;unknown&gt; 14 &lt;unknown&gt; 0x1401d1ac0 &lt;unknown&gt; 15 &lt;unknown&gt; 0x147f19368 &lt;unknown&gt; 16 &lt;unknown&gt; 0x147e0aab0 &lt;unknown&gt; 17 &lt;unknown&gt; 0x1401d1494 &lt;unknown&gt; 18 &lt;unknown&gt; 0x1401d20dc &lt;unknown&gt; 19 &lt;unknown&gt; 0x147e4c1b4 &lt;unknown&gt; 20 &lt;unknown&gt; 0x147f1b5f8 &lt;unknown&gt; 21 &lt;unknown&gt; 0x147e3b754 &lt;unknown&gt; 22 &lt;unknown&gt; 0x147e0b618 &lt;unknown&gt; 23 Electron Framework 0x10ee0c49c v8::internal::(anonymous namespace)::Invoke (simulator.h:178) 24 Electron Framework 0x10ee0d08c v8::internal::(anonymous namespace)::InvokeWithTryCatch (execution.cc:475) 25 Electron Framework 0x10ee0d1e0 v8::internal::Execution::TryRunMicrotasks (execution.cc:576) 26 Electron Framework 0x10ee37364 v8::internal::MicrotaskQueue::PerformCheckpoint (microtask-queue.cc:176) 27 Electron Framework 0x1146cce9c node::InternalCallbackScope::Close (callback.cc:137) 28 Electron Framework 0x1146ccb64 node::InternalCallbackScope::~InternalCallbackScope (callback.cc:92) 29 Electron Framework 0x1147112b4 node::Environment::RunTimers (env.cc:1376) 30 Electron Framework 0x10daf9980 uv__run_timers (timer.c:178) 31 Electron Framework 0x10dafcb3c uv_run (core.c:465) 32 Electron Framework 0x10dc944d4 electron::NodeBindings::UvRunOnce (node_bindings.cc:891) 33 Electron Framework 0x110e2016c base::TaskAnnotator::RunTaskImpl (callback.h:156) 34 Electron Framework 0x110e3cea4 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork (task_annotator.h:89) 35 Electron Framework 0x110e8851c base::MessagePumpCFRunLoopBase::RunWorkSource (message_pump_apple.mm:444) 36 Electron Framework 0x10da7ad7c base::apple::CallWithEHFrame 37 Electron Framework 0x110e876a4 base::MessagePumpCFRunLoopBase::RunWorkSource (message_pump_apple.mm:415) 38 CoreFoundation 0x19c89deac __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ 39 CoreFoundation 0x19c89de40 __CFRunLoopDoSource0 40 CoreFoundation 0x19c89dbb0 __CFRunLoopDoSources0 41 CoreFoundation 0x19c89c79c __CFRunLoopRun 42 CoreFoundation 0x19c89be08 CFRunLoopRunSpecific 43 HIToolbox 0x1a7036ffc RunCurrentEventLoopInMode 44 HIToolbox 0x1a7036e38 ReceiveNextEventCommon 45 HIToolbox 0x1a7036b90 _BlockUntilNextEventMatchingListInModeWithFilter 46 AppKit 0x1a00f496c _DPSNextEvent 47 AppKit 0x1a08e6de8 -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] 48 AppKit 0x1a00e7cb4 -[NSApplication run] 49 Electron Framework 0x110e89244 base::MessagePumpNSApplication::DoRun (message_pump_apple.mm:805) 50 Electron Framework 0x110e87068 base::MessagePumpCFRunLoopBase::Run (message_pump_apple.mm:156) 51 Electron Framework 0x110e3d9a0 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run (thread_controller_with_message_pump_impl.cc:646) 52 Electron Framework 0x110e05a98 base::RunLoop::Run (run_loop.cc:134) 53 Electron Framework 0x10ffcbcd0 content::BrowserMainLoop::RunMainMessageLoop (browser_main_loop.cc:1094) 54 Electron Framework 0x10ffcd744 content::BrowserMainRunnerImpl::Run (browser_main_runner_impl.cc:158) 55 Electron Framework 0x10ffc964c content::BrowserMain (browser_main.cc:34) 56 Electron Framework 0x10de12aa8 content::RunBrowserProcessMain (content_main_runner_impl.cc:712) 57 Electron Framework 0x10de13b1c content::ContentMainRunnerImpl::RunBrowser (content_main_runner_impl.cc:1299) ...
9
1
1.7k
Sep ’24
Called endBackgroundTask but not working
When my app enter to background, I start a background task, and when Expiration happens, I end my background task. The code likes below: backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ dispatch_async(dispatch_get_main_queue(), ^{ if (backgroundTask != UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:backgroundTask]; backgroundTask = UIBackgroundTaskInvalid; [self cancel]; } }); }]; When the breakpoint is triggered at the endBackgroundTask line, I also get the following log: [BackgroundTask] Background task still not ended after expiration handlers were called: <UIBackgroundTaskInfo: 0x282d7ab40>: taskID = 36, taskName = Called by MyApp, from MyMethod, creationTime = 892832 (elapsed = 26). This app will likely be terminated by the system. Call UIApplication.endBackgroundTask(:) to avoid this. The log don't appear every time, so why is that? Is there something wrong with my code?
3
0
2.7k
4w
dispatch_async_f does not return immediatly
Hi, I work on a game for iOS and the framerate decreases progressively when the debugger is attached. Running it for 2mins, it went from 30 to 1 FPS while rendering a simple static scene. I narrowed it down to a call to dispatch_async_f which takes longer to execute over time. clock_t t1 = clock(); dispatch_async_f(queue, context, function); clock_t t2 = clock(); double duration = (double)(t2 -t1)/(double)CLOCKS_PER_SEC; Dodumentation says dispatch_async_f is supposed to return immediatly. So what could explain duration to increases in debug? Am i measuring this incorrectly? The game is written in mixed C++ and ObjC. It uses Metal as graphic API and GCD for dispatching jobs. I have Xcode 13.4.1 and test on an iPhone 13 Pro with iOS 15.7. Thanks.
10
0
2.6k
Sep ’24
FxPlug open file dialog using a push button
I am trying to develop a plug in for motion in Objective-c using the FxPlug template and so far I have been having issues with getting "NSOpenPanel" to be called from a push button in order to get a file dialog window, similar to the "File" generator present in Motion. [paramAPI addPushButtonWithName: @"MIDI file" parameterID: 1 selector: @selector(MIDI_func) parameterFlags: kFxParameterFlag_DEFAULT] I have tried to call NSOpenPanel through "dispatch_async" so that it would run on the main thread and thus not crash but when I press the button it appears not to work - (void)MIDI_func {     NSLog(@"Button pressed");     dispatch_async(dispatch_get_main_queue(), ^{         NSOpenPanel* openDlg = [NSOpenPanel openPanel];         [openDlg setCanChooseFiles:YES];         [openDlg setAllowsMultipleSelection:NO];         [openDlg setCanChooseDirectories:NO];         if ([openDlg runModal] == NSModalResponseOK) {             NSArray* urls = [openDlg URLs];             for(NSInteger i = 0; i < [urls count]; i++ ) {                 NSString* url = [urls objectAtIndex:i];                 NSLog(@"Url: %@", url);             }         }     }); } How can I achieve this or is there a function in the FxPlug SDK that will let me open a file dialog from the host application?
3
1
1.9k
Sep ’24