XB_block(3)

1.__block的内存管理

我们已经知道,__block修饰符会把auto变量包装成一个对象

  • 1.当block在栈上时,并不会对__block变量产生强引用
  • 2.当block被copy到堆时,会调用block内部的copy函数,copy函数内部会调用_Block_object_assign函数, _Block_object_assign函数会对__block变量形成强引用(retain),注意这里是__block变量,也就是类似struct __Block_byref_age_这个的结构体,而不是内部的age。

 

 如果Block0先使用了__block变量,会将__block变量复制到堆空间,Block1后使用__block变量,不会再次复制__block到堆空间。

  • 3.当block从堆中移除时,会调用block内部的dispose函数,dispose函数会调用_Block_object_dispose函,_Block_object_dispose函数会自动释放引用的__block变量(release)。
  • 4.关于__block的__forwarding指针

也就解释了,在block外部调用栈上的__block变量的时候,其实访问了堆中的__block变量

  •  

2.对象类型的auto变量与__block修饰的变量对比

  • 当block在栈上的时候对它们都不会产生强引用
  • 当block拷贝到堆上时,都会通过copy函数来处理它们

     1.>  __block变量(假设变量名叫做a),底层处理如下:

_Block_object_assign((void*)&dst->a, (void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/); 

      2.>对象类型的auto变量(假设变量名叫做p) ,底层处理如下:

_Block_object_assign((void*)&dst->p, (void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);
  • 当block从堆上移除时,都会通过dispose函数来释放它们

     1.>__block变量(假设变量名叫做a),底层处理如下:

  • _Block_object_dispose((void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);

     2.>对象类型的auto变量(假设变量名叫做p),底层处理如下:

_Block_object_dispose((void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);

其实就是BLOCK_FIELD的不同

3.被__block修饰的对象类型的auto变量

  • 当__block变量在栈上时,不会对指向的对象产生强引用
  • 当__block变量被copy到堆时,会调用__block变量内部的copy函数,copy函数内部会调用_Block_object_assign函数, _Block_object_assign函数会根据所指向对象的修饰符(__strong、__weak、__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用(注意:这里仅限于ARC时会retain,MRC时不会retain,这里的强弱引用是指向的对象,而不是__block变量,__block变量一直是强引用的,与修饰符无关)。

   强引用下生成的底层结构

  __block Person *person = [[Person alloc] init];;
        person.age = 10;
        MyBlock block = ^{
            NSLog(@"age is %d", person.age);
        };


//xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m  生成C++文件
struct __Block_byref_person_0 {
  void *__isa;
__Block_byref_person_0 *__forwarding;
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);
 void (*__Block_byref_id_object_dispose)(void*);
 Person *__strong person;
};

弱引用下生成的底层结构

Person *person = [[Person alloc] init];
        __block __weak typeof(person) weakPerson = person;
        person.age = 10;
        MyBlock block = ^{
            NSLog(@"age is %d", weakPerson.age);
        };



//xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m  生成C++文件
typedef void(*MyBlock)(void);
struct __Block_byref_weakPerson_0 {
  void *__isa;
__Block_byref_weakPerson_0 *__forwarding;
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);
 void (*__Block_byref_id_object_dispose)(void*);
 Person *__weak weakPerson;
};

 

  • 当__block变量从堆上移除时,会调用block内部的dispose函数,dispose函数会调用_Block_object_dispose函,_Block_object_dispose函数会自动释放引用的__block变量(release)。

注意:这里与被__block修饰的非对象类型的auto变量的唯一的区别就是在copy到堆上的时候,会根据对象修饰符对__block变量中的引用对象做出强弱引用操作。

3.解决循环引用

1.在ARC环境下使用__weak、__unsafe_unretained修饰符解决,MRC环境下使用__unsafe_unretained修饰符,不能使用__weak

2.在ARC和MRC环境下都可以使用__block解决,但条件是必须要调用block

原理如下

总结:

对于引用对象类型的__block变量,一定要搞清楚__block变量与引用的对象不是同一个东西,__block变量持有引用的对象。

#include <reg52.h> #include <intrins.h> sbit DATA_PIN = P1^0; sbit CLOCK_PIN = P1^1; sbit LATCH_PIN = P1^2; sbit KEY_LEFT = P3^1; sbit KEY_RIGHT = P3^4; sbit KEY_ROT = P3^5; sbit KEY_DOWN = P3^6; #define MAP_WIDTH 8 #define MAP_HEIGHT 8 #define FALL_DELAY 500 unsigned char game_map[MAP_HEIGHT] = {0}; unsigned char display_buffer[MAP_HEIGHT] = {0}; struct { unsigned char type; unsigned char rotation; char x; char y; } current_block; unsigned int fall_timer = 0; unsigned int game_speed = FALL_DELAY; bit game_over = 0; unsigned int score = 0; unsigned char code SHAPES[7][4][4] = { {{0x0F, 0x00, 0x00, 0x00}, {0x04, 0x04, 0x04, 0x04}, {0x0F, 0x00, 0x00, 0x00}, {0x04, 0x04, 0x04, 0x04}}, {{0x0E, 0x04, 0x00, 0x00}, {0x04, 0x06, 0x04, 0x00}, {0x04, 0x0E, 0x00, 0x00}, {0x04, 0x0C, 0x04, 0x00}}, {{0x08, 0x0C, 0x00, 0x00}, {0x06, 0x04, 0x04, 0x00}, {0x0C, 0x08, 0x00, 0x00}, {0x04, 0x04, 0x06, 0x00}}, {{0x04, 0x0C, 0x00, 0x00}, {0x04, 0x04, 0x06, 0x00}, {0x0C, 0x04, 0x00, 0x00}, {0x06, 0x04, 0x04, 0x00}}, {{0x06, 0x06, 0x00, 0x00}, {0x06, 0x06, 0x00, 0x00}, {0x06, 0x06, 0x00, 0x00}, {0x06, 0x06, 0x00, 0x00}}, {{0x06, 0x0C, 0x00, 0x00}, {0x04, 0x06, 0x02, 0x00}, {0x06, 0x0C, 0x00, 0x00}, {0x04, 0x06, 0x02, 0x00}}, {{0x0C, 0x06, 0x00, 0x00}, {0x02, 0x06, 0x04, 0x00}, {0x0C, 0x06, 0x00, 0x00}, {0x02, 0x06, 0x04, 0x00}} }; void send_byte(unsigned char dat) { unsigned char i; for(i=0; i<8; i++) { DATA_PIN = dat & 0x80; CLOCK_PIN = 1; _nop_();_nop_(); CLOCK_PIN = 0; dat <<= 1; } } void refresh_display() { static unsigned char row = 0; LATCH_PIN = 0; send_byte(~display_buffer[row]); send_byte(1 << row); LATCH_PIN = 1; row = (row + 1) % MAP_HEIGHT; } void timer1_init() { TMOD = 0x11; TH1 = 0xFC; TL1 = 0x18; ET1 = 1; TR1 = 1; EA = 1; } bit check_collision() { unsigned char i, j; unsigned char shape_data; for(i=0; i<4; i++) { if(current_block.y + i >= MAP_HEIGHT) return 1; shape_data = SHAPES[current_block.type][current_block.rotation][i]; for(j=0; j<4; j++) { if(shape_data & (0x08 >> j)) { int map_x = current_block.x + j; int map_y = current_block.y + i; if(map_x < 0 || map_x >= MAP_WIDTH) return 1; if(map_y >= MAP_HEIGHT) return 1; if(map_y >= 0 && (game_map[map_y] & (0x80 >> map_x))) return 1; } } } return 0; } void new_block() { current_block.type = rand() % 7; current_block.rotation = 0; current_block.x = 3; current_block.y = 0; if(check_collision()) { game_over = 1; } } void fix_block() { unsigned char i, j,shape_data; for(i=0; i<4; i++) { if(current_block.y + i < 0) continue; shape_data = SHAPES[current_block.type][current_block.rotation][i]; for(j=0; j<4; j++) { if(shape_data & (0x08 >> j)) { int map_x = current_block.x + j; int map_y = current_block.y + i; if(map_x >=0 && map_x < MAP_WIDTH && map_y >=0 && map_y < MAP_HEIGHT) { game_map[map_y] |= (0x80 >> map_x); } } } } } void clear_lines() { unsigned char y, y2,x; bit full_line; for(y=0; y<MAP_HEIGHT; y++) { full_line = 1; for( x=0; x<MAP_WIDTH; x++) { if(!(game_map[y] & (0x80 >> x))) { full_line = 0; break; } } if(full_line) { score += 10; if(game_speed > 100) game_speed -= 10; for(y2=y; y2>0; y2--) { game_map[y2] = game_map[y2-1]; } game_map[0] = 0; } } } void update_display() { unsigned char i, j,x,y,shape_data; for(i=0; i<MAP_HEIGHT; i++) { display_buffer[i] = game_map[i]; } for(i=0; i<4; i++) { y = current_block.y + i; if(y >= MAP_HEIGHT || y < 0) continue; shape_data = SHAPES[current_block.type][current_block.rotation][i]; for(j=0; j<4; j++) { x = current_block.x + j; if(x >=0 && x < MAP_WIDTH && (shape_data & (0x08 >> j))) { display_buffer[y] |= (0x80 >> x); } } } } void move_block(char dx, char dy) { current_block.x += dx; current_block.y += dy; if(check_collision()) { current_block.x -= dx; current_block.y -= dy; if(dy > 0) { fix_block(); clear_lines(); new_block(); } } } void rotate_block() { unsigned char old_rotation; old_rotation = current_block.rotation; current_block.rotation = (current_block.rotation + 1) % 4; if(check_collision()) { current_block.rotation = old_rotation; } } void scan_keys() { static bit key_flag = 0; if(!key_flag) { if(!KEY_LEFT) { move_block(-1, 0); key_flag = 1; } else if(!KEY_RIGHT) { move_block(1, 0); key_flag = 1; } else if(!KEY_DOWN) { move_block(0, 1); key_flag = 1; } else if(!KEY_ROT) { rotate_block(); key_flag = 1; } } else { if(KEY_LEFT && KEY_RIGHT && KEY_DOWN && KEY_ROT) { key_flag = 0; } } } void els() { unsigned char i; timer1_init(); new_block(); scan_keys(); while(1) { if(game_over) { for( i=0; i<MAP_HEIGHT; i++) { display_buffer[i] = (i % 2) ? 0xFF : 0x00; } continue; } if(fall_timer >= game_speed) { move_block(0, 1); fall_timer = 0; } scan_keys(); update_display(); } } void timer1_isr() interrupt 1 { TH1 = 0xFC; TL1 = 0x18; refresh_display(); fall_timer++; }程序一直在扫描矩阵
最新发布
11-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值