Objective-C 고급 프로그래밍 (2) 블록

14935 단어

1. 블락 소개


자동 변수가 있는 익명 함수는 실질적으로 Objective-C의 대상이다.

1. 블록 구문

^ returnType paramType expression
^ int (int count) {return count++;}
^ (int count) {return count++;}
^ void (void)  {printf("Hello Block");}
^ {printf("Hello Block");}

2. 블록 선언

//  
int (*funcptr) (int)
// Block 
int (^block) (int)
// Block 
void func (int (^block) (int))
// Block 
@property (nonatomic, copy) void(^block)(void);
// typedef
typedef int (^block) (int)

2. 블록 실질


1. 변환 소스 코드

//  
clang -rewrite-objc [fileName]
xcrun -sdk iphoneos clang -rewrite-objc ViewController.m
xcrun -sdk iphonesimulator clang -rewrite-objc ViewController.m

소스 코드
#import 

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        void (^JDPBlock) (void) = ^{printf("Hello, Block!");};
        JDPBlock();
    }
    return 0;
}

바꾸다
struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
printf("Hello, Block!");}

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        void (*JDPBlock) (void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
        ((void (*)(__block_impl *))((__block_impl *)JDPBlock)->FuncPtr)((__block_impl *)JDPBlock);
    }
    return 0;
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };

이해하다
struct A
struct B, init b
function f(x)

struct X {
A,
B,
constructor(F,B, Flag)
}

x = X(f, b)
x.f(x)

2, 블락 캡처 자동 변수


소스 코드
#import 

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSInteger integer = 1;
        void (^JDPBlock1) (void) = ^{printf("%lu
", integer);}; integer = 2; JDPBlock1(); } return 0; }

바꾸다
struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr;
};
struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  NSInteger integer;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, NSInteger _integer, int flags=0) : integer(_integer) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  NSInteger integer = __cself->integer; // bound by copy
printf("%d", integer);}

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        NSInteger integer = 1;
        void (*JDPBlock1) (void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, integer));
        integer = 2;
        ((void (*)(__block_impl *))((__block_impl *)JDPBlock1)->FuncPtr)((__block_impl *)JDPBlock1);
    }
    return 0;
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };

이해하다
struct A
struct B, init b
function f(x) {
i = x.i
}

struct X {
A,
B,
I,
constructor(F, B, I, Flag)
}

i = 1
x = X(f, b, i)
i = 2;
x.f(x)

1. 블록 문법 표현식에 사용된 자동 변수는 구성원 변수로 구조체에 추가됩니다.2. 블록 문법 표현식에 사용되지 않은 자동 변수는 추가되지 않습니다.3. 블록이 자동 변수 값을 캡처하는 것은 블록을 정의할 때 블록 문법 표현식에 사용된 자동 변수 값이 블록의 구조체 실례에 저장된다는 것을 의미한다.4. 블록 정의 후 자동 변수 값의 수정은 블록 내의 구성원 변수의 값에 영향을 주지 않는다.

3、__block 변수


소스 코드
#import 

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        __block NSInteger integer = 1;
        void (^JDPBlock1) (void) = ^{
            integer = 3;
            printf("%lu
", integer); }; integer = 2; JDPBlock1(); } return 0; } 3

바꾸다
struct __Block_byref_integer_0 {
  void *__isa;
__Block_byref_integer_0 *__forwarding;
 int __flags;
 int __size;
 NSInteger integer;
};

struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr;
};
struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref_integer_0 *integer; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_integer_0 *_integer, int flags=0) : integer(_integer->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref_integer_0 *integer = __cself->integer; // bound by ref

            (integer->__forwarding->integer) = 3;
            printf("%lu
", (integer->__forwarding->integer)); } static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->integer, (void*)src->integer, 8/*BLOCK_FIELD_IS_BYREF*/);} static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->integer, 8/*BLOCK_FIELD_IS_BYREF*/);} static struct __main_block_desc_0 { size_t reserved; size_t Block_size; void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*); void (*dispose)(struct __main_block_impl_0*); } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0}; int main(int argc, const char * argv[]) { /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; __attribute__((__blocks__(byref))) __Block_byref_integer_0 integer = {(void*)0,(__Block_byref_integer_0 *)&integer, 0, sizeof(__Block_byref_integer_0), 1}; void (*JDPBlock1) (void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_integer_0 *)&integer, 570425344)); (integer.__forwarding->integer) = 2; ((void (*)(__block_impl *))((__block_impl *)JDPBlock1)->FuncPtr)((__block_impl *)JDPBlock1); } return 0; } static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };

이해하다
struct Q
struct A
struct B, init b
function f(x) {
q = x.q
q.i = 3
}

struct X {
A,
B,
Q,
constructor(F, B, Q, flag)
}

q = constructor(0, &q, 0, size(Q), 1)
x = X(f, b, q)
q.i = 2;
x.f(x)

3. 블록 유형


1, 블록 및block 변수의 실질은 창고에서 생성된 구조체의 실례이다.2、블락의 유형은NSConcreteGlobalBlock、_NSConcreteStackBlock、_NSConcreteMallocBlock 은 각각 데이터 영역, 스택, 스택에 있습니다.3. 블록이 자동 변수를 캡처하지 않을 때 블록을 프로그램의 데이터 영역에 설정할 수 있다.4、__block 구조체, 구성원 변수forwarding은 를 막론하고 실현할 수 있다Block 변수가 창고에 설정되어 있거나 쌓여 있을 때 같은 에 정확하게 접근할 수 있습니다block 변수.5. ARC가 유효할 때 컴파일러는 자동으로 블록을 창고에서 더미로 복사합니다. 언제 자동으로 복사합니까?5.1 블록의copy 실례 방법을 호출할 때 5.2, 블록이 함수로 되돌아올 때 5.3, 블록에 값을 부여할 때strong 수식자의 변수는 5.4, 방법명에 usingBlock이 포함된 코코아 프레임워크 방법이나 GCD의 API에서 Block을 전달할 때 6, 방법이나 함수에 있는 매개 변수에서 Block을 전달할 때 컴파일러가 자동으로 복사하는지 판단할 수 없으며 코코아 usingBlock과 GCD를 제외한다.
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        void (^JDPBlock) (void) = ^{printf("Hello, Block!");};
        NSLog(@"%@", JDPBlock);
    }
    return 0;
}

<__nsglobalblock__:>
#import 

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSInteger i = 1;
        void (^JDPBlock) (void) = ^{printf("%lu", i);};
        NSLog(@"%@", JDPBlock);
    }
    return 0;
}

// MRC
<__nsstackblock__:>
// ARC
<__nsmallocblock__:>

4.블록&대상


1. 블락 포획 대상


소스 코드
#import 

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSMutableArray *array = [[NSMutableArray alloc] init];
        void (^JDPBlock) (void) = ^{NSLog(@"%@", array);};
        JDPBlock();
    }
    return 0;
}

바꾸다
struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  NSMutableArray *array;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, NSMutableArray *_array, int flags=0) : array(_array) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  NSMutableArray *array = __cself->array; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_yp_b0w71dps58s5rncj_t1znym80000gn_T_main_6313b8_mi_0, array);}
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->array, (void*)src->array, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->array, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
  void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};
int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        NSMutableArray *array = ((NSMutableArray *(*)(id, SEL))(void *)objc_msgSend)((id)((NSMutableArray *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("alloc")), sel_registerName("init"));
        void (*JDPBlock) (void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, array, 570425344));
        ((void (*)(__block_impl *))((__block_impl *)JDPBlock)->FuncPtr)((__block_impl *)JDPBlock);
    }
    return 0;
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };

이해하다
struct A
struct B, init b
function f(x) {
NSMutableArray *array = x.array;
NSLog(@"%@", array);
}

struct X {
A,
B,
NSMutableArray *array;
constructor(F, B, NSMutableArray *array, Flag)
}

NSMutableArray *array = [[NSMutableArray alloc] init];
x = X(f, b, array)
x.f(x)

2、__block 손질 객체


소스 코드
#import 

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        __block NSMutableArray *array = [[NSMutableArray alloc] init];
        void (^JDPBlock) (void) = ^{NSLog(@"%@", array);};
        JDPBlock();
    }
    return 0;
}

바꾸다
struct __Block_byref_array_0 {
  void *__isa;
__Block_byref_array_0 *__forwarding;
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);
 void (*__Block_byref_id_object_dispose)(void*);
 NSMutableArray *array;
};

struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr;
};
struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref_array_0 *array; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_array_0 *_array, int flags=0) : array(_array->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref_array_0 *array = __cself->array; // bound by ref
NSLog((NSString *)&__NSConstantStringImpl__var_folders_yp_b0w71dps58s5rncj_t1znym80000gn_T_main_b13376_mi_0, (array->__forwarding->array));}
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->array, (void*)src->array, 8/*BLOCK_FIELD_IS_BYREF*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->array, 8/*BLOCK_FIELD_IS_BYREF*/);}

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
  void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};
int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        __attribute__((__blocks__(byref))) __Block_byref_array_0 array = {(void*)0,(__Block_byref_array_0 *)&array, 33554432, sizeof(__Block_byref_array_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, ((NSMutableArray *(*)(id, SEL))(void *)objc_msgSend)((id)((NSMutableArray *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("alloc")), sel_registerName("init"))};
        void (*JDPBlock) (void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_array_0 *)&array, 570425344));
        ((void (*)(__block_impl *))((__block_impl *)JDPBlock)->FuncPtr)((__block_impl *)JDPBlock);
    }
    return 0;
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };

이해하다
struct Q
struct A
struct B, init b
function f(x) {
q = x.q
NSLog(@"%@", x.array);
}

struct X {
A,
B,
Q;
constructor(F, B, Q, Flag)
}

NSMutableArray *array = [[NSMutableArray alloc] init];
q = Q(0, &q, 0, sizeof(Q), array);
x = X(f, b, q)
x.f(x)

5. 블록 순환 참조


MRC에서Block 수식자는 Block의 순환 인용을 피하는 데 사용됩니다.이는 Block이 스택에서 스택으로 복사할 때 Block이 사용하는 변수가 이(가) 첨부되어 있기 때문입니다.block 수식자의 id 형식이나 대상 형식의 자동 변수입니다.retain에 의해 변경되지 않습니다.Block에서 사용하는 변수가 없음인 경우block 수식자의 id 형식이나 대상 형식의 자동 변수는retain에 의해 변경됩니다.

좋은 웹페이지 즐겨찾기