IOS Block Detailed 3

Source: Internet
Author: User
Tags locale

--Translated from Apple Reference Library "Blocks programming Topic"

Brief introduction

Block objects are syntactic and run-time characteristics of the C language. It is similar to a standard C function, but you can bind code, variables to heap (heap), stacks (stack). A block also maintains a series of States or data that affect the results of execution.

Blocks can be made into function expressions that are passed to the API or used in multiple threads. The most useful is the callback, because the block can send the code and data along with the callback.

In the OSX 10.6 Xcode, you can use blocks, which are integrated with GCC and Clang . Block syntax is supported after OSX 10.6 and iOS 4.0. The block runtime is open source and can be integrated into the LLVM ' s compiler-rt subproject repository . The block is defined in N1370:apple's Extensions to C of the standard C workgroup, which also includes garbage collection. Both O-c and C + + come from C, and blocks work in 3 languages (including o-c++).

In this document, you will learn what block objects are and how to use them in c,c++ and o-c to make your code more performance and maintainable.

Begin

Declaration block

The ^ operator declares the beginning of a block variable (as with C; To indicate the end of an expression), as shown in the code:

int multiplier = 7;

Int (^myblock) (int) = ^ (int num) {

return num * multiplier;

};

Explain:

Note that a block can use a variable defined within the same scope.

Once a block is declared, you can call it as if it were a function:

int multiplier = 7;

Int (^myblock) (int) = ^ (int num) {

return num * multiplier;

};

printf ("%d", Myblock (3));

Using blocks directly

In many cases, you do not have to declare a block variable, but simply write a inline block and treat it as a parameter, as shown in the following code.

Gsort_b similar to the standard Gsort_r function, but its last parameter is a block.

Char *mycharacters[3] = {"Tomjohn", "George", "Charles Condomine"};

Qsort_b (mycharacters, 3, sizeof (char *), ^ (const void *l, const void *r) {

Char *left = * (char * *) L;

Char *right = * (char * *) R;

Return strncmp (left, right, 1);

});

Mycharacters is now {"Charles condomine", "George", Tomjohn "}

Cocoa and Blocks

In the cocoa framework, there are several ways to take a block as a parameter. Typically, an operation is performed in the collection, or as a callback after the operation is completed. The following code shows how to use blocks in the Sortedarrayusingcomparator method of Nsarray. This method uses a block parameter. To demonstrate, the block is defined here as a nscomparator local variable.

Nsarray *stringsarray = [Nsarray arraywithobjects: @ "string 1" @ "string" @ "string 12" ,

@ "String One", @ "string", nil];

static nsstringcompareoptions comparisonoptions = Nscaseinsensitivesearch | Nsnumericsearch |

Nswidthinsensitivesearch | Nsforcedorderingsearch;

Nslocale *currentlocale = [Nslocale Currentlocale];

Nscomparator Findersortblock = ^ (ID string1, id string2) {

Nsrange string1range = nsmakerange (0, [string1 length]);

return [string1 compare:string2 options:comparisonoptions range:string1range Locale:currentlocale];

};

Nsarray *findersortarray = [Stringsarray sortedarrayusingcomparator:findersortblock];

NSLog (@ "Findersortarray:%@", Findersortarray);

/*output:

Findersortarray: (

"String 1",

"String 02",

"String 11",

"String 12",

"String 21"

)*/

Block variables

A powerful feature of the block it can change variables within the same scope. Use the __block modifier to identify a variable that can be changed by a block. Using the following code, you can use a block variable to calculate how many of the strings in the comparison are the same. To demonstrate, the block is used directly, while the currentlocal variable is read-only for the block.

Nsarray *stringsarray = [Nsarray arraywithobjects:

@ "String 1", @ "string",//<-

@ "string" @ "string One" @ "Strîng",//<-

@ "Striñg",//<-

@ "String", nil];

Nslocale *currentlocale = [Nslocale Currentlocale];

__block Nsuinteger orderedsamecount = 0;

Nsarray *diacriticinsensitivesortarray = [Stringsarray sortedarrayusingcomparator:^ (ID string1, id string2) {

Nsrange string1range = nsmakerange (0, [string1 length]);

Nscomparisonresult Comparisonresult = [string1 compare:string2 options:nsdiacriticinsensitivesearch Range: String1range Locale:currentlocale];

if (Comparisonresult = = Nsorderedsame) {

orderedsamecount++;

}

return comparisonresult;

}];

NSLog (@ "Diacriticinsensitivesortarray:%@", Diacriticinsensitivesortarray);

NSLog (@ "Orderedsamecount:%d", orderedsamecount);

/*output:

Diacriticinsensitivesortarray: (

"String 02",

"String 1",

"String 11",

"String 12",

"String 21",

"Str/u00eeng 21",

"STRI/U00F1G 21"

)

Orderedsamecount:2

*/

Related concepts

Blocks provide a way to allow you to create a special body of functions that can be considered an expression in C and C derived languages such as o-c and C + +. In other languages, in order not to be confused with the blocks in C terminology, blocks are also called closure (domestic translation closures), where they are called blocks.

Function of block

A block is a collection of code within a row:

? As with functions, there are typed parameter lists

? Have a return result or declare a return type

? Can get the state within the same scope (the same scope that defines the block)

? You can modify the state (variable) of the same scope

? Sharing variables with other blocks in the same range

? Can continue to share and change variables within the same scope after a scope is released

You can even copy blocks and pass them on to other subsequent threads of execution. The compiler and the runtime are responsible for protecting the variables referenced by all blocks within the lifetime of the copy of all blocks. For C and C + +, the block is a variable, but for O-c, the block is still an object.

Use of blocks

Blocks typically represent small, self-contained snippets of code.

As a result, they are encapsulated as extra useful for working units that can be executed in parallel, either for traversal in the collection or as callbacks when other operations are complete.

Block instead of the traditional callback function has two meanings:

1. They allow code to be written to the nearest source in the invocation of the method implementation. And blocks are often used as parameters for some of the methods in the framework.

2. They allow access to local variables. In the case of threading, it is obviously simpler for the block to directly access local variables than the callback function needs to implant the required contextual information into the data structure.

Declaration and creation of blocks

Declaring block variables

A block variable references a block. Its declaration syntax is similar to a function pointer, except that you need to use ^ instead of *.

void (^blockreturningvoidwithvoidargument) (void);

Int (^blockreturningintwithintandchararguments) (int, char);

void (^arrayoftenblocksreturningvoidwithintargument[10]) (int);

The block supports variable parameters (... )。 If the block has no parameters, void is required to replace the entire argument list.

Blocks are type-safe, and by setting compilation options, the compiler checks for block calls, parameters, and return types. You can convert a block variable to a pointer type, but you cannot dereference it with *-the length of the block cannot be determined at compile time.

You can create a block type so that you can think of a block as a symbol that you can use repeatedly:

typedef float (^myblocktype) (float, float);

Myblocktype Myfirstblock =//...;

Myblocktype Mysecondblock =//...;

Creating blocks

The block begins with a ^ and ends. The following shows the definition of the BLOCK:

Int (^onefrom) (int);

Onefrom = ^ (int anint) {

return anInt-1;

};

If the return value type of the block is not explicitly declared, the return type may be inferred automatically from the block code. If the argument list is void and the return type relies on inference, you can omit void from the argument list. Otherwise, when a return statement exists in the block, they should be exactly matched (the necessary type conversions may be required).

Global block

You can define a block as a global variable and use it at the file level.

#import <stdio.h>

int globalint = 0;

Int (^getglobalint) (void) = ^{return globalint;};

Blocks and variables

This section describes the interaction between blocks and variables, including memory management.

Variable type

Inside the block code, the variable is processed into 5 different situations.

Just like a function, you can refer to 3 standard variables:

? Global variables, including static variables

? Global functions

? Local variables and parameters (within the block range)

In addition, the block supports two types of variables:

1. At the function level, is the __block variable. They are mutable within the block range, and are protected if the referenced blocks are copied to the heap.

2. Const imports.

In the method body, blocks can also refer to O-c instance variables, see Objects and block variables.

Using variables in a block has the following rules:

1. Accessible global variables within the same scope include static variables.

2. You can access the parameters passed to the block (like function arguments).

3. A stack (non-static) variable of the same range is treated as a const variable. Their values are similar to block expressions. When nesting blocks, values are taken from the nearest scope.

4. Variables declared within the same scope, if modified with the __block modifier, the value is mutable. The scope is affected by the change to the variable that includes other blocks within the same scope within the range. See "__block Storage Type" for details.

5. A local variable declared within the scope of a block (block), similar to a local variable in a function. Each call to the block causes the variables to be re-copied. These variables can be used as const or reference (by-reference) variables.

The following shows the use of local non-static variables:

int x = 123;

void (^printxandy) (int) = ^ (int y) {

printf ("%d%d/n", x, y);

};

Printxandy (456); Prints:123 456

Note that attempting to assign a value to X will result in an error:

int x = 123;

void (^printxandy) (int) = ^ (int y) {

x = x + y; Error

printf ("%d%d/n", x, y);

};

To change the value of x within a block, you need to use __block to modify the X. See "__block Storage Type".

__block Storage Type

You can specify whether an external variable is variable--readable and writable--by using the __block storage type modifier. __block storage is similar but differs from Register,auto and static storage types.

The __block variable is stored in the scope of the variable declaration, in all blocks within the same scope, and between the block copies. And this storage will be retained when the stack frame is released, as long as the copy of the declared block in the same frame is still alive (for example, being pushed into the stack for reuse). Multiple blocks within a specified scope can use shared variables at the same time.

As an optimization, block storage uses stack storage, just like the block itself. If you use a block_copy copy block (or send a copy message to a block in o-c), the variable is copied to the heap. Also, the address of the __block variable is then changed.

The __block variable has two restrictions: it cannot be a variable-length array, nor is it a struct containing a variable-length array of C99.

The following shows the use of the __block variable:

__block int x = 123; X lives in block storage

void (^printxandy) (int) = ^ (int y) {

x = x + y;

printf ("%d%d/n", x, y);

};

Printxandy (456); prints:579 456

X is now 579

The following shows the use of multiple types of variables in a block:

extern Nsinteger Counterglobal;

Static Nsinteger counterstatic;

{

Nsinteger localcounter = 42;

__block Char Localcharacter;

void (^ablock) (void) = ^ (void) {

++counterglobal;

++counterstatic;

Counterglobal = Localcounter; Localcounter Fixed at block creation

Localcharacter = ' a '; Sets Localcharacter in enclosing scope

};

++localcounter; Unseen by The Block

Localcharacter = ' B ';

Ablock (); Execute the Block

Localcharacter now ' a '

}

Object and block variables

Blocks provide support for o-c and C + + objects.

O-c Object

In the case of reference counting, when you reference a O-c object in a block, the object is retained. Even simply referencing an instance variable of this object is the same.

But for __block tagged object variables, it's not the same.

Note: In the case of garbage collection, if the variable is modified with both __weak and __block, the block may not necessarily guarantee that it is available.

If you use blocks in a method body, the memory management rules for object instance variables are subtle:

? If the instance variable is accessed through an object reference, self is retained;

? If the instance variable is accessed by means of a value reference, the variable is retained;

The following code illustrates these 2 scenarios:

Dispatch_async (Queue, ^{

Instancevariable is used by reference, self is retained

Dosomethingwithobject (instancevariable);

});

ID localvariable = instancevariable;

Dispatch_async (Queue, ^{

Localvariable is used by value, Localvariable was retained (not self)

Dosomethingwithobject (localvariable);

});

C + + objects

In general, you can use C + + objects in blocks. A reference to a member variable in a member function, as if it were a reference to a pointer, can be changed. If the block is copied, there are two kinds of results:

If there is a class of __block storage type, the class is a stack-based C + + object, typically using a copy constructor;

If you are using a stack-based C + + object in another block, it must have a const copy constructor. The C + + object uses this constructor for copying.

Block

When you copy a block, other blocks that it references may also be copied (starting at the top). If there is a block variable and a block is referenced in the block, the block is also copied.

When you copy a stack-based block, you get a new block. When copying a heap-based block, simply increase the number of retain and then return the result of the Copy method/function to the block.

Using blocks

Call of the Block

If you declare a block as a variable, you can use it as a function, for example:

Int (^onefrom) (int) = ^ (int anint) {

return anInt-1;

};

printf ("1 from-is%d", Onefrom (10));

Prints "1 from Ten is 9"

Float (^distancetraveled) (float, float, float) =

^ (float startingspeed, float acceleration, float time) {

float distance = (Startingspeed * time) + (0.5 * acceleration * time * time);

return distance;

};

float Howfar = distancetraveled (0.0, 9.8, 1.0);

Howfar = 4.9

However, the block is often passed as an argument to a function or method, so that inline (inline) blocks are used.

Use blocks as function parameters

In this case, the block declaration is not required. Simply implement it where you need to take it as a parameter. As shown below, Gsort_b is a function similar to the standard Gsort_r, which uses blocks for the last parameter.

Char *mycharacters[3] = {"Tomjohn", "George", "Charles Condomine"};

Qsort_b (mycharacters, 3, sizeof (char *), ^ (const void *l, const void *r) {

Char *left = * (char * *) L;

Char *right = * (char * *) R;

Return strncmp (left, right, 1);

});

Block implementation ends at "}"

Mycharacters is now {"Charles condomine", "George", Tomjohn "}

Note that the block is contained in the parameter list of the function.

The next example shows how to use blocks in the Dispath_apply function. Dispatch_apply's statement is:

void Dispatch_apply (size_t iterations, dispatch_queue_t queue, void (^block) (size_t));

This function submits the block to the dispatch queue for invocation. It has 3 parameters: the number of times to be manipulated, the queue to which the block is committed, and the block-the block has one parameter-the current number of traversal operations.

You can simply print out the index of the traversal operation with Dispatch_apply:

#include <dispatch/dispatch.h>

size_t count = 10;

dispatch_queue_t queue = Dispatch_get_global_queue (Dispatch_queue_priority_default, 0);

Dispatch_apply (count, queue, ^ (size_t i) {

printf ("%u/n", I);

});

Use the block as an argument

Cocoa provides a large number of ways to use blocks. There is no difference between using a block as an argument and using other types of parameters.

The following code determines the index of the first 5 elements in the array containing the given filter set.

Nsarray *array = [Nsarray arraywithobjects: @ "A", @ "B", @ "C", @ "a", @ "B", @ "Z", @ "G", @ "is", @ "Q", nil];

Nsset *filterset = [Nsset setwithobjects: @ "A", @ "Z", @ "Q", nil];

BOOL (^test) (id obj, Nsuinteger idx, BOOL *stop);

Test = ^ (ID obj, Nsuinteger idx, BOOL *stop) {

if (IDX < 5) {

if ([Filterset containsobject:obj]) {

return YES;

}

}

return NO;

};

Nsindexset *indexes = [array indexesofobjectspassingtest:test];

NSLog (@ "Indexes:%@", indexes);

/*output:

Indexes: <nsindexset:0x10236f0>[number of Indexes:2 (in 2 ranges), indexes: (0 3)]

*/

The following code determines whether a Nsset object contains the specified local variable, and if so, sets the other local variable (found) to Yes (and stops the search). Note that found is declared as a __block variable, and the block is declared within a row:

__block BOOL found = NO;

Nsset *aset = [Nsset setwithobjects: @ "Alpha", @ "Beta", @ "Gamma", @ "X", nil];

NSString *string = @ "Gamma";

[ASet enumerateobjectsusingblock:^ (id obj, BOOL *stop) {

if ([obj localizedcaseinsensitivecompare:string] ==nsorderedsame) {

*stop = YES;

Found = YES;

}

}];

At this point, found = = YES

Block replication

Generally, you don't need to copy blocks. You need to copy it only if you want to use it outside the scope of this block declaration. Copying will cause the block to move into the heap.

You can use the C function to release and copy blocks.

Block_copy ();

Block_release ();

For o-c, you can send Copy,retain and release (and autorelease) messages to the block.

To avoid memory leaks, a block_copy () always corresponds to a block_release (). Each copy/retain always has a corresponding release (or autorelease)-with the exception of garbage collection.

Avoidance of usage

A block declaration (ie ^{...} ) is the address of a local stack data structure (stack-local data structure), which represents the block. The local stack data structure is a compound statement enclosed by {}, so use should be avoided as follows:

void Dontdothis () {

void (^blockarray[3]) (void);//array of 3 block references

for (int i = 0; i < 3; ++i) {

Blockarray[i] = ^{printf ("Hello,%d/n", i);};

Wrong:the block literal scope is the ' for ' Loop

}

}

void Dontdothiseither () {

void (^block) (void);

int i = random ():

if (i > 1000) {

block = ^{printf ("Got I at:%d/n", i);};

Wrong:the block literal scope is the ' then ' clause

}

// ...

}

Debugging

You can set breakpoints within a block and step through it. In a GDB session, use the Invoke-block call block, for example:

$ invoke-block Myblock 10 20

If you need to pass a C string, you must enclose it in double quotation marks. For example, pass a string to the dosomethignwithstring block:

$ invoke-block dosomethingwithstring "/" This string/""

Original address: http://blog.csdn.net/kmyhy/article/details/6447287

IOS Block Detailed 3

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.