문제

This is a two-part question about blocks (^{}) in Objective-C. I have searched for some answers, but nothing has showed up in Google or SO. This question stems from a desire to create an custom XML Layout Engine for iOS, with support for blocks - meaning that I want to parse NSStrings and create a block during runtime.

1) Is this even possible? If so, how can it be done?

Not being able to find much on NSString to Block, I thought that the reason may be how a block is handled by the compiler - so again I searched for an answer but came up empty-handed. So:

2) What happens to a block at compile time in Objective-C?

도움이 되었습니까?

해결책

A block is two things; a hunk of executable code and state captured at the moment when execution passes over the block.

I.e. given:

 myBlock = ^{ return someVariable + someOtherVariable; };

When compiled, this creates a chunk of code that acts very much like a function that adds two variables together returns the result. No block instance is created.

When executing, when the expression myBlock = ^{...}; is evaluated, then a block instance is created. Inside that block instance is a reference to the code the compiler created and a copy of the values contained in the two variables at the time the assignment to myBlock was made (unless, of course, __block is in play, etc...).

That answers (2), but is relevant to answering (1).

At runtime, you can create instances of existing, compiled, blocks all day long. You cannot, however, create new kinds of blocks. Doing so would require a compiler and would be limited to runtime environments where compiling new executable code and actually executing it is possible.

다른 팁

What you can't easily do is compile Objective-C code at run-time to create blocks. What you can do is create a small parser for your layout DSL and create a tree of blocks. For example a mathematical expression parser could be implemented using nested blocks.

Here is an example for the expresion "2 + 3 * 4":

typedef double(^MathBlock)(void);

MathBlock exprL = ^(void) { return 3.0; };
MathBlock exprR = ^(void) { return 4.0; };

exprR = ^(void) { return exprL() * exprR();  };
exprL = ^(void) { return 2.0; };

exprR = ^(void) { return exprL() + exprR();  };

double result = exprR();

Obviously, you will need to write parsing functions interpret your XML to return these blocks. This is particularly simple with recursive descent parsers.

1) if you mean to compile a block at run time, no. Compiler is not available at run time. 2) obviously, a block is compiled at compile time. It is executable code at run time, like a function or a method or a part of any of them. But blocks are compiled in a way they can be sent for post execution and handling block vars magic.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top