Block的使用

简介:

Block:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
//  main.m
//  块的使用
 
#import <Foundation/Foundation.h>
#include <stdlib.h>
 
typedef  void  (^DownloadURL)( void );
 
//获取用于下载URL的块
DownloadURL getDownloadURLBlock(NSString *url)
{
     NSString *urlString = url;
     return  ^{
         //下载URL
         NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
         NSError *error;
         NSDate *startTime = [NSDate date];
         NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
         if  (data == nil) {
             NSLog(@ "Error loading request %@" , [error localizedDescription]);
         }
         else  {
             NSDate *endTime = [NSDate date];
             NSTimeInterval timeInterval = [endTime timeIntervalSinceDate:startTime];
             NSLog(@ "Time taken to download %@ = %f seconds" , urlString, timeInterval);
         }
     };
}
 
int  main( int  argc,  const  char  * argv[]) {
     @autoreleasepool {
         //block可以理解为闭包或者lambda也可以是函数指针 也可以是匿名内部类
         
#pragma mark - 块的定义
         /*定义块的语法格式如下:
             ^[块返回值类型] (形参类型1 形参1,形参类型2 形参2,  ...){
             //块执行体
             }
         */
         //定义不带参数、无返回值的块
         void  (^printStr) ( void ) = ^( void ){
             NSLog(@ "这是块" );
         };
         //使用printStr调用块
         printStr();
         
         //定义带参数、有返回值的块
         double  (^hypot) ( double  , double ) = ^( double  num1 , double  num2){
             return  sqrt (num1 * num1 + num2 * num2);
         };
         //调用块,并输出块的返回值
         NSLog(@ "%g"  , hypot(3,4));
         
         //也可以先只定义块变量:定义带参数、无返回值的快
         void  (^print) (NSString *);
         //再将块赋值给指定的块变量
         print = ^(NSString * info){
             NSLog(@ "info参数为:%@"  , info);
         };
         //调用块
         print(@ "测试块调用" );
         
#pragma mark - 修改局部变量的值
         /*块可以访问程序中局部变量的值,当块访问局部变量的值时,不允许修改局部变量的值
          如果不希望在定义块时就把局部变量的值复制到块中,而是等到执行时才去访问、获取局部变量的值,
          甚至希望块也可以改变局部变量的值,此时可以考虑使用__block修饰局部变量。*/
         //定义__block修饰的全局变量
         //int one = 1;
         __block  int  my = 20;
         void  (^printMy)( void ) = ^( void ){
             //运行时访问、获取局部变量的值,此处输出45
             NSLog(@ "%d"  , my);
             //尝试对_block局部变量赋值是允许的
             my = 30;
             //one = 2;      //Xcode会提示无法对one进行修改,除非用__block进行了修饰
             //此处输出30
             NSLog(@ "%d"  , my);
         };
         my = 45;
         printMy(); //调用块
         //由于块修改了__block局部变量的值,因此下面的代码输出30
         NSLog(@ "块执行完后,my的值为:%d"  , my);
         
#pragma mark - 使用typedef定义块类型
         /*使用typedef定义块类型的语法格式如下:
             typedef 块返回值类型 (^块类型) (形参类型1 [形参名] ,形参类型2 [形参名] , ... );
         */
         /*使用typedef可以定义块类型,定义了块类型后,该块类型主要有如下两个用途:
             1.复用块类型,使用块类型可以重复定义多个块变量。
             2.使用块类型定义函数参数,这样即可定义带块参数的函数。*/
         //使用typedef定义块类型
         typedef  void  (^FKPrintBlock) (NSString*);
         //使用FKPrintBlock定义块变量,并将指定块赋给该变量
         FKPrintBlock printt = ^(NSString * info){
             NSLog(@ "%@"  , info);
         };
         //使用FKPrintBlock定义块变量,并将指定块赋值给该变量
         FKPrintBlock loopPrint = ^(NSString * info){
             for  ( int  i = 0 ; i < 2 ; i++){
                 NSLog(@ "%@"  , info);
             }
         };
         //一次调用两个块
         printt(@ "Objective-C" );
         loopPrint(@ "iOS" );
         
#pragma mark - 作为方法的参数
         /*作为方法声明的参数
          //- (void)方法名:(返回值类型 (^)(参数类型))block的名称;
          - (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
         */
         NSArray *jingse = @[@ "锦瑟无端五十弦," ,@ "一弦一柱思华年。" ,@ "庄生晓梦迷蝴蝶," ,@ "望帝春心托杜鹃。" ,@ "沧海月明珠有泪," ,@ "蓝田日暖玉生烟" ,@1,@NO];
         //定义一个block块操作 return(^fpointer)(int,NS*...) = ^(int a,NS* B...){...};
         void  (^Pblock1)(id,NSUInteger, BOOL *) = ^(id obj,NSUInteger idx, BOOL  *stop){
             NSLog(@ "%ld --> %@" ,idx,obj);
             if  (idx == [jingse count]) {
                 *stop = YES;
             }
         };
         //匿名block指针
         [jingse enumerateObjectsUsingBlock:Pblock1];
         //- (void)enumerateObjectsUsingBlock:(void (^)(ObjectType obj, NSUInteger idx, BOOL *stop));
 
         //?????
//        BOOL *stop = NO;
//        for (int i = 0 ; stop; i++)
//            Pblock1(jingse[i],i,stop);
         
#pragma mark - 块的内存管理
         /*1)在运行程序时,块常量表达式会获得栈内存,因而会拥有与局部变量相同的生命周期。
         因此,它们您必须被复制到永久存储区域(即堆)中,才能在定义它们的范围之外使用。
           2)使用Block_copy()命令可以将块常量复制到堆中,使用Block_release()命令可以释放堆中的块常量.
           3)在使用ARC时,只要块没有返回id类型值或将id类型值用作参数,编译器就会自动执行块的复制和释放操作。否则,就必须手动执行复制和释放操作。
           4)在使用MRR时,__block变量不会被保留;而在使用ARC时,__block变量会被保留。这就意味着如果你在使用ARC时不想不想保留__block变量(如避免循环引用),还应对变量应用__weak存储类型修饰符*/
         /*在MRR下使用
          void (^greetingBlock)(void)
         {
             greetingBlock = [^{
                 NSLog(@"Hello Jabit");
             } copy];
         }
         greetingBlock();
         [greetingBlock release];*/
         
         /*在MRR下使用
         void (^greetingBlock)(id salutation);
         {
             greetingBlock = Block_copy(^(id salutation){
                 NSLog(@"%@, Jabit", salutation);
             });
         }
         greetingBlock(@"Hello");
         Block_release(greetingBlock);*/
         
#pragma mark - 在OC中使用block
         /*1、作为变量
          //1
          返回值类型 (^block的名称)(参数类型) = ^返回值类型(参数) {...};
          //2
          returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
          
          2、作为属性
          //1
          @property (nonatomic, copy) 返回值类型 (^block的名称)(参数类型);
          //2
          @property (nonatomic, copy) returnType (^blockName)(parameterTypes);
          
          3、作为方法声明的参数
          //1
          - (void)方法名:(返回值类型 (^)(参数类型))block的名称;
          //2
          - (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
          
          4、作为方法实现的参数
          //1
          [对象/类 方法名:^返回值类型 (参数) {...}];
          //2
          [someObject someMethodThatTakesABlock:^returnType (parameters) {...}];
          
          5、使用typedef定义块类型
         */
         
#pragma mark - 使用块为数组排序
#define ArrayElements 10
         //创建一个含有随机数值(0~99)的数组
         NSMutableArray *numbers = [NSMutableArray arrayWithCapacity:ArrayElements];
         for  ( int  elem=0; elem<ArrayElements; elem++) {
             unsigned  int  value = arc4random() % 100;
             [numbers addObject:[NSNumber numberWithUnsignedInt:value]];
         }
         NSLog(@ "Values:%@" , numbers);        //记录未排序的数值
         
         //以升序方式为数组数值排序
         [numbers sortUsingComparator:^(id obj1, id obj2){
             if  ([obj1 integerValue] > [obj2 integerValue]) {
                 return  (NSComparisonResult)NSOrderedDescending;
             }
             if  ([obj1 integerValue] < [obj2 integerValue]) {
                 return  (NSComparisonResult)NSOrderedAscending;
             }
             return  (NSComparisonResult)NSOrderedSame;
         }];
         NSLog(@ "Values:%@" , numbers);        //记录已排序的数值
         
#pragma mark - 使用块加载URL
#define IndexURL @"http://www.wikipedia.com/index.html"
         //为连接获取当前的运行循环
         NSRunLoop *loop = [NSRunLoop currentRunLoop];
         BOOL  __block downloadComplete = NO;
         
         //创建请求
         NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:IndexURL]];
         [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
             if  (data == nil) {
                 NSLog(@ "Error loading request %@" , [error localizedDescription]);
             }
             else  {
                 NSLog(@ "\n\tDownloaded %lu bytes from request %@\n" , [data length], [request URL]);
             }
             downloadComplete = YES;
         }];
         
         //一直循环直到完成加载资源的操作为止(它会运行循环,接收输入源的事件,并执行所有相应的委托或回调方法,直到连接完成加载资源的操作为止
         while  (!downloadComplete && [loop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
         
#pragma mark - 使用块的并行编程方式
#define YahooURL    @"http://www.yahoo.com/index.html"
#define ApressURL   @"http://www.apress.com/index.html"
         //创建任务请求(GCD API)
         dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
         dispatch_queue_t queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
         
         //创建任务分组
         dispatch_group_t group = dispatch_group_create();
         
         //获取度量的当前时间
         NSDate *startTime = [NSDate date];
         
         //创建并分派异步任务
         dispatch_group_async(group, queue1, getDownloadURLBlock(YahooURL));
         dispatch_group_async(group, queue2, getDownloadURLBlock(ApressURL));
         
         //使主进程等待,直到分组中的所有任务完成为止
         dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
         
         //为并行操作和日志检索时间信息
         NSDate *endTime = [NSDate date];
         NSTimeInterval timeInterval = [endTime timeIntervalSinceDate:startTime];
         NSLog(@ "Time taken to download URLs concurrently = %f seconds\n" , timeInterval);
     }
     return  0;
}
目录
相关文章
|
11天前
|
人工智能 JavaScript Ubuntu
5分钟上手龙虾AI!OpenClaw部署(阿里云+本地)+ 免费多模型配置保姆级教程(MiniMax、Claude、阿里云百炼)
OpenClaw(昵称“龙虾AI”)作为2026年热门的开源个人AI助手,由PSPDFKit创始人Peter Steinberger开发,核心优势在于“真正执行任务”——不仅能聊天互动,还能自动处理邮件、管理日程、订机票、写代码等,且所有数据本地处理,隐私完全可控。它支持接入MiniMax、Claude、GPT等多类大模型,兼容微信、Telegram、飞书等主流聊天工具,搭配100+可扩展技能,成为兼顾实用性与隐私性的AI工具首选。
18376 102
|
3天前
|
人工智能 安全 Linux
【OpenClaw保姆级图文教程】阿里云/本地部署集成模型Ollama/Qwen3.5/百炼 API 步骤流程及避坑指南
2026年,AI代理工具的部署逻辑已从“单一云端依赖”转向“云端+本地双轨模式”。OpenClaw(曾用名Clawdbot)作为开源AI代理框架,既支持对接阿里云百炼等云端免费API,也能通过Ollama部署本地大模型,完美解决两类核心需求:一是担心云端API泄露核心数据的隐私安全诉求;二是频繁调用导致token消耗过高的成本控制需求。
3545 4
|
6天前
|
人工智能 安全 API
OpenClaw“小龙虾”进阶保姆级攻略!阿里云/本地部署+百炼API配置+4种Skills安装方法
很多用户成功部署OpenClaw(昵称“小龙虾”)后,都会陷入“看似能用却不好用”的困境——默认状态下的OpenClaw更像一个聊天机器人,缺乏连接外部工具、执行实际任务的能力。而Skills(技能插件)作为OpenClaw的“动手能力核心”,正是打破这一局限的关键:装对Skills,它能帮你自动化处理流程、检索全网资源、管理平台账号,真正变身“能做事的AI管家”。
4537 7
|
7天前
|
人工智能 安全 前端开发
Team 版 OpenClaw:HiClaw 开源,5 分钟完成本地安装
HiClaw 基于 OpenClaw、Higress AI Gateway、Element IM 客户端+Tuwunel IM 服务器(均基于 Matrix 实时通信协议)、MinIO 共享文件系统打造。
7225 6
|
6天前
|
人工智能 API 网络安全
Mac mini × OpenClaw 保姆级配置教程(附阿里云/本地部署OpenClaw配置百炼API图文指南)
Mac mini凭借小巧机身、低功耗和稳定性能,成为OpenClaw(原Clawdbot)本地部署的首选设备——既能作为家用AI节点实现7×24小时运行,又能通过本地存储保障数据隐私,搭配阿里云部署方案,可灵活满足“长期值守”与“隐私优先”的双重需求。对新手而言,无需复杂命令行操作,无需专业技术储备,按本文步骤复制粘贴代码,即可完成OpenClaw的全流程配置,同时接入阿里云百炼API,解锁更强的AI任务执行能力。
5826 1
|
15天前
|
人工智能 自然语言处理 JavaScript
2026年Windows+Ollama本地部署OpenClaw保姆级教程:本地AI Agent+阿里云上快速搭建
2026年OpenClaw凭借本地部署、私有化运行的特性,成为打造个人智能体的核心工具,而Ollama作为轻量级本地大模型管理工具,能让OpenClaw摆脱对云端大模型的依赖,实现**本地推理、数据不泄露、全流程私有化**的智能体验。本文基于Windows 11系统,从硬件环境准备、Ollama安装与模型定制、OpenClaw部署配置、技能扩展到常见问题排查,打造保姆级本地部署教程,同时补充阿里云OpenClaw(Clawdbot)快速部署步骤,兼顾本地私有化需求与云端7×24小时运行需求,文中所有代码命令均可直接复制执行,确保零基础用户也能快速搭建属于自己的本地智能体。
18197 116
|
9天前
|
人工智能 JSON API
保姆级教程:OpenClaw阿里云及本地部署+模型切换流程+GLM5.0/Seedance2.0/MiniMax M2.5接入指南
2026年,GLM5.0、Seedance2.0、MiniMax M2.5等旗舰大模型相继发布,凭借出色的性能与极具竞争力的成本优势,成为AI工具的热门选择。OpenClaw作为灵活的AI Agent平台,支持无缝接入这些主流模型,通过简单配置即可实现“永久切换、快速切换、主备切换”三种模式,让不同场景下的任务执行更高效、更稳定。
6223 4

热门文章

最新文章