The last article tells the simple and practical block, this one is the most often and relatively simple usage of the block, personally think that this is a block relative to other pages of the use of a better way. Also, by the way, summarize some of the points of attention to block's understanding over the next two days.
对于页面传值这种情况,我们一般在程序里有几种处理的方法。1、设置Delegate2、使用NotificationCenter3、使用Block4、KVO页面传值5、NSUserDefault等文件存储机制做中间介质传递(但比较浪费,用在页面传值上几率很低)
This blog I only talk about the block of the general page value of the use of the method and explore its principle. Words don't say much directly on the code: method and use
///On the first page:#Import "ViewController.h"#Import "NextVC.h"@interfaceViewcontroller () <nextvcdelegate>{UILabel *_useblocktext;//Display textUIButton *_tonextvc_block;//Go to the next page}@end///The button and the display label are placed on the view, omitted here. Specific to the end to see my demo source/** * @brief button event: Go to the next page and specify the block callback function */- (void) Tonext_block {NEXTVC *next = [[NEXTVC alloc]init];//Specify callback functionNext. Nextvcblock = ^ (NSString *text) {_useblocktext.text = [NSString stringwithformat:@"I ' m from Block:%@", text]; }; [Self.navigationcontroller Pushviewcontroller:next animated:yes];}
//second page//.h Header File@interfaceNextvc:uiviewcontroller@property(nonatomic, copy)void(^nextvcblock) (NSString *text);@end//.M Implementation file#Import "NextVC.h"@interfaceNEXTVC () {UIButton *_useblock; Uitextfield *_text;}///The button and the display label are placed on the view, omitted here. Specific to the end to see my demo source/** * @brief page value using block * /- (void) Tranferuseblock {//Pass Value Section if(self.) Nextvcblock) self. Nextvcblock (_text.text); [Self.navigationcontroller Popviewcontrolleranimated:yes];}@end
The effect here is roughly the following:
Transfer Process Research
Define a block in a class and how to get the message changed in another class.
流程分析:通过打断点以及尝试总算明白了block在页面间传值的一个流程。我们在第二个页面中声明了一个block类型的属性NextVCBlock:@property (nonatomic, copy) void(^NextVCBlock)(NSString *text);而我们在第一个页面实例化了NextVC的对象:NextVC *next = [[NextVC alloc]init];并且实现了这个NextVCBlock:next.NextVCBlock = ^(NSString *text){ _useBlockText.text = ...;};当我们在第二个页面中调用了该Block:self.NextVCBlock(_text.text);这会自动把Block复制到堆上,然后触发了next.NextVCBlock内部实现代码。
Use permission issues for external variables
To optimize storage, the block variable and the block itself are stored on the stack at the beginning, similar to local variables. Local variables defined in the function body are usually stored in the stack, and global variables/static variables are generally placed on the heap. The block can be readonly when referencing an external variable. can only read and not change, if you want to modify the local variables, you should use __block to decorate the variable. Like __block int sum = 10;
原因分析:这是因为block事实上是指向一个结构体的指针,其内部的代码会被声称一个函数。内部代码在使用外部的变量sum时,传递的只是一个值,而当使用了__block修饰后,传递过来的则是变脸sum的地址。
Circular reference issues (Memory recycle)
For example, in the function we have just above - (void)toNext_Block , if we add a sentence NSLog(@"%@",next.description); , that is:
NextVC *next = [[NextVC alloc]init]; next.NextVCBlock = ^(NSString *text){ _useBlockText.text = [NSStringstringWithFormat:@"I‘m from block : %@", text]; NSLog(@"%@",next.description); };
In this case, a circular reference is generated.
原因分析:因为当这个函数生命周期结束的时候,系统想释放next,但释放next首先要释放NextVCBlock这个变量.而我们在NextVCBlock中又强引用了next这个对象。主要原因是所有局部变量在默认情况下的修饰符都为__strong。解决方法:你以为这里只需要在NextVC前加__weak即可解决吗?事实却不是如此,因为如果我们使用:__weak NextVC *next = [[NextVC alloc]init];next一声明马上就被系统自动回收了,所以后面的使用是不执行的。最好的解决方法应该是:NextVC *next = [[NextVC alloc]init];__weak typeof(NextVC) *weakNext = next;然后使用weakNext代替next:weakNext.NextVCBlock = ^(NSString *text){ _useBlockText.text = [NSString stringWithFormat:@"I‘m from block : %@", text]; NSLog(@"I‘m weakNext == %@",weakNext.description);};
In the ARC environment, blocks are automatically copied from the stack to the heap in the following situations:
(from a post on the internet said)
1. The Copy method is executed
2, as the return value of the method
3. Assign the block to an ID object or a member variable of block type by the __strong modifier
4, when the method name contains Usingblock cocoa Framework method or GDC API to pass the time (which I do not quite understand)
这里有个知识点可以扩展下: 栈的优点是创建速度快、管理简单。有严格的生命周期。 因为是先进后出队列,所以效率高也不会有碎片问题。由系统释放。 堆是动态分配的,可由程序员自行控制释放。 但是是根据指针指向一串不连续的内存,空间比较大但频繁的new/release肯定会造成内存空间的更加不连续,即内存碎片化。效率上: 堆:char *s1 = "Hellow Word";是在编译时就确定的; 栈:char s1[] = "Hellow Word"; 是在运行时赋值的; 再比如NSString与NSMutableString的对象,前者是放在栈中,后者是放在堆上。创建方法也不同,比如 NSString *str = @"hello"; NSMutableString *mutableStr = [[NSMutableString alloc] initWithString:@"hello"]; 前者是直接在栈上创建,后者是需要分配空间再进行初始化。
Demo Address: Https://github.com/ChenNan-FRAM/TransferDataDemo
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
The use of block--the method of page transfer and its exploration