ios block什么时候ios 强制销毁控制器

一、block内局部变量无法修改,但为什么可以添加数组?
NSMutableArray *mArray = [NSMutableArray arrayWithObjects:@&a&,@&b&,@&abc&,nil]; &
NSMutableArray *mArrayCount = [NSMutableArray arrayWithCapacity:1]; &
[mArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock: ^(id obj,NSUInteger idx, BOOL *stop){ &
& & & & [mArrayCount addObject:[NSNumber numberWithInt:[obj length]]]; &
& & OC中数组等对象,是一个指针
数组添加/删除对象,指针本身并没有变化
因此,除非在block里对数组进行赋值,否则任何操作都是可行的。
下面总结下,block下变量的访问权限:
相同作用域下,局部变量在block内是只读的
相同作用域下,带__block修饰的变量,在block内是可读写的
静态变量和全局变量在block内是可读写的。
当block内使用了局部变量时,block会在栈上保存一份局部变量(block都是存储在栈上的),保存的变量在block里是一个常量,所以不能修改。
若是OC中的对象,blcok会retain,等执行完毕后再release。
如果有带__block的变量,那么block就可以对此变量进行修改。由此可见,带__block的变量不是线程安全的。iOS中,我们经常通过设置request的completionBlock来简化代码时,就需要注意到这一点。
typedef void (^TestBlock) (void); &
& & int val = 20; &
& & TestBlock block1 = ^{ NSLog (@&%d&, val); }; &
& & val = 50; &
& & TestBlock block2 = ^{ NSLog (@&%d&, val); }; &
& & val = 5; &
& & TestBlock block3 = ^{ NSLog (@&%d&, val); }; &
& & block1(); &
& & block2(); &
& & block3(); &
& & //output: 20 50 5 &
//例如:(无ARC)
//__block id safeSelf =
//(有ARC)
//__weak id safeSelf = & & & &//ios 5
// __unsafe_unretained id safeSelf = //ios 4
二,block 注意事项
1,block 在实现时就会对它引用到的它所在方法中定义的栈变量进行一次只读拷贝,然后在 block 块内使用该只读拷贝。
如下代码:
- (void)testAccessVariable &
& & NSInteger outsideVariable = 10; &
& & //__block NSInteger outsideVariable = 10; &
& & NSMutableArray * outsideArray = [[NSMutableArray alloc] init]; &
& & void (^blockObject)(void) = ^(void){ &
& & & & NSInteger insideVariable = 20; &
& & & & KSLog(@& && member variable = %d&, self.memberVariable); &
& & & & KSLog(@& && outside variable = %d&, outsideVariable); &
& & & & KSLog(@& && inside variable = %d&, insideVariable); &
& & & & &&
& & & & [outsideArray addObject:@&AddedInsideBlock&]; &
& & outsideVariable = 30; &
& & self.memberVariable = 30; &
& & blockObject(); &
& & KSLog(@& && %d items in outsideArray&, [outsideArray count]); &
输出结果为:
& & member variable = 30
& & outside variable = 10
& & inside variable = 20
& & 1 items in outsideArray
注意到没?outside 变量的输出值为10,虽然outside变量在定义 block 之后在定义 block 所在的方法 testAccessVariable 中被修改为 20 了。这里的规则就是:blockObject 在实现时会对 outside 变量进行只读拷贝,在 block 块内使用该只读拷贝。因此这里输出的是拷贝时的变量值 10。如果,我们想要让 blockObject 修改或同步使用 outside 变量就需要用 __block 来修饰 outside 变量。
__block NSInteger outsideVariable = 10;
a),在上面的 block 中,我们往 outsideArray 数组中添加了值,但并未修改 outsideArray 自身,这是允许的,因为拷贝的是 outsideArray 自身。&
b),对于 static 变量,全局变量,在 block 中是有读写权限的,因为在 block 的内部实现中,拷贝的是指向这些变量的指针。
c), __block 变量的内部实现要复杂许多,__block 变量其实是一个结构体对象,拷贝的是指向该结构体对象的指针。
2,非内联(inline) block 不能直接访问 self,只能通过将 self 当作参数传递到 block 中才能使用,并且此时的 self 只能通过 setter 或 getter 方法访问其属性,不能使用句点式方法。但内联 block 不受此限制。
typedef NSString* (^IntToStringConverter)(id self, NSInteger paramInteger); &
- (NSString *) convertIntToString:(NSInteger)paramInteger &
& & & & & & & & &usingBlockObject:(IntToStringConverter)paramBlockObject &
& & return paramBlockObject(self, paramInteger); &
typedef NSString* (^IntToStringInlineConverter)(NSInteger paramInteger); &
- (NSString *) convertIntToStringInline:(NSInteger)paramInteger &
& & & & & & & & &usingBlockObject:(IntToStringInlineConverter)paramBlockObject &
& & return paramBlockObject(paramInteger); &
IntToStringConverter independentBlockObject = ^(id self, NSInteger paramInteger) { &
& & KSLog(@& && self %@, memberVariable %d&, self, [self memberVariable]); &
& & NSString *result = [NSString stringWithFormat:@&%d&, paramInteger]; &
& & KSLog(@& && independentBlockObject %@&, result); &
- (void)testAccessSelf &
& & // Independent &
& & [self convertIntToString:20 usingBlockObject:independentBlockObject]; &
& & // Inline &
& & IntToStringInlineConverter inlineBlockObject = ^(NSInteger paramInteger) { &
& & & & KSLog(@& && self %@, memberVariable %d&, self, self.memberVariable); &
& & & & &&
& & & & NSString *result = [NSString stringWithFormat:@&%d&, paramInteger]; &
& & & & KSLog(@& && inlineBlockObject %@&, result); &
& & [self convertIntToStringInline:20 usingBlockObject:inlineBlockObject]; &
3,使用 weak&strong dance 技术来避免循环引用
在第二条中,我提到内联 block 可以直接引用 self,但是要非常小心地在 block 中引用 self。因为在一些内联 block 引用 self,可能会导致循环引用。如下例所示:
@interface KSViewController () &
& & id _ &
@implementation KSViewController &
- (void)viewDidLoad &
& & [super viewDidLoad]; &
& & // Do any additional setup after loading the view, typically from a nib. &
& & KSTester * tester = [[KSTester alloc] init]; &
& & [tester run]; &
& & _observer = [[NSNotificationCenter defaultCenter] &
& & & & & & & & &addObserverForName:@&TestNotificationKey& &
& & & & & & & & &object:nil queue:nil usingBlock:^(NSNotification *n) { &
& & & & & & & & & & &NSLog(@&%@&, self); &
& & & & & & & & &}]; &
- (void)dealloc &
& & if (_observer) { &
& & & & [[NSNotificationCenter defaultCenter] removeObserver:_observer]; &
在上面代码中,我们添加向通知中心注册了一个观察者,然后在 dealloc 时解除该注册,一切看起来正常。但这里有两个问题:
a) 在消息通知 block 中引用到了 self,在这里 self 对象被 block retain,而 _observer 又 retain 该 block的一份拷贝,通知中心又持有 _observer。因此只要 _observer 对象还没有被解除注册,block 就会一直被通知中心持有,从而 self 就不会被释放,其 dealloc 就不会被调用。而我们却又期望在 dealloc 中通过 removeObserver 来解除注册以消除通知中心对 _observer/block 的 retain。
b) 同时,_observer 是在 self 所在类中定义赋值,因此是被 self retain 的,这样就形成了循环引用。
上面的过程 a) 值得深入分析一下:
苹果官方文档中对 addObserverForName:object:queue:usingBlock: 中的 block 变量说明如下:
The block is copied by the notification center and (the copy) held until the observer registration is removed.
因此,通知中心会拷贝 block 并持有该拷贝直到解除 _observer 的注册。在 ARC 中,在被拷贝的 block 中无论是直接引用 self 还是通过引用 self 的成员变量间接引用 self,该 block 都会 retain self。
这两个问题,可以用 weak&strong dance 技术来解决。该技术在 WWDC 中介绍过:2011 WWDC Session #322 (Objective-C Advancements in Depth)
__weak KSViewController * wself = &
_observer = [[NSNotificationCenter defaultCenter] &
& & & & & & &addObserverForName:@&TestNotificationKey& &
& & & & & & &object:nil queue:nil usingBlock:^(NSNotification *n) { &
& & & & & & & & &KSViewController * sself = &
& & & & & & & & &if (sself) { &
& & & & & & & & & & &NSLog(@&%@&, sself); &
& & & & & & & & &} &
& & & & & & & & &else { &
& & & & & & & & & & &NSLog(@&&self& dealloc before we could run this code.&); &
& & & & & & & & &} &
& & & & & & &}]; &
下面来分析为什么该手法能够起作用。
首先,在 block 之前定义对 self 的一个弱引用 wself,因为是弱引用,所以当 self 被释放时 wself 会变为 nil;然后在 block 中引用该弱应用,考虑到多线程情况,通过使用强引用 sself 来引用该弱引用,这时如果 self 不为 nil 就会 retain self,以防止在后面的使用过程中 self 被释放;然后在之后的 block 块中使用该强引用 sself,注意在使用前要对 sself 进行了 nil 检测,因为多线程环境下在用弱引用 wself 对强引用 sself 赋值时,弱引用 wself 可能已经为 nil 了。
通过这种手法,block 就不会持有 self 的引用,从而打破了循环引用。
扩展:其他还需要注意避免循环引用的地方
与此类似的情况还有 NSTimer。苹果官方文档中提到&Note in particular that run loops retain their timers, so you can release a timer after you have added it to a run loop.&,同时在对接口
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats
的 target 说明文档中提到:
The object to which to send the message specified by aSelector when the timer fires. The target object is retained by the timer and released when the timer is invalidated.
结合这两处文档说明,我们就知道只要重复性 timer 还没有被 invalidated,target 对象就会被一直持有而不会被释放。因此当你使用 self 当作 target 时,你就不能期望在 dealloc 中 invalidate timer,因为在 timer 没有被invalidate 之前,dealloc 绝不会被调用。因此,需要找个合适的时机和地方来 invalidate timer,但绝不是在 dealloc 中。&
4,block 内存管理分析
block 其实也是一个 NSObject 对象,并且在大多数情况下,block 是分配在栈上面的,只有当 block 被定义为全局变量或 block 块中没有引用任何 automatic 变量时,block 才分配在全局数据段上。 __block 变量也是分配在栈上面的。
在 ARC 下,编译器会自动检测为我们处理了 block 的大部分内存管理,但当将 block 当作方法参数时候,编译器不会自动检测,需要我们手动拷贝该 block 对象。幸运的是,Cocoa 库中的大部分名称中包含&usingBlock&的接口以及 GCD 接口在其接口内部已经进行了拷贝操作,不需要我们再手动处理了。但除此之外的情况,就需要我们手动干预了。
- (id) getBlockArray &
& & int val = 10; &
& & return [[NSArray alloc] initWithObjects: &
& & & & & & ^{ KSLog(@& && block 0:%d&, val); }, & &// block on the stack &
& & & & & & ^{ KSLog(@& && block 1:%d&, val); }, & &// block on the stack &
& & & & & & nil]; &
// & &return [[NSArray alloc] initWithObjects: &
// & & & & & &[^{ KSLog(@& && block 0:%d&, val); } copy], & &// block copy to heap &
// & & & & & &[^{ KSLog(@& && block 1:%d&, val); } copy], & &// block copy to heap &
// & & & & & &nil]; &
- (void)testManageBlockMemory &
& & id obj = [self getBlockArray]; &
& & typedef void (^BlockType)(void); &
& & BlockType blockObject = (BlockType)[obj objectAtIndex:0]; &
& & blockObject(); &
执行上面的代码中,在调用 testManageBlockMemory 时,程序会 crash 掉。因为从 getBlockArray 返回的 block 是分配在 stack 上的,但超出了定义 block 所在的作用域,block 就不在了。正确的做法(被屏蔽的那段代码)是在将 block 添加到 NSArray 中时先 copy 到 heap 上,这样就可以在之后的使用中正常访问。
在 ARC 下,对 block 变量进行 copy 始终是安全的,无论它是在栈上,还是全局数据段,还是已经拷贝到堆上。对栈上的 block 进行 copy 是将它拷贝到堆上;对全局数据段中的 block 进行 copy 不会有任何作用;对堆上的 block 进行 copy 只是增加它的引用记数。
如果栈上的 block 中引用了__block 类型的变量,在将该 block 拷贝到堆上时也会将 __block 变量拷贝到堆上如果该 __block 变量在堆上还没有对应的拷贝的话,否则就增加堆上对应的拷贝的引用记数。今天看啥 热点:
浅析ios开发中Block块语法的妙用,浅析iosblock妙用
& & & 事实上,任何一个应用的开发都离不开多线程。而“块”block与GCD就是苹果OC语言中多线程的核心。
一.块的内部结构
& & &在oc中,块语法以闭包的形式存在,每一个Objective-C对象都占据着某个内存区域。块本身也是一个对象,在存放块的对象内存区域中,首个变量是指向Class的指针,该指针叫做isa。其余内存里含有块对象正常运转所需的各种信息。
& & 以下是块语法的内部结构变量。
& & 1.void* & & & & & & & & & & & & & & & & & isa(指向class的对象指针)
& & 2.int & & & & & & & & & & & & & & & & & & & flags
& & 3.int & & & & & & & & & & & & & & & & & & & reserved
& & 4.void(*)(void*,……) &invoke(函数指针)
& & 5.struct* & & & & & & & & & & & & & & & & descriptor(结构体描述)
& & 根据上述块语法的内存结构可知,其中最重要的就是invoke变量,这是一个函数指针,指向的就是块的实现代码。
二.块在系统api回调中的应用
& &在iOS的原生api中,有不少的地方都用到了块语法。其中最常见的主要是两个地方,一个就是数组和字典的块枚举,这种枚举方式是每一个NSArry和NSDictionary都自带的,其效率和便利性远远高于传统的for循环。
[self.p_tableArrenumerateObjectsUsingBlock:^(id obj,NSUInteger idx,
BOOL *stop) {
& & & & & & & & & & &#code#&
& & & & & & & & }]
另一个常见的地方就是页面跳转present之后的完成回调,
[self presentViewController:&(UIViewController *)& animated:&(BOOL)& completion:&^(void)completion&]
三.块语法在UIAlertView中的集中代码
&UIAlertView是一个弹窗控件,有一些按钮,最常见的就是确认和取消,UIAlertView有一个代理处理这些按钮,当用户点击后,该代理可以捕获按钮的下标,然后用户根据下标Index写一些逻辑代码。
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
& 快语法的第一个妙用就是可以直接在创建这个UIAlertView控件的时候就已经写好逻辑代码,完全不用写在以上回调中。
& 以下是具体实现。
& 第一步,申明一个全部的Block对象,根据UIAlertView的回调代理可知,该代理主要参数是一个NSInteger类型的参数,那么我们申明的Block对象可以根据代理的实际情况来创建。
@property(nonatomic,copy)void(^p_alertBlock)(NSInteger);
& 第二部,在创建这个UIAltView的地方实现这个全部的Block对象。
& if(!self.p_alertBlock)
& & & & & &self.p_alertBlock = ^(NSInteger buttonIndex)
& & & & & & {
& & & & & & & &AccountViewController *acc =
& & & & & & & &switch (buttonIndex) {
& & & & & & & & & &case
& & & & & & & & & & & &break;
&& & & & & & & & & & & &
& & & & & & & & & &case
&& & & & & & & & & & & &
& & & & & & & & & & & &if([acc.p_fmdbdeleteObjc:list])
& & & & & & & & & & & & {
& & & & & & & & & & & & & & [acc.p_tableArrremoveObjectAtIndex:acc.p_didSelect];
& & & & & & & & & & & & & & [acc.p_tablereloadData];
& & & & & & & & & & & & }
& & & & & & & & & & & &break;
& & & & & & & & }
& & & & & & };
& & & & UIAlertView *alt = [[UIAlertViewalloc]
initWithTitle:NSLocalizedString(@&tip&,nil)message:NSLocalizedString(@&sureDelet&,nil)
delegate:selfcancelButtonTitle:NSLocalizedString(@&cancel&,nil)
otherButtonTitles:NSLocalizedString(@&ok&,nil),nil];
& & & & [altshow];
& &这是一个删除数据库操作的弹窗,当用户点击确认的时候删除数据库的对象,点击取消不做任何处理。
& &第三步,在UIAlertView的代理中运行快。
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
& &self.p_alertBlock(buttonIndex);
& 这个用法有一个好处就是可以在UIAlertView还未创建之前就已经确定了它按钮的处理,集中代码,看起来更加的方便和直观。
& 以上只是一个事例,在系统很多控件中都可以这样实现,诸如UIActionSheet等。
&&三.块语法替代Delegate
&提起ios的消息通知,就少不了代理Delegate。代理尽管很方便,可是实现的过程比较繁琐。如果使用块语法的话,我们可以提前把回调函数的代码实现封装到Block中作为参数传递给数据层,这样子实际上在代理回调中
if(self.delegate && [self.delegaterespondsToSelector:@selector(setAddressSuccess:)])
& & & & & & [self.delegatesetAddressSuccess:self.accountList.remark];
这句话就被
Block(self.accountList.remark);所取代。
& 是不是更加的便捷了呢?关键是你根本就不用声明代理,实现,设置代理,维护协议等等复杂的过程。
& 代理还有一个限制就是必须要对象化,假如一个工具类是一个类的实例方法,你想在某些操作之后把数据回调给C层,这个时候代理就无法实行了,但是Block只不是是一个对象而已,就像NSString一样,可以帮助你实现。
& 以上只是块语法在系统控件API回调中的妙用和两个类之间代理的妙用,更多的功能还有待在实际开发中逐步挖掘发现。
& 仁者见仁,智者见智,块语法究竟强大到何种地步,等你用多了就知道了。
相关搜索:
相关阅读:
相关频道:
Android教程最近更新【如何在iOS中使用Block】-突袭网
17:51:30【 转载互联网】 作者: &&|&责编:李强
&&& &为了解决用户可能碰到关于"如何在iOS中使用Block"相关的问题,突袭网经过收集整理为用户提供相关的解决办法,请注意,解决办法仅供参考,不代表本网同意其意见,如有任何问题请与本网联系。"如何在iOS中使用Block"相关的详细问题如下:RT,我想知道:如何在iOS中使用Block===========突袭网收集的解决方案如下===========
解决方案1:comparisonO; }。超过100个的Apple API都使用了Block:currentLocale]; &#47, NSUInteger idx,封装了用于遍历(线性遍历)或者回调:stringB options,但通常情况下我们会以内联的方式使用BZ& //: compareStringsBlock]); sortFunction(anArray,它表示一个Block的开始, ^(string *a string *b){ if ( a == @&A& NSString *string = @&1 from 10 is %d&dog&quot。Apple文档中指出: int (^oneFrom)(int) = ^(int anInt) {
return anInt - 1,这样就可以在需要将block作为参数的时候以内联代码的方式简单地实现;A&quot: @&quot, oneFrom(10));,这样你就可以传入Block作为方法的参数;; NSSet *aSet = [NSSet setWithObjects。可以在词义范围(堆栈帧)被销毁后继续共享和修改该词义范围(堆栈帧)的状态: Block是符合如下要求的匿名内联的代码集;;&#47, @&quotBlock可以帮助我们组织独立的代码段;, id stringB) { NSRange rangeS = NSMakeRange (0。Block是一个自包含的小代码段;&#47。声明和使用Block Apple文档中介绍了如何将一个Block声明为变量。int num1 = 7;,所以这是一个我们必须开始熟悉的知识, @&cat&quot.; &#47。
float (^distanceTraveled) ( }.;Gamma&quot。iOS4在UIKit中引入了该特征;X&1 from 10 is 9&/we provide below a way of how to enumerate: @& 这样我们就看到一个内联的block代码段占据了最后一个参数(必须是参数列表的最后一个参数)的位置,nil]; 我们创建了一个内联块^(int anInt): obj]) {
return YES,可以并发执行的任务单元;
} }], NSUInteger idx? 你可以使用^操作符来声明一个Block变量, [stringA length]), float) =
^(float startingS }; }).5 * acceleration * time * time);&#47:NSLog(@&quot, NSUInteger idx. and the body logic test = ^ (id obj:^(id obj, BOOL *stop);) return TRUE;, @&quot,返回float值;Alpha&%d&gamma&quot: @&quot, @&
found = YES;body of block gets the block literal ^( NSSet *filterSet = [NSSet setWithOBeta& Apple提供的另外一个例子是;Block declaration returns BOOL;;
NSArray *compareSortArray = [arrayOfStringDays sortArrayUsingComparator, aBlock(49)):__block BOOL found = NO;
你也可以传入一个Block作为一个参数。Cocoa提供了很多使用Block的方法; 这个block函数(distanceTraveled)传入3个float型参数.,而不要以如上的方式声明它们。NSArray *anArray = [NSArray arrayWithObjects。NSComperator compareStringsBlock = ^(id stringA; /cat&/ }。Block是什么样的;Q&,并提高复用性和可读性:和函数一样具有一个指定类型的参数列表 有一个可以推导或声明的返回值类型可以从它被定义的词义范围中捕捉状态可以在需要的时候改变词义范围的状态可以和相同的词义范围中定义的其他的Block共享更改的可能.;C&quot:NSArray *array = [NSArray arrayWithO, params inc,要么将其作为一个操作完成后的回调, using our own compare logic [aSet enumerateObjectsUsingB
return NO;B& Block具有将临时函数体创建为表达式的优势, float time) {
float distance = (startingSpeed * time) + (0; &#47, @&quot, @&quot,比如在一个变量中, float,所以可以将它当做一个函数中使用, nil], BOOL *stop) {
if (idx &lt, @&quot, BOOL *stop) {
if ([obj localizedCaseInsensitiveC /
BOOL (^test)( 5) {
if ([filterSet containsObject, @&;adds 49 to 7 which gives us 56。API要么会使用Block在一个对象集合上执行某种操作,其函数体和结果被传到了另外一个名为OneFrom的B: &quot。
printf(&quot:rangeS, nil], nil], Bool *stop): @&/
return (stringA compare. 我们刚看过了将block当做变量的情况;;
return distance. ,并将其作为一个函数使用, 打印出:string] == NSOrderedSame) {
*stop = YES; int(^aBlock)(int) = ^)int num2) {
return num1+nunm2; 在如上代码中我们将Block声明为一个变量. id and BOOL &#47
================可能对您有帮助================
答:Block可以帮助我们组织独立的代码段,并提高复用性和可读性。iOS4在UIKit中引入了该特征。超过100个的Apple API都使用了Block,所以这是一个我们必须开始熟悉的知识。 Block是什么样的? 你可以使用^操作符来声明一个Block变量,它表示一个Block...===========================================答:Block可以帮助我们组织独立的代码段,并提高复用性和可读性。iOS4在UIKit中引入了该特征。超过100个的Apple API都使用了Block,所以这是一个我们必须开始熟悉的知识。 Block是什么样的? 你可以使用^操作符来声明一个Block变量,它表示一个Block...===========================================答:Block 的声明格式如下: return_type (^block_name)(param_type, param_type, ...) 如果你之前使用过其他 C 类型的语言,那这段代码你应该看起来很眼熟, 除了这个 ^ 符号。 ^ 这个符号表示了 “我们定义的这个东西是一个 Block”。 如果你能分析...===========================================答:Block可以帮助我们组织独立的代码段,并提高复用性和可读性。iOS4在UIKit中引入了该特征。超过100个的Apple API都使用了Block,所以这是一个我们必须开始熟悉的知识。 Block是什么样的? 你可以使用^操作符来声明一个Block变量,它表示一个Block...===========================================答:首先你要理解bolck的概念、 你可以先写点简单点的例子 然后等熟悉的差不多了,在运用到实际的项目里===========================================答:Block可以帮助我们组织独立的代码段,并提高复用性和可读性。iOS4在UIKit中引入了该特征。超过100个的Apple API都使用了Block,所以这是一个我们必须开始熟悉的知识。 Block是什么样的? 你可以使用^操作符来声明一个Block变量,它表示一个Block...===========================================答:如果你之前使用过其他 C 类型的语言,那这段代码你应该看起来很眼熟, 除了这个 ^ 符号。 ^ 这个符号表示了 “我们定义的这个东西是一个 Block”。 如果你能分析到 ^ 符号的意思 “我是一个 Block” ,那么祝贺你 – 你已经了解了 Block 中最难的部分...===========================================答:首先你要理解bolck的概念、 你可以先写点简单点的例子 然后等熟悉的差不多了,在运用到实际的项目里===========================================答:- (void)viewDidLoad{ [super viewDidLoad]; //(1)定义无参无返回值的Block void (^printBlock)() = ^(){ printf("no number"); }; printBlock(); printBlock(9); int mutiplier = 7; //(3)定义名为myBlock的代码块,返回值类型为int int (^...===========================================

我要回帖

更多关于 ios 销毁单例对象 的文章

 

随机推荐