EKEventStore Programming Xcode iOS Asynchronous Search - ios

The Documentation states:
(void)enumerateEventsMatchingPredicate:(NSPredicate *)predicate
usingBlock:(EKEventSearchCallback)block
This method is synchronous. For asynchronous behavior, run the method on another thread with dispatch_async or NSOperation.
How do you make this asynchronous, the sentence doesn't really demonstrate it. Could anyone clarify?
Thanks
D :-)

either dispatch it all:
#include <stdio.h>
int main(int argc, char *argv[]) {
...
dispatch_async(dispatch_get_global_queue(0,0), ^{
[store enumerateEventsMatchingPredicate:p usingBlock:^(..) {
//DO IT
}];
});
...
}
or the callbacks
#include <stdio.h>
int main(int argc, char *argv[]) {
...
[store enumerateEventsMatchingPredicate:p usingBlock:^(..) {
dispatch_async(dispatch_get_global_queue(0,0), ^{
//DO IT
});
}];
...
}

Related

Why does modern Xcode generate projects with UIApplicationMain outside of autorelease pool?

If I remember correctly, back in the days Xcode used to generate the main function something like this (at least for iOS applications):
int main(int argc, char * argv[]) {
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]);
}
}
I.e. UIApplicationMain function was wrapped inside of #autoreleasepool. However I noticed that currently Xcode no longer does that:
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
#autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
So, UIApplicationMain is outside of the autorelease pool by default nowadays. Is there any official changelog/paper that explains why the latter implementation is now preferred over the former one?

Objective-C - making a Unity plugin from Aruts

What would be the best approach to making a plugin from a full Xcode Project? I've tried creating simple "get numbers from Objective-C" type of plugins, but this seems far more complex.
I'm trying to see if I can get the functionality of Aruts by Simon Epskamp onto a Unity game. What Aruts does is take the audio heard by the mic and output it to the headphones / speakers.
So far, what I've tried is to import IosAudioController.m, IosAudioController.h (renamed TestScript), and my own "extern" file that accesses Start and Stop functionality from said files.
While it does run without errors, all I'm hearing are rapid-firing clicking sounds, and per the comments, the function recordingCallback is not being called.
I also tried to take bits of the Aruts main.m and tried to stick it into the Unity project's main.mm, to no success. I'll update this with code when I can get my hands on it.
EDIT:
Here's my TestExtern.h:
#import <Foundation/Foundation.h>
#import "TestScript.h"
void TestStartAudioRec() {
[iosAudio start];
}
void TestStopAudioRec() {
[iosAudio stop];
}
Here's the Unity project's main.mm:
#include "RegisterMonoModules.h"
#include "RegisterFeatures.h"
#include <csignal>
#import "TestScript.h"
static const int constsection = 0;
void UnityInitTrampoline();
const char* AppControllerClassName = "UnityAppController";
int main(int argc, char* argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
iosAudio = [[TestScript alloc] init];
#autoreleasepool
{
UnityInitTrampoline();
UnityParseCommandLine(argc, argv);
RegisterMonoModules();
NSLog(#"-> registered mono modules %p\n", &constsection);
RegisterFeatures();
std::signal(SIGPIPE, SIG_IGN);
int retval = UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String:AppControllerClassName]);
NSLog(#"After retval");
[pool release];
return retval;
}
return 0;
}
#if TARGET_IPHONE_SIMULATOR && TARGET_TVOS_SIMULATOR
#include <pthread.h>
extern "C" int pthread_cond_init$UNIX2003(pthread_cond_t *cond, const pthread_condattr_t *attr)
{ return pthread_cond_init(cond, attr); }
extern "C" int pthread_cond_destroy$UNIX2003(pthread_cond_t *cond)
{ return pthread_cond_destroy(cond); }
extern "C" int pthread_cond_wait$UNIX2003(pthread_cond_t *cond, pthread_mutex_t *mutex)
{ return pthread_cond_wait(cond, mutex); }
extern "C" int pthread_cond_timedwait$UNIX2003(pthread_cond_t *cond, pthread_mutex_t *mutex,
const struct timespec *abstime)
{ return pthread_cond_timedwait(cond, mutex, abstime); }
#endif // TARGET_IPHONE_SIMULATOR && TARGET_TVOS_SIMULATOR
Perhaps there's something wrong with it. Compare it with the main.m for Aruts:
#import <UIKit/UIKit.h>
#import "IosAudioController.h"
int main(int argc, char *argv[]) {
NSLog(#"main");
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
iosAudio = [[IosAudioController alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Any suggestions?

How can I intercept fatal exceptions?

I want to integrate in my iPad application a way to monitor the user activity and especially the exceptions that occurred and triggered the application to stop, something like the bug report of Apple but for the mobile clients.
I tried to encapsulate the main action (main.m) between #try and #catch blocks, but the exception is not thrown until there, and I just can't add such blocks everywhere in my code. Neither the delegate method applicationWillTerminate is not called, the application is just brutally stopped without any notification.
Any ideas on this ?
It works for me in main.m
int main(int argc, char *argv[]) {
#autoreleasepool {
int retVal = 0;
#try {
retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
#catch (NSException *exception) {
NSLog(#"Exception: %#", exception);
[exception raise];
}
return retVal;
}
}
P.S.
Another tricky way : EXC_BAD_ACCESS automatic handling
And example of NSUncaughtExceptionHandler

How do I recover from EXC_BAD_ACCESS?

I'm intentionally causing an EXC_BAD_ACCESS. By triggering a write to an NSObject in a read-only virtual memory page. Ideally, I'd like to catch EXC_BAD_ACCESS, mark the virtual memory page as read-write and have execution continue as it normally would have. Is this even possible? The code I've written to cause the EXC_BAD_ACCESS is below.
WeakTargetObject.h (ARC)
#interface WeakTargetObject : NSObject
#property (nonatomic, weak) NSObject *target;
#end
WeakTargetObject.m (ARC)
#implementation WeakTargetObject
#end
main.m (MRR)
- (void)main {
char *mem = NULL;
vm_allocate(mach_task_self(), (vm_address_t *)&mem, vm_page_size, VM_FLAGS_ANYWHERE);
NSLog(#"mem: %p", mem);
WeakTargetObject *weakTargetObject = objc_constructInstance([WeakTargetObject class], (void *)mem);
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSObject *target = [[NSObject alloc] init];
weakTargetObject.target = target;
[pool drain];
pool = [[NSAutoreleasePool alloc] init];
NSLog(#"expect non-nil. weakTargetObject.target: %#", weakTargetObject.target);
[pool drain];
vm_protect(mach_task_self(),
(vm_address_t)mem,
vm_page_size,
1,
VM_PROT_READ);
// triggers EXC_BAD_ACCESS when objc runtime
// tries to nil weakTargetObject.target
[weakTargetObject release];
NSLog(#"expect nil. weakTargetObject.target: %#", weakTargetObject.target);
}
I found a darwin-dev post that has the answer!
WARNING
This answer has a major downside. My debugger wouldn't work in any thread other than the mach exception thread. Putting a breakpoint in any other thread caused Xcode5 to hang. I had to force-quit it. Inside my catch_exception_raise function, it worked fine. I asked the LLDB folks about this.
END WARNING
This code is the skeleton of the answer. It will infinite loop, because (according to the follow-up) you need to do something to make the error recoverable. In my case, I need to mark the page as read-write.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <stdarg.h>
#include <pthread.h>
#include <assert.h>
#include <mach/mach.h>
kern_return_t
catch_exception_raise(mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
exception_data_t code_vector,
mach_msg_type_number_t code_count)
{
fprintf(stderr, "catch_exception_raise %d\n", exception);
return KERN_SUCCESS; // loops infinitely...
}
void *exception_handler(void *arg)
{
extern boolean_t exc_server();
mach_port_t port = (mach_port_t) arg;
mach_msg_server(exc_server, 2048, port, 0);
abort(); // without this GCC complains (it doesn't know that mach_msg_server never returns)
}
void setup_mach_exception_port()
{
static mach_port_t exception_port = MACH_PORT_NULL;
mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &exception_port);
mach_port_insert_right(mach_task_self(), exception_port, exception_port, MACH_MSG_TYPE_MAKE_SEND);
task_set_exception_ports(mach_task_self(), EXC_MASK_BAD_ACCESS, exception_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
pthread_t returned_thread;
pthread_create(&returned_thread, NULL, exception_handler, (void*) exception_port);
}
void test_crash()
{
id *obj = NULL;
*obj = #"foo";
}
int main(int argc, char** argv)
{
setup_mach_exception_port();
test_crash();
return 0;
}
This is my new code that works:
WeakTargetObject.h (ARC)
#interface WeakTargetObject : NSObject
#property (nonatomic, weak) NSObject *target;
#end
WeakTargetObject.m (ARC)
#implementation WeakTargetObject
#end
main.m (MRR)
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <stdarg.h>
#include <pthread.h>
#include <assert.h>
#include <mach/mach.h>
static char * mem = NULL;
kern_return_t
catch_exception_raise(mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
exception_data_t code_vector,
mach_msg_type_number_t code_count)
{
fprintf(stderr, "catch_exception_raise %d, mem: %p\n", exception, mem);
kern_return_t success = vm_protect(mach_task_self(),
(vm_address_t)mem,
vm_page_size,
0,
VM_PROT_DEFAULT);
fprintf(stderr, "switched to read-write: %d\n", success);
return KERN_SUCCESS;
}
void *exception_handler(void *arg)
{
extern boolean_t exc_server();
mach_port_t port = (mach_port_t) arg;
mach_msg_server(exc_server, 2048, port, 0);
abort(); // without this GCC complains (it doesn't know that mach_msg_server never returns)
}
void setup_mach_exception_port()
{
static mach_port_t exception_port = MACH_PORT_NULL;
mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &exception_port);
mach_port_insert_right(mach_task_self(), exception_port, exception_port, MACH_MSG_TYPE_MAKE_SEND);
task_set_exception_ports(mach_task_self(), EXC_MASK_BAD_ACCESS, exception_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
pthread_t returned_thread;
pthread_create(&returned_thread, NULL, exception_handler, (void*) exception_port);
}
- (void)main {
setup_mach_exception_port();
vm_allocate(mach_task_self(), (vm_address_t *)&mem, vm_page_size, VM_FLAGS_ANYWHERE);
NSLog(#"mem: %p", mem);
WeakTargetObject *weakTargetObject = objc_constructInstance([WeakTargetObject class], (void *)mem);
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSObject *target = [[NSObject alloc] init];
weakTargetObject.target = target;
[pool drain];
pool = [[NSAutoreleasePool alloc] init];
NSLog(#"expect non-nil. weakTargetObject.target: %#", weakTargetObject.target);
[pool drain];
vm_protect(mach_task_self(),
(vm_address_t)mem,
vm_page_size,
// zero means don't set VM_PROT_READ as the maximum protection
// one means DO set VM_PROT_READ as the maximum protection
// we want zero because the if VM_PROT_READ is the maximum protection
// we won't be able to set it to VM_PROT_DEFAULT later
0,
VM_PROT_READ);
// triggers EXC_BAD_ACCESS when objc runtime
// tries to nil weakTargetObject.target
[weakTargetObject release];
NSLog(#"expect nil. weakTargetObject.target: %#", weakTargetObject.target);
}

Why does Xcode 4.2 use #autoreleasepool in main.m instead of NSAutoreleasePool?

I've noticed that there is a different way in Xcode 4.2 to start the main function:
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([PlistAppDelegate class]));
}
}
and
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Does anybody know the difference between those two?
The first one is using ARC, which is implemented in iOS5 and above to handle memory management for you.
On the second one, you're managing your own memory and creating an autorelease pool to handle every autorelease that happens inside your main function.
So after reading a bit on what's new on Obj-C with iOS5 it appears that the:
#autoreleasepool {
//some code
}
works the same as
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// some code
[pool release];
with the difference that the last one would throw an error on ARC.
EDIT:
The first one is using ARC or not.

Resources