OBJ-C block + protocol 学习笔记

本文深入讲解了Block(块)的概念及其在C级别的语法和运行机制, 包括定义格式、类型定义、访问外部变量等内容,并介绍了Protocol(协议)的基本概念、使用方法以及@required和@optional关键字的作用。
================================================================
                                             block + protocol
===============================================================


block类型是一个C级别的语法和运行机制。  


------------------------------------------------


block变量的定义格式:


int multiplier = 7;
int(^myBlock)(int) = ^(int num){return num * multiplier;};


^符号将myBlock声明为一个块对象;
myBlock是块对象,返回整型值;
它有一个参数,参数的类型也是整型值;
参数的名称是num; 


-----------------------------------------------


无参无返回值:void(^变量名)() = ^(){代码块语句;};
有参无返回值:void(^变量名)(参数类型及个数) = ^(形参列表){代码块语句;};


--------------------------------------------------


block的typedef


利用typedef定义block类型(和指向函数的指针很像)


例如:


typedef int(^Block)(int) 是给返回值是int类型并且有一个int类型参数的block语句块起别名,别名为Block。


------------------------------------------------------------


block访问外部变量


当定义block的时候,block会把外部变量以const的方式复制一份,然后存放到block所在的内存中。
注意:block中访问的外部变量,其地址与外部变量的地址不同;


如果在block内部定义的变量,是存到栈区的。


给block的外部变量前面加上__block修饰,则这个变量可以在block内部修改。而且,在修改之后,在block里被修改的变量,到block外部访问使用时,其值和地址都变成了block修改之后的。


-----------------------------------------------------------------


block分为3种:全局block,栈block,堆block;


---------------------------------------------------


block作为函数的返回值


步骤:


1.使用typedef给block类型起个别名;
2.用新定义的类型作为函数的返回值;
3.定义block变量接收函数返回的结果;
4.执行block;


---------------------------------------------------


block使用技巧及注意


助记符:inlineblock可以调出block的格式;




==================================================================================


protocol概念及基本使用


protocol基本概念


1.定义协议:


@protocol 协议名称<NSObject>
//方法声明列表;
@end


注意:协议默认采纳NSObject的协议




2.采纳协议:


(1)类遵守协议         @interface 类名:父类名<协议名称1,协议名称2>
                        @end




(2)协议遵守协议


-------------------------------------------------------------------


protocol的使用注意


1.Protocol:就一个用途,用来声明一大堆的方法(不能声明成员变量),不能写实现;
2.只要某个类遵守了这个协议,就拥有了这个协议中的所有方法声明;
3.只要父类遵守了某个协议,那么子类也遵守;
4.protocol声明的方法可以让任何类去实现;
5.OC不能继承多个类(单继承)但是能遵守多个协议;
6.基协议:<NSObject>是基协议,是最根本最基本的协议,其中声明了很多最基本的方法;
7.协议可以遵守协议,一个协议遵守了另一个协议,就可以拥有另一份协议中的方法声明;


------------------------------------------------------------------


@required和@optional


这两个关键字的作用:
@required是必须要实现的方法,默认值。如果不实现,编译器会发出警告;
@optional是可选择实现的方法;


------------------------------------------------------------------


protocol类型限制:


1.给id类型增加限制


例如:


id<myProtocol> obj = mm; 这句话的意思是:如果等号右边的对象想赋值给obj,那么这个对象必须遵守myProtocol这个协议,即mm所在的类要遵守myProtocol这个协议。


------------------------------------------------------------------


id和instancetype的区别


1.instancetype只能作为函数或者方法的返回值;
2.id能作为方法或者函数的返回值、参数类型、也能用来定义变量;
3.instancetype能精确地限制返回值的具体类型;


-----------------------------------------------------------------


protocol代理设计模式引入


代理模式概念:传入的对象,代替当前类完成了某个功能,称为代理模式;


---------------------------------------------


协议的循环引入问题


即不用#import,用@protocol。和@class的用法差不多。
<think>好的,我现在需要分析用户提供的这个函数`static void UI_WindowPrintEditJobAutoSize(void)`。首先,我会通读代码,理解它的结构和目的。 函数开头声明了一个`UI_PRINT_OBJ_DATA`类型的指针`obj`,初始化为NULL。然后检查`s_PrintEditJob`是否存在,如果不存在就直接返回,这说明函数可能在处理无效指针时做了保护,避免空指针异常。 接下来,函数将`s_PrintEditJob`的宽度`w`和高度`h`都设为0。这可能是为了重置之前的尺寸,重新计算当前的实际尺寸。 然后进入一个循环,遍历`s_PrintEditJob->obj_list`链表中的每个`obj`。对于每个对象,比较当前`s_PrintEditJob->w`和`obj->x + obj->w`,如果对象的右边界(x坐标加宽度)更大,就更新`s_PrintEditJob->w`。同样,高度方面也是类似的处理,比较下边界(y坐标加高度)来更新`s_PrintEditJob->h`。这说明这个函数的作用是计算所有对象中最右和最下的位置,从而确定整个作业区域的总尺寸。 最后,用`Log`函数输出计算后的尺寸,方便调试或记录。 接下来需要验证我的理解是否正确。比如,确认循环遍历每个对象是否正确,是否正确更新了最大宽度和高度。同时检查是否有遗漏的情况,比如对象可能为空或者链表遍历是否正确。此外,还要注意变量命名是否符合常见规范,比如`obj_list`可能是一个链表结构,通过`next`指针遍历。 可能的疑问点:为何在循环开始前将`w`和`h`设为0?是否应该初始化为链表第一个对象的尺寸?但根据逻辑,如果没有任何对象,尺寸保持为0,这也是合理的。而当有对象时,每次循环都会更新到最大的值,初始0会被覆盖,所以没问题。 另外,函数是静态的,说明可能只在当前文件内使用,属于内部实现。函数名中的AutoSize提示了其自动调整尺寸的功能,符合代码逻辑。 总结下来,这个函数的作用是遍历所有打印编辑作业中的对象,计算出包围所有对象的最小矩形尺寸,并记录下来用于后续处理或显示。</think>这是一个用于自动调整打印编辑作业窗口尺寸的静态函数。下面分步骤解析其实现逻辑: $$static\ void\ UI\_WindowPrintEditJobAutoSize(void)$$ 1. **安全检测** ```c if (!s_PrintEditJob) return; ``` - 首先检查全局指针`s_PrintEditJob`的有效性 - 如果指针为空则直接返回,避免空指针异常 2. **尺寸初始化** ```c s_PrintEditJob->w = 0; s_PrintEditJob->h = 0; ``` - 将作业窗口的宽度(w)和高度(h)重置为0 - 为后续计算提供初始基准值 3. **遍历对象链表** ```c for (obj = s_PrintEditJob->obj_list; obj; obj = obj->next) ``` - 通过`obj_list`链表遍历所有UI对象 - 使用`next`指针进行链表遍历 4. **动态计算最大尺寸** ```c if (s_PrintEditJob->w < obj->x + obj->w) s_PrintEditJob->w = obj->x + obj->w; if (s_PrintEditJob->h < obj->y + obj->h) s_PrintEditJob->h = obj->y + obj->h; ``` - 计算每个对象的右边界$x+w$ - 计算每个对象的下边界$y+h$ - 通过比较更新窗口最大尺寸 - 最终得到能包含所有对象的最小包围矩形 5. **日志输出** ```c Log(UI_LOG_NORMAL, "job size w = %d,h = %d\n", s_PrintEditJob->w, s_PrintEditJob->h); ``` - 将最终计算的尺寸输出到日志系统 - 调试时可验证自动尺寸计算结果 **功能总结**:该函数通过遍历UI对象链表,动态计算所有UI元素的包围矩形尺寸,实现窗口的自动适配。这种设计常用于需要动态布局的编辑器类程序,能自动适应不同数量和尺寸的UI元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值