AXObserverAddNotification fails in Big Sur OSX 11.5 - macos-big-sur

After replacing Big Sur MacOS 11.0 with the latest 11.5 update, my app's AXObserverAddNotification method fails despite providing both observer and element. Below is the ObjC code I use:
if (AXObserverCreate(pid, menuOpened, &observer) == kAXErrorSuccess) {
CFRunLoopAddSource(CFRunLoopGetCurrent(),
AXObserverGetRunLoopSource(observer),
kCFRunLoopDefaultMode);
AXUIElementRef element = AXUIElementCreateApplication(pid);
NSLog(#"observer: %# element: %#", observer, observer);
if(AXObserverAddNotification(observer, element, kAXMenuOpenedNotification, (__bridge void *)(self)) != kAXErrorSuccess) {
NSLog(#"Failed to create observer for application \"%#\". pid: %i", self.activeApp, pid);
}
}
Here is the log window output showing that the AXObserverAddNotification method "Failed to create observer" for a newly the newly launched app--in this case, "System Preferences":
2021-08-11 10:59:52.682012-0700 SpellSentry[98563:3551301] observer: <AXObserver 0x6000032d21c0> {pid=98580} element: <AXObserver 0x6000032d21c0> {pid=98580}
2021-08-11 10:59:52.695445-0700 SpellSentry[98563:3551301] Failed to create observer for application "System Preferences". pid: 98580
I never experienced this bug in MacOS 11.0 and suspect that the newer OS contains added security measures that are interfering with the proper functioning of the Carbon layer (the "Accessibility" programming layer). Perhaps others are having the same problem with OSX 11.5? Or is it me?

Related

XCTest UI Test System PhotoAuth Alert error。[__NSArrayM insertObject:atIndex:]: object cannot be nil (NSInvalidArgumentException)

// tap photo auth entrance
XCUIElement *collectionView = app.collectionViews.firstMatch;
XCUIElement *authCell = [collectionView.cells elementBoundByIndex:2];
[authCell tap];
// springboard click allow
XCUIApplication *springboard = [[XCUIApplication alloc] initWithBundleIdentifier:#"com.apple.springboard"];
XCUIElement *button = [[springboard.alerts.firstMatch buttons] elementBoundByIndex:1];
BOOL exist = [button waitForExistenceWithTimeout:5];
XCTAssertEqual(exist, YES, #"photo auth alert not exist");
[button tap];
It works fine on my iphone12(iOS15.4), but it not works on another iphone12-Pro(iOS15.4)
error:
*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil (NSInvalidArgumentException)
How should I solve this problem?
Thanks a lot!
Steps working for me :
close the iOS device or simulator
clean the build folder
clear the derived data
then open the iOS Device or simulator
you are good to go
Restarting iOS Device or simulator works for me

UIDocumentInteractionController - MailCompose not dismissing in iOS8

I have a very strange (& serious) problem.
My app uses a UIDocumentInteractionController to share a PDF document.
When the user selects the "Mail" option in the controller's pop-up the MailCompose window is opened.
But, neither the Send nor Cancel button in this window causes the MailCompose window to be dismissed, meaning the user gets stuck and has to kill the app. The mail does go out though.
Here's the catch:
This happens only in iOS8 (both versions released so far) and only on apps installed via the AppStore. That EXACT same version of the app, when running on my device via USB debugging works fine.
Here's some code:
-(void)sharePDF:(id)sender
{
#try
{
NSURL *fileURL = [NSURL fileURLWithPath:currentFileObject.LocalPath];
if(fileURL)
{
//UIDocumentInteractionController
NSString *newPath;
#try
{
//Create a copy of the file for sharing with a friendly name
if (currentFileObject.isSpecialReport)
{
newPath = [svc saveReport:[NSData dataWithContentsOfURL:fileURL] ToFile:[NSString stringWithFormat:#"%#.pdf", currentFileObject.ReportName]];
}
else
{
newPath = [svc saveReport:[NSData dataWithContentsOfURL:fileURL] ToFile:[NSString stringWithFormat:#"%#.pdf", currentFileObject.PatientFullName]];
}
}
#catch (NSException *exception) {
return;
}
NSURL *newURL = [NSURL fileURLWithPath:newPath];
self.docController = [UIDocumentInteractionController interactionControllerWithURL:newURL];
self.docController.delegate = self;
if (currentFileObject.isSpecialReport)
{
self.docController.name = [NSString stringWithFormat:#"Pathology - %#", currentFileObject.ReportName];
}
else
{
self.docController.name = [NSString stringWithFormat:#"Pathology - %#", currentFileObject.PatientFullName];
}
[self.docController presentOptionsMenuFromBarButtonItem:btnShare animated:YES];
}
}
#catch (NSException *exception) {
return;
}
}
I do not implement any of the delegate methods since non of them are required, I also do not make use of the preview functionality.
What's most puzzling to me is that the app from the AppStore behaves differently than my local one although the code is identical. My next step is to use the new beta developer tools (Test Flight) to re-publish the app, hoping that I can replicate the problem.
EDIT: I found a similar question on SO here: Cannot dismiss email sheet invoked from UIDocumentInteractionController in iOS 8
After reading that post I think it worth mentioning that I submitted the app to the AppStore via XCode 5 (the last version before XCode 6). Can that really be a factor here? Does Apple not use the same version on their side as the version in which the app was originally built?
I think this is a bug in iOS 8, and if it's still not working for you, I don't think Apple are likely to fix it. I'd upgrade to Xcode 6 and see if that fixes it for you. (It did for us, as you've discovered).

How to let DropboxAPI work in runModalForWindow

I'm using the Dropbox API for OSX. All works fine, except when I want to make calls in a modal window that is started with [NSApp runModalForWindow:thisWindow]; it seems the modal loop blocks the
DropboxAPI from processing anything.
The DBRestClient delegate methods are never called in response to for example [client loadMetadata:path]; Which is - if understand correctly - in line with what the NSApplication documentation says for this method. The question is:
Is there a way to let calls to Dropbox work from inside a modal window?
I have seen that timers can be added to the NSModalPanelRunLoopMode. Is there perhaps something similar for the DroboxAPI?
And additionally: will Dropbox calls that were started but not yet completed before this or any other modal window is displayed proceed as normal, or are they also blocked?
Yes; further investigation shows any runModalForWindow and even displaying an NSAlert.showModal will completely block the DropboxAPI. Also, inplace mouse handling loops do the same thing. Imo a major design flaw in the OSX DropboxAPI: it should have been running on a background thread. The only way around this, is to not start any user task that could involve blocking Dropbox while the API something is still running. Which is not really feasible in any non-trivial app that needs dropbox to work in the background.
Implementation of NSApplication runModalForWindow is indeed too harsh.
Here is more humanistic version:
void runWindowModal(NSWindow* pnw) {
[pnw retain];
NSApplication* app = [NSApplication sharedApplication];
NSModalSession session = [app beginModalSessionForWindow:pnw];
for( ;; ) {
if ([app runModalSession:session] != NSModalResponseContinue)
break;
NSEvent* e = [app nextEventMatchingMask: NSAnyEventMask
untilDate: [NSDate distantFuture]
inMode: NSDefaultRunLoopMode
dequeue: YES];
if (e != nil)
[app sendEvent: e];
}
[app endModalSession: session];
[pnw release];
}
This will enable NSURLConnection and other callbacks processing while running modal loops.
Dropbox support just confirmed that the DropboxAPI on OSX works on the main runloop and indeed runModalForWindow etc. will block the API. There's no work around.
The problem is more general. All nsurl connections can run only on the main runloop. This means that webviews have the same issue. And there is a sollution to this. You have to create a modal session and run it for short amounts of time, frequently, and lock the main thread in a loop until the modal window is closed. Every time you switch back to the modal session, the main runloop will finish any scheduled tasks, and that includes the nsurlconnections from the modal session.
Now I will show you a piece of code but note that this is c# using Xamarin.Mac library. You should be able to translate this easily to objc. But if you find it difficult, you can look up solutions for nswebview in modal dialog.
//so this is in my NSWindowController - the modal dialog
IntPtr session;
bool running;
public void showDialog ()//this is the method I use to show the dialog
{
running = true;
session = NSApplication.SharedApplication.BeginModalSession (Window);
int resp = (int)NSRunResponse.Continues;
while (running && resp == (int)NSRunResponse.Continues) {
resp = (int)NSApplication.SharedApplication.RunModalSession (session);
NSRunLoop.Current.RunUntil (NSRunLoopMode.Default, NSDate.DistantFuture);
}
NSApplication.SharedApplication.EndModalSession (session);
}
[Export ("windowWillClose:")]
public void WindowWillClose (NSNotification notification)//this is the override of windowWillClose:
{
running = false;
}

Global shortcut work but system play Error sound

I create global shortcut with this code:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent * theEvent) {
int modiferKeys = NSControlKeyMask | NSAlternateKeyMask;
if (([theEvent keyCode] == 7 && modiferKeys)) {
NSLog (#"%#",#"work");
}
}];
}
This code work perfect, but when some application have a focus (for example Xcode, AppStore...) the system play Error sound.
How fix it?
Thaks.
A different way to implement a global hot key is using RegisterEventHotKey, declared in CarbonEvents.h. The docs for it might be under "legacy", but as far as I can tell from the header, it's not deprecated and is available in 64-bit code.

NSOperationQueue is crashing in IOS

I have a project which downloads images in background using NSOperationQueue. It was working until now on devices with IOS 4.3. However if I build the app with base sdk 4.3 or with 5 and run the app on device with IOS5, the app crashes. When app is launched, it adds NSOperation objects into queue for downloading the images. If in between I press back button, I cancel the NSOperation and it crashes and displays following trace on console:
#0 0x004727b7 in ____NSOQSchedule_block_invoke_0 ()
#1 0x026a5618 in _dispatch_call_block_and_release ()
#2 0x026a7a10 in _dispatch_worker_thread2 ()
#3 0x974bb781 in _pthread_wqthread ()
#4 0x974bb5c6 in start_wqthread ()
and prints "ResourceLoadOperation isFinished = YES without being started by the queue it is in"
If I comment the cancel method call, app doesnot crash.
Is there any updates on the NSOperation changes for IOS5?
I had this same problem when building against iOS 5. I ended up creating a flag named operationStarted that was NO by default and I toggled to YES when the start method was called. Then in my finish method (where I generate the KVO notifications), I checked the value of the flag before firing the notifications.
The flag definition looks like this:
#property (nonatomic, assign, getter=isOperationStarted) BOOL operationStarted;
The start method:
- (void)start {
[self setOperationStarted:YES];
...
}
My finish method which is called when the operation is complete or cancelled:
- (void)finish {
if (![self isOperationStarted]) return;
[self willChangeValueForKey:#"isExecuting"];
executing = NO;
[self didChangeValueForKey:#"isExecuting"];
[self willChangeValueForKey:#"isFinished"];
finished = YES;
[self didChangeValueForKey:#"isFinished"];
}
That ended up resolving the issue for me. Hope it helps someone else.

Resources