Constructing or composing my own blocks or imps - objective-c

Question
Does objective-c have any kind of functionality which allows me to compose my own blocks or IMPs on the fly?
By that I mean let me link together arbitrary code snippets into a single block (and then perform imp_implementationWithBlock) or just get an assembled IMP straight up.
Pseudocode
(IMP) linkExistingBlock:LBExistingBlock With:^{
}
or
(IMP) linkExistingBlock:LBExistingBlock With:LBAnotherBlock

If you have two Blocks, just call them. Further, Blocks are objects, and can be put into NSArrays. Then you can enumerate the array and invoke its contents.
for( dispatch_block_t block in arrayOfBlocks ){
block();
}
or
[arrayOfBlocks enumerateObjectsUsingBlock:^(dispatch_block_t block, NSUInteger idx, BOOL *stop) {
block();
}];
If you have IMPs, those are just function pointers -- they can be put into a C array, or wrapped in NSValues and put into a Cocoa array. You just need to cast them before you try to call them.
For your example method signature:
- (dispatch_block_t)blockLinkingExistingBlock: (dispatch_block_t)firstBlock withBlock: (dispatch_block_t)secondBlock
{
dispatch_block_t linker = ^{ firstBlock(); secondBlock();};
// if compiling with ARC
return linker;
// otherwise
// return [[linker copy] autorelease];
}

There's nothing built in, but you can just create a block that simply executes a series of blocks by calling them.

Related

Objective C - caller Object of a method [duplicate]

Example: When my method -fooBar gets called, I want it to log in the console which other method of which other class called it.
Right now, I only know how to log the method name of fooBar itself and it's class, with this:
_cmd
[self class]
Is this possible to figure out?
In fully optimized code, there is no 100% surefire way to determine the caller to a certain method. The compiler may employ a tail call optimization whereas the compiler effectively re-uses the caller's stack frame for the callee.
To see an example of this, set a breakpoint on any given method using gdb and look at the backtrace. Note that you don't see objc_msgSend() before every method call. That is because objc_msgSend() does a tail call to each method's implementation.
While you could compile your application non-optimized, you would need non-optimized versions of all of the system libraries to avoid just this one problem.
And this is just but one problem; in effect, you are asking "how do I re-invent CrashTracer or gdb?". A very hard problem upon which careers are made. Unless you want "debugging tools" to be your career, I would recommend against going down this road.
What question are you really trying to answer?
How about this:
NSString *sourceString = [[NSThread callStackSymbols] objectAtIndex:1];
NSCharacterSet *separatorSet = [NSCharacterSet characterSetWithCharactersInString:#" -[]+?.,"];
NSMutableArray *array = [NSMutableArray arrayWithArray:[sourceString componentsSeparatedByCharactersInSet:separatorSet]];
[array removeObject:#""];
NSLog(#"Class caller = %#", [array objectAtIndex:3]);
NSLog(#"Method caller = %#", [array objectAtIndex:4]);
Credits to the original author, intropedro.
It's not possible in the general case without actually walking the stack. There's not even a guarantee that another object send the message that called the method. For example, it could be called from a block in a signal handler.
NSLog(#"Show stack trace: %#", [NSThread callStackSymbols]);
See backtrace(3).
User the below method
Pass index for which you want to display method and pass -1 if you want to display full stack of method
+(void) methodAtIndex:(int)index{
void* callstack[128];
int frames = backtrace(callstack, 128);
char** strs = backtrace_symbols(callstack, frames);
if (index == -1) {
for (int i = 0; i < frames; ++i) {
printf("%s\n", strs[i]);
}
}
else {
if (index < frames) {
printf("%s\n", strs[index]);
}
}
free(strs);
}
This information can be obtained using DTrace.
Make a macro that adds the __FUNCTION__ to the function name to the function call. This macro will then call your function with an extra parameter of a char* to the target function.
I was trying to catch who, how and when changes window's size and did some handwork:
- (void)logWindowWidth:(NSString *)whoCalls {
NSLog(#"%#", whoCalls);
NSLog(#"self.window.size.width %f", self.window.size.width);
}
-(void)someMethod {
[self logWindowWidth:#"someMethod - before"];
...
[self logWindowWidth:#"someMethod - after"];
}
-(void)anotherMethod {
[self logWindowWidth:#"anotherMethod - before"];
...
[self logWindowWidth:#"anotherMethod - after"];
}

Add code to block dynamically

I'm pretty new to using blocks. I'm wondering if there is a way to add code dynamically to a block? A mutable block if you will.
This is not quite what it sounds like you want, but it achieves a similar result if not quite the same one: Having a __block NSMutableArray of blocks to be called sequentially from within an outer block.
A silly demo:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool {
__block NSMutableArray *subblocks = [NSMutableArray array];
void (^blockWithBlocks)(void) = ^{
NSLog(#"%s: in blockWithBlocks()", __PRETTY_FUNCTION__);
for (void (^subblock)(void) in subblocks) {
subblock();
}
};
for (int i = 0; i < 3; i++) {
void (^subblock)(void) = ^{
NSLog(#"%s: in subblock %d", __PRETTY_FUNCTION__, i);
};
[subblocks addObject:subblock];
}
blockWithBlocks();
}
return 0;
}
Note that the requirements for copying blocks under ARC have been in flux. Previously it would have been necessary to write [subblocks addObject:[subblock copy]]; rather than simply [subblocks addObject:subblock]; Under the current semantics described in the clang documentation
With the exception of retains done as part of initializing a __strong parameter variable or reading a __weak variable, whenever these semantics call for retaining a value of block-pointer type, it has the effect of a Block_copy. The optimizer may remove such copies when it sees that the result is used only as an argument to a call.
the only times that it is necessary to copy a block to be sure that it is no longer on the stack is when the block is being passed as an argument to a function/method that has a __strong parameter variable and when the block is being read from a __weak variable.
What do you mean "add code dynamically to a block"? How is that different from simply making a new block from the "code" and the original block?
If the difference is that you want to have a reference to a block and have its behavior change without having to assign a new block to that reference, then you can have the block capture mutable state, where the mutable state could contain the block(s) to call, which you can then change, like what #NateChandler suggests.
If the difference is that is that you can choose between several different pieces of "code", so you cannot hard-code it at the place you are creating the block, then you can just make the "pieces of code" into blocks and select the right block to put into the new block.

ObjC: BAD ACCESS when call blocks ^{} in later functions?

Following this discussion, I've encountered a bad access issue;
A loop has several steps: a, b, c, ... x, y, z:
-(void)cycle:(float)delta{
[self stepA]
[self stepB]
// etc.
[self stepZ]
}
At some point, step x does the following:
// IRQ is an NSMutableArray
// Self is a reference to the engine running the cycles
[IRQ addObject:^{ NSLog(#"hello! %#", self); } ];
Later, step z is to process all "delayed" calls:
for (int i = 0; i < [IRQ count]; i++){
void (^delayedCall)(void) = [IRQ objectAtIndex:i];
delayedCall();
}
[IRQ removeAllObjects];
Result: EXEC_BAD_ACCESS
Now, if step x only adds a plain string with no object reference like follows, step Z works fine:
[IRQ addObject:^{ NSLog(#"hello!"); } ];
Last observation, if a same step both adds blocks to the queue AND iterates over the queue to execute the blocks, then no problem occurs.
Like the reference to an object gets "lost" as the step: method is left?
I don't understand much in this area and will need more help!
edit:
James, just tried the following to avoid that reference cyle:
NSString *userName = #"James";
[IRQ addObject:^{ NSLog(#"hello %#", userName); } ];
and it also happens. How would your solution apply to this?
Thanks in advance!
When you create a block with the ^{} syntax, it's created on the stack. To persist the block for a long period of time (beyond the scope of the function that creates it), you must copy the block into the heap:
void (^ myBlock)(void) = ^ {
// your block code is here.
};
[IRQ addObject:[[myBlock copy] autorelease]];
If using ARC, skip the -autorelease message.
The problem is that block objects are created on the stack. You need to copy blocks to the heap when you expect them to be used after the scope in which they were declared is destroyed, and if the block is not copied for you.
Here you pass an object "down the stack" to a method that is not aware of blocks. Replace
[IRQ addObject:^{ NSLog(#"hello! %#", self); } ];
with
[IRQ addObject:[^{ NSLog(#"hello! %#", self); } copy]];
and the EXC_BAD_ACCESS at this point will go away.
In most cases though, you do not need to copy the block! A couple of examples:
If you return a block from a method ("up the stack"), ARC will automatically copy it.
If you call a method that does not keep the block, the block does not need to be copied, because it stays in scope. Example: the block passed to -[NSArray sortedArrayUsingComparator:].
If you call a method that uses the block later, the method should take the responsible for copying the block, otherwise each and every caller would need to copy the block. All methods/functions from Apple's libraries that I am aware of follow that pattern. Example: the completion block passed to +[UIView animateWithDuration:options:animations:completion:].
It seems the object you pass in.. In your examples: self and userName are being prematurely deallocated. This isn't the behaviour I expect from blocks. As in my previous answer, I expected the problem to be because of too much retention!
As a test, could you try:
NSString *userName = [#"James" retain];
[IRQ addObject:^{ NSLog(#"hello %#", userName); } ];
This would be a memory leak, but it would help indicate if the object is being deallocated.
This is caused by a "retain cycle" where the block is retaining self and self is retaining the block.
Try this:
__block typeof(self) blockSafeSelfReference = self;
[IRQ addObject:^{ NSLog(#"hello! %#", blockSafeSelfReference); } ];
If using ARC, use __unsafe_unretained instead of __block

updating UI from a C function in a thread

I am using a library called libmosquitto in an iPhone app.
The library is written in C.
It receives push notifications and therefor runs in a thread.
I want to take the data it receives, and display it in a UITableView, however ( I think) I have to write the callbacks which libmosquitto uses as C functions rather than Objective C methods, so I cannot access 'self' in order to do:
[self performSelectorOnMainThread:#selector(hideActivityViewer) withObject:nil waitUntilDone:NO];
Anyone have problems like this, is there another way I could update the UI?
From inside one of my Objective C methods I call this:
mosquitto_message_callback_set(mosq, my_message_callback);
And my_message_callback is defined as:
void my_message_callback(void *obj, struct mosquitto_message *message)
{
NSLog(#"Do this thing:");
if(message->payloadlen){
const char *payload = (const char *)message->payload;
[array addObject:[NSString stringWithUTF8String: payload]];
//[self performSelectorOnMainThread:#selector(updateTable) withObject:nil waitUntilDone:NO];
//printf("%s %s\n", message->topic, message->payload);
}else{
//printf("%s (null)\n", message->topic);
}
//fflush(stdout);
}
Thanks
Look into Grand Central Dispatch (GCD, aka libdispatch). It's a C library so ought to be able to be called from your C code without issue. You'd want to do something like:
dispatch_async(dispatch_get_main_queue(), ^{
//code you want on the main thread.
});
The function mosquitto_new takes a void * pointer as the second argument, which it will then pass to any callbacks that you have. You can use that to pass self as the thing that should arrive at your callback as void *obj. It's then explicitly safe to cast that to the correct [pointer to] class type since C allows any pointer type to be converted to void * (and back) without any side effects.
So then you'd do something like:
void my_message_callback(void *obj, struct mosquitto_message *message)
{
[(ClassType *)obj
performSelectorOnMainThread:#selector(updateTable)
withObject:nil
waitUntilDone:NO];
}
You can get access to NSApp from everywhere, and I believe that any message not understood by NSApplication will be send to its delagate which is your instance of NSApplicationDelegate. If this does not do it, you could add a class application that returns the object that can run your method if this object is unique.
You can also use
Use grand central dispatch and the function
dispatch_async(dispatch_get_main_queue(), ^{
//some code
})

Is there a SELF pointer for blocks?

I'd like to recursively call a block from within itself. In an obj-c object, we get to use "self", is there something like this to refer to a block instance from inside itself?
Fun story! Blocks actually are Objective-C objects. That said, there is no exposed API to get the self pointer of blocks.
However, if you declare blocks before using them, you can use them recursively. In a non-garbage-collected environment, you would do something like this:
__weak __block int (^block_self)(int);
int (^fibonacci)(int) = [^(int n) {
if (n < 2) { return 1; }
return block_self(n - 1) + block_self(n - 2);
} copy];
block_self = fibonacci;
It is necessary to apply the __block modifier to block_self, because otherwise, the block_self reference inside fibonacci would refer to it before it is assigned (crashing your program on the first recursive call). The __weak is to ensure that the block doesn't capture a strong reference to itself, which would cause a memory leak.
The following recursive block code will compile and run using ARC, GC, or manual memory management, without crashing, leaking, or issuing warnings (analyzer or regular):
typedef void (^CountdownBlock)(int currentValue);
- (CountdownBlock) makeRecursiveBlock
{
CountdownBlock aBlock;
__block __unsafe_unretained CountdownBlock aBlock_recursive;
aBlock_recursive = aBlock = [^(int currentValue)
{
if(currentValue >= 0)
{
NSLog(#"Current value = %d", currentValue);
aBlock_recursive(currentValue-1);
}
} copy];
#if !__has_feature(objc_arc)
[aBlock autorelease];
#endif
return aBlock;
}
- (void) callRecursiveBlock
{
CountdownBlock aBlock = [self makeRecursiveBlock];
// You don't need to dispatch; I'm doing this to demonstrate
// calling from beyond the current autorelease pool.
dispatch_async(dispatch_get_main_queue(), ^
{
aBlock(10);
});
}
Important considerations:
You must copy the block onto the heap manually or else it will try to access a nonexistent stack when you call it from another context (ARC usually does this for you, but not in all cases. Better to play it safe).
You need TWO references: One to hold the strong reference to the block, and one to hold a weak reference for the recursive block to call (technically, this is only needed for ARC).
You must use the __block qualifier so that the block doesn't capture the as-yet unassigned value of the block reference.
If you're doing manual memory management, you'll need to autorelease the copied block yourself.
You have to declare the block variable as __block:
typedef void (^MyBlock)(id);
__block MyBlock block = ^(id param) {
NSLog(#"%#", param);
block(param);
};
There is no self for blocks (yet). You can build one like this (assuming ARC):
__block void (__weak ^blockSelf)(void);
void (^block)(void) = [^{
// Use blockSelf here
} copy];
blockSelf = block;
// Use block here
The __block is needed so we can set blockSelf to the block after creating the block. The __weak is needed because otherwise the block would hold a strong reference to itself, which would cause a strong reference cycle and therefore a memory leak. The copy is needed to make sure that the block is copied to the heap. That may be unnecessary with newer compiler versions, but it won't do any harm.