iOS学习之block

Block是C语言的扩充功能。带有自动变量(局部变量)的匿名函数。(不带有名称的函数)

非匿名函数:int func(int count);(声明了名称为func的函数)使用:int result =func(10);

匿名函数:



Block语法:

  1. ^返回值类型  参数列表    表达式
      1. ^int        ( int count)    {  return count+1};
  2. 省略返回值:
      1. ^        ( int count)    {  return count+1};
  3. 省略返回值和参数列表:
    1. ^        ()    {  return count+1};或者^{  printf(“1223”);}
  4. 将Block赋值为Block类型变量:

返回值类型(^块名)(参数类型)=^参数列表    表达式

Int    (^blk)    (int)            =^(int count){return count+1;};

按照调用函数的方式调用块对象变量就可以了:

int result = myBlock(4); // result是 28


  1. 在函数参数和返回值中使用block
  • 函数参数:void func(int (^blk)  (int)  ){

}

  • 返回值:int(^func())(int){

Return  ^ (int count)    {  return count+1}

}



2.使用typedef简化(定义别名)

定义: typedef int (^blk_t)(int);

  • 原本:void func(int (^blk)  (int)  ){
  • 简化:void func(blk_t blk)
  • 原本:int(^func())(int){
  • 简化:blk_t func()

原本:typedef int (^MyBlock)(int, int);

int (^minusBlock) (int, int) = ^(int a, int b){

return a - b;

};

int (^multiBlock) (int, int) = ^(int a, int b){

return a * b;

};

下面的代码更简洁

MyBlock minusBlock = ^(int a, int b){

return a - b;

};

        MyBlock multiBlock = ^(int a, int b){

return a * b;

};

  • (1)在类中,定义一个Block变量,就像定义一个函数;
  • (2)Block可以定义在方法内部,也可以定义在方法外部;
  • (3)只有调用Block时候,才会执行其{}体内的代码;

Block的几个特性:

  1. 自动变量值的截获

Int dmy=256;

Int val=10;

Const char *fmt=”val=%d\n”;

Void(^blk)(void)=^printf(fmt,val);};

Val=2;

Fmt=”these values were changed. Val=%d\n”;

blk();

Return 0;

}

输出结果:val=10;



2.修改外部变量(_block说明符)

//将Block定义在方法内部

int x = 100;

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

x = x+y;

printf("new x value is %d",x);

};

sumXAndYBlock(50);

出现编译错误:error: Variable is not assigning (missing __block type)

这时候给int x = 100;语句前面加上__block关键字即可

__block int x = 100;

这样在Block的{}体内,就可以修改外部变量了。



Block储存域:

程序占用内存分布的结构:

栈区(stack:由系统自动分配,一般存放函数参数值、局部变量的值等。由编译器自动创建与释放。其操作方式类似于数据结构中的栈,即后进先出、先进后出的原则。

堆区(heap:一般由程序员申请并指明大小,最终也由程序员释放。如果程序员不释放,程序结束时可能会由OS回收。

全局区/静态区:顾名思义,全局变量和静态变量存储在这个区域。只不过初始化的全局变量和静态变量存储在一块,未初始化的全局变量和静态变量存储在一块。程序结束后由系统释放。

文字常量区:这个区域主要存储字符串常量。程序结束后由系统释放。

程序代码区:这个区域主要存放函数体的二进制代码

int a = 0; // 全局初始化区

char *p1; // 全局未初始化区

main {

int b; // 栈

char s[] = "abc"; // 栈

char *p2; // 栈

char *p3 = "123456"; // 123456\0在常量区,p3在栈上

static int c =0; // 全局静态初始化区

p1 = (char *)malloc(10);

p2 = (char *)malloc(20); // 分配得来的10和20字节的区域就在堆区

strcpy(p1, "123456"); // 123456\0在常量区,这个函数的作用是将"123456" 这串字符串复制一份放在p1申请的10个字节的堆区域中。

// p3指向的"123456"与这里的"123456"可能会被编译器优化成一个地址。



Block的使用:



1.Block传值

将B界面的textField.text传给A界面的Label

A页面:RootViewControllers  B页面:DetailViewControllers

B页面:DetailViewController文件

#import <UIKit/Uikit.h>

typedef void (^DetailBlock)(NSString *);//block取别名。并且在参数列表中将需要传递的参数写形参

@interface DetailViewController : UIViewController

@property (nonatomic, copy) PassingValueBlock passingvalue;//设置block属性(注意使用copy)

@property (weak, nonatomic) UITextField *inputTF;

@end

- (IBAction)BtnAction:(id)sender {

//判断block是否为空

if (self. passingvalue) {

self. passingvalue (self.inputTF.text);

}

[self.navigationController popViewControllerAnimated:YES];

}//点击按钮到A界面

RootViewController.m

@property (strong, nonatomic) UILabel *textLabel;

-(void)handleButton: (NSString*)sender{

DetailViewController *detailViewController = [[DetailViewController alloc]init];

detailViewController.passingValue=^( NSString* str){

self. textLabel.text= str;}

[self.navigationController pushViewController:detailViewController animated:YES];

}



2.Block避免循环引用

由于我们很多行为会导致Block的copy,而当Block被copy时,会对block中用到的对象产生强引用(ARC下)或者引用计数加一(non-ARC下)。

如果遇到这种情况:

@property(nonatomic, readwrite, copy) completionBlock completionBlock;

self.completionBlock = ^ {

if (self.success) {

self.success(self.responseData);

}

}

};

对象有一个Block属性,然而这个Block属性中又引用了对象的其他成员变量,那么就会对这个变量本身产生强应用,那么变量本身和他自己的Block属性就形成了循环引用。在ARC下需要修改成这样:

@property(nonatomic, readwrite, copy) completionBlock completionBlock;

__weak typeof(self) weakSelf = self;

self.completionBlock = ^ {

if (weakSelf.success) {

weakSelf.success(weakSelf.responseData);

}

};

注1:iOS4.3之前版本就用__unsafe_unretained替代__weak

注2:如果是non-ARC环境下就将__weak替换为__block即可

时间: 2024-08-06 16:02:25

iOS学习之block的相关文章

ios学习笔记block回调的应用(一个简单的例子)

一.什么是Blocks      Block是一个C级别的语法以及运行时的一个特性,和标准C中的函数(函数指针)类似,但是其运行需要编译器和运行时支持,从ios4.0开始就很好的支持Block. 二.在ios开发中,什么情况下使用Block      Block除了能够定义参数列表.返回类型外,还能够获取被定义时的词法范围内的状态(比如局部变量),并且在一定条件下(比如使用__block变量)能够修改这些状态.此外,这些可修改的状态在相同词法范围内的多个block之间是共享的,即便出了该词法范围

ios学习之block初探

1. block概念 block是ios4.0+和Mac osX 10.6以后引进的对C语言的拓展,用来实现匿名函数的特性.所谓匿名函数,也称闭包函数,即允许创建一个临时的没有指定名称的函数.最经常用作回调函数(callback)参数的值,当然也有其他用法.比如说作为一个变量值来使用,具体用法将在后面介绍. 2. block定义: 在iOS中,使用脱字符"^"来声明一个block变量,block的内容包含在"{}"中的,并且和C语言一样用":"来

iOS学习之block总结及block内存管理(必看)

Block简介(copy一段) Block作为C语言的扩展,并不是高新技术,和其他语言的闭包或lambda表达式是一回事.需要注意的是由于Objective-C在iOS中不支持GC机制,使用Block必须自己管理内存,而内存管理正是使用Block坑最多的地方,错误的内存管理 要么导致return cycle内存泄漏要么内存被提前释放导致crash. Block的使用很像函数指针,不过与函数最大的不同是:Block可以访问函数以外.词法作用域以内的外部变量的值.换句话说,Block不仅 实现函数的

IOS学习之路--BLOCK

/* 1.定义block变量: 返回值类型 (^block变量名) (参数类型1, 参数类型2, ....); 2.给block变量赋值 block变量名 = ^(参数类型1 参数名称1, .....) { }; */ /* 1.设置动画属性 2.开始执行动画 3.动画执行完毕 block1 = ^{ 封装了动画开始执行前想做的事情 }; block2 = ^{ 封装了动画执行完毕后想做的事情 }; */ #import <Foundation/Foundation.h> //typedef

2015最新iOS学习线路图

iOS是由苹果公司开发的移动操作系统,以xcode为主要开发工具,具有简单易用的界面.令人惊叹的功能,以及超强的稳定性,已经成为iPhone.iPad 和iPod touch 的强大基础:iOS 内置的众多技术和功能让 Apple设备始终保持着遥遥领先的地位. iOS学习路线:http://www.mobiletrain.org/page/ios.html 课程分  类 课程模块 模块介绍 课程内容 Part1C语言 C语言和Objective-C语言 C语言 Mac系统及常用工具.进制:C数据

ios学习记录 day41 UI17 多线程

CPU(工厂) 进程(车间) 线程(工人) 一个进程代表一个应用程序 CPU总是运行一个进程,其它进程处于非运行状态.一个进程可以包含多个线程.线程与线程之间可以共享进程的内存区域. 打开一个应用程序,系统会给我们创建一个线程,称为主线程 管理主界面的UI与内部循环机制(与界面相关的东西必须放在主线程中!!!) 压力比较大且会造成线程阻塞(界面卡),因此我们通过创建子线程来对主线程进行分压. 什么时候用多线程 1.网络请求(同步的) 2.文件读写(少) 3.大数据计算(冒泡) 4.数据库sele

iOS学习笔记(3)— 屏幕旋转

iOS学习笔记(3)— 屏幕旋转 一.屏幕旋转机制: iOS通过加速计判断当前的设备方向和屏幕旋转.当加速计检测到方向变化的时候,屏幕旋转的流程如下: 1.设备旋转时,系统接收到旋转事件. 2.系统将旋转事件通过AppDelegate通知当前的主Window. 3.window通知它的rootViewController. 4.rootViewController判断所支持的旋转方向,完成旋转. iOS系统中屏幕旋转事件没有像触碰事件那样进行hitTest,所以只有rootViewControl

IOS学习笔记 -- 多线程

多线程1.多线程的原理 1>.同一时间,CPU只能处理1条线程,只有1条线程在工作(执行) 2>.多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换) 3>.如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象如果线程非常非常多,会发生: 1>.CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源 2>.每条线程被调度执行的频次会降低(线程的执行效率降低) 2.多线程的优缺点 1>.多线程的优点 能适当提高程序的执行效率 能适当提高资源

IOS学习之十七:Grand Central Dispatch(GCD)编程基础

IOS学习之十七:Grand Central Dispatch(GCD)编程基础 有过编程经验的人,基本都会接触到多线程这块. 在java中以及Android开发中,大量的后台运行,异步消息队列,基本都是运用了多线程来实现. 同样在,在ios移动开发和Android基本是很类似的一种模型. 但是很多时候,在应用开发中,我们会发现本身并没有自己编码去处理一些并发的事件,去开辟新的子线程等等. (虽然一般的调用sdk发起一个网络请求,系统都是会默认给你新起一个线程去处理的). 整个程序看上去基本就是