How to suppress console messages generated by CFUserNotificationDisplayAlert - objective-c

If I call CFUserNotificationDisplayAlert() to display an alert box, it prints the following message in the console:
CFUserNotificationDisplayAlert: called from main application thread, will block waiting for a response.
I don't want this message printed. Is there any way to disable it? Or, is there a better way to go about this? Thanks!

CFUserNotificationDisplayAlert() is a convenience function that always blocks the main thread while waiting for user input. If you don't want to block the main thread, you'll have to create the CFUserNotification yourself and attach it to the main thread's runloop:
// First, add member variables in your class to store the user notification and runloop source, like this. You'll need to be able to access these variables later, from your callback method:
CFUserNotificationRef _userNotification;
CFRunLoopSourceRef _runLoopSource;
// When you want to show the alert, you will create it, create a runloop source for it, then attach the runloop source to the runloop:
_userNotification= CFUserNotificationCreate(... set this up the way you want to ...);
_runLoopSource = CFUserNotificationCreateRunLoopSource(NULL, userNotification, YourUserNotificationCallback, 0);
CFRunLoopAddSource(CFRunLoopGetMain(), runLoopSource, kCFRunLoopCommonModes);
// ...elsewhere, you'll need to define your callback function, something like this:
void YourUserNotificationCallback(CFUserNotificationRef userNotification, CFOptionFlags responseFlags)
{
// Handle the user's input here.
...
// Release your notification and runloop source:
CFRunLoopRemoveSource(CFRunLoopGetMain(), _runLoopSource, kCFRunLoopCommonModes);
CFRelease(_runLoopSource);
CFRelease(_userNotification);
}

Related

What happens when back button is pressed before asynchronous call is completed?

I have view models that are being stored in an array list on the application class. So their lifetime continues even if the activity gets destroyed because of rotation (however once isFinishing is true then the view model instance is removed from the list and ceases to exist).
I also have data service singletons that are used by the view models that also live indefinitely. So if I start an async call in my view model using the anko async block i.e.
async {
val data = DataService.instance.getData()
uiThread {
if (data != null) {
//do something
}
}
}
What happens if the user presses the back button before the call completes? IsFinishing will be true and my view model instance will no longer exist. Will the async call exception when it returns or will it die gracefully?
The code within uiThread call won't get executed if the underlying activity/fragment context has been garbage collected. A uiThread call within an async call will hold a WeakReference to the context, so the often encountered context memory leak won't occur. Details here.
I guess it will gracefully die. You could write a small test program in which you debug the behaviour. However, I would strongly suggest to keep a reference/pointer to the asynchronous task and kill it when you press the back button. No need to let it run in the background if you do not need the result / cannot handle the result anymore right

Why is any code executed before this has finished?

Supposing I have a code like this:
[ApiConnection getServerTimeWithBlock:^(BOOL gotTimeResponse){
if(gotTimeResponse)
{
//we're online, got the response from time endpoint
[ApiConnection registerNewCustomerWithBlock:^(NSString* val){
if(val)
{
NSLog(#"val: %#",val);
}
else
{
NSLog(#"no val");
}
}];
}
else
{
//we're offline
}
}];
NSLog(#"TEST");
why is the last NSLog executed before the whole first block has finished execution?
Because the getServerTimeWithBlock: method is asynchronous, so it returns immediately and runs on a background thread. When that thread is complete is calls the completion block.
So, the method runs before your log, but the completion block (usually) doesn't (it might if there was an error or something like that).
Presumably getServerTimeWithBlock: is exectuted asynchronously. When supplying the block, you're telling the APIConnection object what to do when it has finished getting the server time. This will involve network fetches and reading data back, which you don't want to wait for on the main thread as this will cause your UI to freeze. Your program therefore carries on, and the block is executed whenever the fetch is complete.
Note that blocks do not imply that asynchronous or multithreaded code is in use (see NSArray's enumerateWithBlock: method, for example) but it seems very likely to be the case here.

Using Dispatch Semaphores with delegate methods

So I have a wrapper class that when I send it a message, it returns YES/NO based on whether the internal object RECEIVED the message. Meaning, when I send this, it doesn't actually return when the task is done. I also want to make sure that only one task is executed at a time, so I use dispatch semaphores. My wrapper class calls a delegate method to notify me that it finished processing the internal task.
dispatch_queue_t queue = dispatch_queue_create("com.test.all", 0); // private queue
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); // one at a time
...
- (void)doStuff:(NSString *)stuff {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_sync(queue, ^(void) {
[myWrapperObject sendRequestToInternalStuff:stuff];
}
}
...
- (void)myWrapperClassProcessingIsDone {
dispatch_semaphore_signal(semaphore);
}
This doesn't work, and it hangs. How can I implement something like this without hanging?
If you want to ensure that only one task is executed at a time, the correct approach is to execute each task on the same serial GCD queue. A serial queue always executes just one task at a time. The dispatch_queue_create function creates a serial queue when you pass 0 (or DISPATCH_QUEUE_SERIAL or NULL) as the second argument..
If anyone needs to know, there is no way to do this. The semaphore locks the thread, so you would have to have a separate spawned thread with a run-loop waiting for a variable change. I just re-worked my code to avoid semaphores.

Can we fire an event when ever there is Incoming and Outgoing call in iphone?

Can I fire an event when ever there is Incoming and Outgoing call ends on iphone? Axample of an event is calling a webservice .
Yes you can, but not necessarily immediately.
There is a framework, called the CoreTelephony framework, which has a CTCallCenter class. One of the properties on this class is the callEventHandler property. This is a block that gets fired when then state of a phone call changes. For example:
CTCallCenter *callCenter = ...; // get a CallCenter somehow; most likely as a global object or something similar?
[callCenter setCallEventHandler:^(CTCall *call) {
if ([[call callState] isEqual:CTCallStateConnected]) {
//this call has just connected
} else if ([[call callState] isEqual:CTCallStateDisconnected]) {
//this call has just ended (dropped/hung up/etc)
}
}];
That's really about all you can do with this. You don't get access to any phone numbers. The only other useful tidbit of information is an identifier property on CTCall so you uniquely identify a CTCall object.
CAUTION:
This event handler is not invoked unless your app is in the foreground! If you make and receive calls while the app is backgrounded, the event handler will not fire until your app becomes active again, at which point (according to the documentation linked to above) the event handler will get invoked once for each call that has changed state while the app was in the background.
No but you do get callbacks into the app when those events happen.
-(void)applicationWillResignActive:(UIApplication *)application{
//our app is going to loose focus since thier is an incoming call
[self pauseApp];
}
-(void)applicationDidBecomeActive:(UIApplication *)application{
//the user declined the call and is returning to our app
[self resumeApp];
}
No. As of the current SDK, this is not possible. Apple does not allow apps to have such hooks.

How can my app detect a change to another app's window?

In Cocoa on the Mac, I'd like to detect when a window belonging to another app is moved, resized, or repainted. How can I do this?
You would need to use the Accessibility APIs, which are plain-C, located inside the ApplicationServices framework. For instance:
First you create an application object:
AXUIElementRef app = AXUIElementCreateApplication( targetApplicationProcessID );
Then you get the window from this. You can request the window list and enumerate, or you can get the frontmost window (look in AXAttributeConstants.h for all the attribute names you'd use).
AXUIElementRef frontWindow = NULL;
AXError err = AXUIElementCopyAttributeValue( app, kAXMainWindowAttribute, &frontWindow );
if ( err != kAXErrorSuccess )
// it failed -- maybe no main window (yet)
Now you can request notification via a C callback function when a property of this window changes. This is a four-step process:
First you need a callback function to receive the notifications:
void MyAXObserverCallback( AXObserverRef observer, AXUIElementRef element,
CFStringRef notificationName, void * contextData )
{
// handle the notification appropriately
// when using ObjC, your contextData might be an object, therefore you can do:
SomeObject * obj = (SomeObject *) contextData;
// now do something with obj
}
Next you need an AXObserverRef, which manages the callback routine. This requires the same process ID you used to create the 'app' element above:
AXObserverRef observer = NULL;
AXError err = AXObserverCreate( applicationProcessID, MyObserverCallback, &observer );
if ( err != kAXErrorSuccess )
// handle the error
Having got your observer, the next step is to request notification of certain things. See AXNotificationConstants.h for the full list, but for window changes you'll probably only need these two:
AXObserverAddNotification( observer, frontWindow, kAXMovedNotification, self );
AXObserverAddNotification( observer, frontWindow, kAXResizedNotification, self );
Note that the last parameter there is passing an assumed 'self' object as the contextData. This is not retained, so it's important to call AXObserverRemoveNotification when this object goes away.
Having got your observer and added notification requests, you now want to attach the observer to your runloop so you can be sent these notifications in an asynchronous manner (or indeed at all):
CFRunLoopAddSource( [[NSRunLoop currentRunLoop] getCFRunLoop],
AXObserverGetRunLoopSource(observer),
kCFRunLoopDefaultMode );
AXUIElementRefs are CoreFoundation-style objects, so you need to use CFRelease() to dispose of them cleanly. For cleanliness here, for example, you would use CFRelease(app) once you've obtained the frontWindow element, since you'll no longer need the app.
A note about Garbage-Collection: To keep an AXUIElementRef as a member variable, declare it like so:
__strong AXUIElementRef frontWindow;
This instructs the garbage collector to keep track of this reference to it. When assigning it, for compatibility with GC and non-GC, use this:
frontWindow = (AXUIElementRef) CFMakeCollectable( CFRetain(theElement) );
Further research turned up "Quartz Display Services"
The interesting function for my needs is CGRegisterScreenRefreshCallback.