注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

风的驿站

一徐清风,半指烛光,觥筹已净,只余茶香。残卷一章,妙趣非常,忽闻帘响,愿闻其详?

 
 
 

日志

 
 
关于我

喜欢写生 编程 音乐 设计 喜欢把自己的想法变成实实在在的东西 喜欢安静的做一些事情 CSDN博客:http://blog.csdn.net/qwertyupoiuytr

网易考拉推荐

【转载】Objective-C学习备忘单(上)  

2014-06-16 21:49:41|  分类: 程序设计 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

这不是一个初学者指南,也不是关于Objective-C的详细讨论,这是关于常见的和高水平的论题的快速索引。

 

如果这里有些问题没有涉及到,你也可以查阅以下文章:

Objective-C: A Comprehensive Guide for Beginners

The Objective-C Programming Language

Coding Guidelines for Cocoa

iOS App Programming Guide

 

内容目录

Commenting

Data Types

Constants

Operators

Declaring Classes

Preprocessor Directives

Compiler Directives

Literals

Methods

Properties and Variables

Naming Conventions

Blocks

Control Statements

Enumeration

Extending Classes

Error Handling

Passing Information

User Defaults

Common Patterns

 

注释

Objective-C中注释用来组织代码,并为将来的代码重构或者那些可能阅读你代码的iOS开发者们提供重要的额外信息。注释通常会被编译器忽视,因此它们不会增加编译器程序的大小。

 

有两种方式添加注释:

  1. // This is an inline comment(内嵌注释) 
  2. /* This is a block comment  and it can span multiple lines. */(块注释,可用于多行注释) 
  3. // You can also use it to comment out code(也可以用来注释掉代码) 
  4.  
  5. /* 
  6. - (SomeOtherClass *)doWork 
  7. { 
  8.     // Implement this 
  9. } 
  10. */ 

 

使用pragma mark来组织代码:

  1. #pragma mark - Use pragma mark to logically organize your code(使用#pragma mark可以对代码进行逻辑组织) 
  2. // Declare some methods or variables here(在此处声明方法和变量) 
  3.  
  4. #pragma mark - They also show up nicely in the properties/methods list in Xcode(在Xcode中#pragma mark还可以用来很好地显示属性及方法列表) 
  5. // Declare some more methods or variables here(在此处声明方法和变量) 

 

数据类型

数据类型的大小

无论是在32位还是64位的系统环境中,允许的数据类型大小是由为具体的类型分配了多少内存字节决定的。在32位的系统环境中,长整型(long)被分配4字节,相当于2^(4*8)(每个字节有8位)或者4294967295的内存范围。在64为的系统环境中,长整型(long)被分配8字节,相当于2^(8*8)或者1.84467440737096e19的范围。

 

64位系统环境的变化的完全指南,请参考:transition document

 

C语言基础

注:Objective-C继承了所有的C语言基本类型,然后又新增了一些其他的类型。

 

Void(空类型)

Void是C语言的空数据类型。通常用于指定无返回值的函数的返回值类型(即,函数类型为无返回值类型)。

 

整数

整数既可以是signed(有符号)的也可以是unsigned(无符号)的。signed(有符号)代表是正整数或者负整数,unsigned(无符号)代表只能是正整数。

 

整数类型以及它们的字节大小:

  1. // Char (1 byte for both 32-bit and 64-bit)  
  2. unsigned char anUnsignedChar = 255; 
  3. NSLog(@"char size: %zu", sizeof(char)); 
  4.  
  5. // Short (2 bytes for both 32-bit and 64-bit) 
  6. short aShort = -32768; 
  7. unsigned short anUnsignedShort = 65535; 
  8. NSLog(@"short size: %zu", sizeof(short)); 
  9.  
  10. // Integer (4 bytes for both 32-bit and 64-bit) 
  11. int anInt = -2147483648; 
  12. unsigned int anUnsignedInt = 4294967295; 
  13. NSLog(@"int size: %zu", sizeof(int)); 
  14.  
  15. // Long (4 bytes for 32-bit, 8 bytes for 64-bit) 
  16. long aLong = -9223372036854775808; // 32-bit 
  17. unsigned long anUnsignedLong = 18446744073709551615; // 32-bit 
  18. NSLog(@"long size: %zu", sizeof(long)); 
  19.  
  20. // Long Long (8 bytes for both 32-bit and 64-bit) 
  21. long long aLongLong = -9223372036854775808; 
  22. unsigned long long anUnsignedLongLong = 18446744073709551615; 
  23. NSLog(@"long long size: %zu", sizeof(long long)); 

 

固定宽度的整数类型和字节大小来作为变量名:

  1. // Exact integer types 
  2.  
  3. int8_t aOneByteInt = 127; 
  4.  
  5. uint8_t aOneByteUnsignedInt = 255; 
  6.  
  7. int16_t aTwoByteInt = 32767; 
  8.  
  9. uint16_t aTwoByteUnsignedInt = 65535; 
  10.  
  11. int32_t aFourByteInt = 2147483647; 
  12.  
  13. uint32_t aFourByteUnsignedInt = 4294967295; 
  14.  
  15. int64_t anEightByteInt = 9223372036854775807; 
  16.  
  17. uint64_t anEightByteUnsignedInt = 18446744073709551615; 
  18.  
  19.  
  20. // Minimum integer types 
  21.  
  22. int_least8_t aTinyInt = 127; 
  23.  
  24. uint_least8_t aTinyUnsignedInt = 255; 
  25.  
  26. int_least16_t aMediumInt = 32767; 
  27.  
  28. uint_least16_t aMediumUnsignedInt = 65535; 
  29.  
  30. int_least32_t aNormalInt = 2147483647; 
  31.  
  32. uint_least32_t aNormalUnsignedInt = 4294967295; 
  33.  
  34. int_least64_t aBigInt = 9223372036854775807; 
  35.  
  36. uint_least64_t aBigUnsignedInt = 18446744073709551615; 
  37.  
  38.  
  39. // The largest supported integer type 
  40.  
  41. intmax_t theBiggestInt = 9223372036854775807; 
  42.  
  43. uintmax_t theBiggestUnsignedInt = 18446744073709551615; 

 

浮点类型

浮点没有signed或者unsigned

  1. // Single precision floating-point (4 bytes for both 32-bit and 64-bit)单精度浮点float aFloat = 72.0345f; 
  2.  
  3. NSLog(@"float size: %zu", sizeof(float)); 
  4.  
  5.  
  6. // Double precision floating-point (8 bytes for both 32-bit and 64-bit)双精度浮点 
  7.  
  8. double aDouble = -72.0345f; 
  9.  
  10. NSLog(@"double size: %zu", sizeof(double)); 
  11.  
  12.  
  13. // Extended precision floating-point (16 bytes for both 32-bit and 64-bit)扩展精度浮点 
  14.  
  15. long double aLongDouble = 72.0345e7L; 
  16.  
  17. NSLog(@"long double size: %zu", sizeof(long double)); 

 

Objective-C基础

id:被定义为匿名或者动态对象类型,它可以存储任何类型对象的引用,不需要指定指针符号。

  1. id delegate = self.delegate; 

 

Class:用来表示对象的类,并能用于对象的内省。

  1. Class aClass = [UIView class]; 

 

Method:用来表示一个方法,并可用于swizzling方法。

  1. Method aMethod = class_getInstanceMethod(aClass, aSelector); 

 

SEL:用于指定一个selector,它是编译器指定的代码,用于识别方法的名称。

  1. SEL someSelector = @selector(someMethodName); 

 

IMP:用于在方法开始时指向内存地址。你可能不会用到这个。

  1. IMP theImplementation = [self methodForSelector:someSelector]; 

 

BOOL:用来指定一个布尔类型,布尔类型中0值被认为是NO(false),任何非零值被认为是YES(true)。任何零值对象都被认为是NO,因此不需要对零值进行同样的验证(例如,只要写if(someObject),不需要写if (someObject !=nil))

  1. // Boolean 
  2. BOOL isBool = YES; // Or NO 

 

nil:用来指定一个空对象指针。当类第一次被初始化时,类中所有的属性被设置为0,这意味着都指向空指针。

 

Objective-C中还有很多其他类型,如NSInteger, NSUInteger, CGRect,CGFloat, CGSize, CGPoint等。

 

Enum(枚举)和Bitmask(位掩码)类型

Objective-C的枚举类型可以用以下多个不同方式定义:

  1. // Specifying a typed enum with a name (recommended way)用一个别名来指定一个带有typedef关键字的枚举类型(推荐方法) 
  2.  
  3. typedef NS_ENUM(NSInteger, UITableViewCellStyle) { 
  4.  
  5.     UITableViewCellStyleDefault, 
  6.  
  7.     UITableViewCellStyleValue1, 
  8.  
  9.     UITableViewCellStyleValue2, 
  10.  
  11.     UITableViewCellStyleSubtitle 
  12.  
  13. }; 
  14.  
  15.  
  16. // Specify a bitmask with a name (recommended way)用一个别名来指定一个bitmask(推荐方法) 
  17.  
  18. typedef NS_OPTIONS(NSUInteger, RPBitMask) { 
  19.  
  20.     RPOptionNone      = 0, 
  21.  
  22.     RPOptionRight     = 1 << 0, 
  23.  
  24.     RPOptionBottom    = 1 << 1, 
  25.  
  26.     RPOptionLeft      = 1 << 2, 
  27.  
  28.     RPOptionTop       = 1 << 3 
  29.  
  30. }; 
  31.  
  32.  
  33. // Other methods:(其他方法) 
  34.  
  35. // Untyped(无类型) 
  36.  
  37. enum { 
  38.  
  39.     UITableViewCellStyleDefault, 
  40.  
  41.     UITableViewCellStyleValue1, 
  42.  
  43.     UITableViewCellStyleValue2, 
  44.  
  45.     UITableViewCellStyleSubtitle 
  46.  
  47. }; 
  48.  
  49.  
  50. // Untyped with a name 用一个别名来定义一个带有typedef关键字将枚举类型 
  51.  
  52. typedef enum { 
  53.  
  54.     UITableViewCellStyleDefault, 
  55.  
  56.     UITableViewCellStyleValue1, 
  57.  
  58.     UITableViewCellStyleValue2, 
  59.  
  60.     UITableViewCellStyleSubtitle 
  61.  
  62. } UITableViewCellStyle; 

 

构造数据类型

有时为一个特定的类或者数据类型构造一个id或者不同的类型时很有必要的。例如,从一个浮点型构造成整数或者从一个UITableViewCell构造成一个如RPTableViewCell的子类。

 

构造非对象数据类型:(cast)

  1. // Format: nonObjectType variableName = (nonObjectType) 
  2.  
  3. variableNameToCastFrom; 
  4.  
  5. int anInt = (int)anAnonymouslyTypedNonObjectOrDifferentDataType; 

 

构造对象数据类型:

  1. // Format: ClassNameOrObjectType *variableName =(ClassNameOrObjectType *)variableNameToCastFrom; 
  2.  
  3. UIViewController *aViewController = (UIViewController *) 
  4.  
  5. anAnonymouslyTypedObjectOrDifferentDataType; 

 

常量

使用常量通常是一个更好的方法,因为常量为代码中的任何对象的引用指向相同的内存地址。#define定义了一个宏。在编译开始前,宏用实际常量值来代替所有的引用,而不是作为指向常量值的内存指针。

 

Objective-C常量可以这样定义:

  1. // Format: type const constantName = value; 
  2. NSString *const kRPShortDateFormat = @"MM/dd/yyyy"
  3.  
  4. // Format: #define constantName value 
  5. #define kRPShortDateFormat @"MM/dd/yyyy" 

 

要是在扩展类中能使用常量,你必须也将它添加在头文件(.h)中。

  1. extern NSString *const kRPShortDateFormat; 

 

如果你知道一个常量只可用于它包含的.m文件中,可以这样指定它:

  1. static NSString *const kRPShortDateFormat = @"MM/dd/yyyy"

 

在方法中声明一个静态变量在调用时值不会改变。当为一个属性声明一个singleton(单例)或者创建setter和getter器时这将很有用处。

 

运算符

算术运算符

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

 

关系运算符

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

 

逻辑运算符

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

 

复合赋值运算符

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站
 

增值或减值运算符

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

 

位运算符

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

 

其他运算符

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

 

声明类

声明类需要两个文件:一个头文件(.h)和一个实现文件(.m)

 

头文件应包含(按如下顺序):

1. 所有需要#import的语句或者在前面@class声明;

2. 任何协议声明;

3. @interface声明指定继承自哪个类;

4. 所有可访问的公共变量、属性以及方法;

 

实现文件应包含(按如下顺序):

1. 所有需要的#import语句;

2. 所有的私有变量或属性的种类或者类扩展;

3. @implementation声明指定一个类;

4. 所有的公共或私有方法;

 

如下例子:

MyClass.h

  1. #import "SomeClass.h" 
  2.  
  3. // Used instead of #import to forward declare a class in property return types, etc. 
  4.  
  5. @class SomeOtherClass; 
  6.  
  7. // Place all global constants at the top extern NSString *const kRPErrorDomain; 
  8.  
  9. // Format: YourClassName : ClassThatYouAreInheritingFrom 
  10.  
  11. @interface MyClass : SomeClass 
  12.  
  13. // Public properties first 
  14.  
  15. @property (readonly, nonatomic, strong) SomeClass *someProperty; 
  16.  
  17. // Then class methods 
  18.  
  19. + (id)someClassMethod; 
  20.  
  21. // Then instance methods 
  22.  
  23. - (SomeOtherClass *)doWork; 
  24.  
  25. @end 

 

MyClass.m

  1. #import "MyClass.h" 
  2.  
  3. #import "SomeOtherClass.h" 
  4.  
  5. // Declare any constants at the top 
  6.  
  7. NSString *const kRPErrorDomain = @"com.myIncredibleApp.errors"
  8.  
  9. static NSString *const kRPShortDateFormat = @"MM/dd/yyyy"
  10.  
  11.  
  12. // Class extensions for private variables / properties 
  13.  
  14. @interface MyClass () 
  15.     int somePrivateInt; 
  16.  
  17.     // Re-declare as a private read-write version of the public read-only property 
  18.  
  19.     @property (readwrite, nonatomic, strong) SomeClass 
  20.  
  21. *someProperty; 
  22.  
  23.  
  24. @end 
  25.  
  26.  
  27. @implementation MyClass 
  28.  
  29.  
  30. // Use #pragma mark - statements to logically organize your code 
  31.  
  32. #pragma mark - Class Methods 
  33.  
  34.  
  35. + (id)someClassMethod 
  36. { 
  37.    return [[MyClass alloc] init]; 
  38.  
  39.  
  40. #pragma mark - Init & Dealloc methods 
  41.  
  42. - (id)init 
  43.     if (self = [super init]) { 
  44.  
  45.         // Initialize any properties or setup code here 
  46.     }  
  47.     return self; 
  48.  
  49.  
  50.  
  51. // Dealloc method should always follow init method 
  52.  
  53. - (void)dealloc 
  54.  
  55.     // Remove any observers or free any necessary cache, etc. 
  56.  
  57.     [super dealloc]; 
  58.  
  59. #pragma mark - Instance Methods 
  60.  
  61. - (SomeOtherClass *)doWork 
  62.     // Implement this 
  63.  
  64. @end 

 

实例化

当想要创建类的新实例时,你需要使用如下语法:

  1. MyClass *myClass = [[MyClass alloc] init]; 

alloc类方法返回一个指针指向一个新分配的内存块,这个内存块空间足够大可以储存这个类的一个实例。这个分配的内存中包含了所有Objective-C对象都必须有的实例变量和isa指针。isa指针变量自动初始化指向类对象,类对象分配内存并使实例能够接收消息,比如用来完成初始化的init。

 

预处理器指令

本节仍有需要改进的地方

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

 

编译器指令

请参考literal(字面)章节

 

类和协议

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

 

属性

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

 

错误

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

 

实例变量的可变性

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

默认的是@protected类型,所以不用明确地指定此类型。

 

其他

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

 

Literals(字面语法)

字面语法是的编译器指令,它提供简化符号来创建对象。

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

NSArray访问语法:

  1. NSArray *example = @[ @"hi", @"there", @23, @YES ]; 
  2. NSLog(@"item at index 0: %@", example[0]); 

NSDictionary访问语法:

  1. NSDictionary *example = @{ @"hi" : @"there", @"iOS" : @"people" }; 
  2. NSLog(@"hi %@", example[@"hi"]); 

注意事项:与NSString类似,通过常量数组和字典收集对象是不可变的。相反,你必须在创建这个不可变的字典或者数组后创建一个可变的副本。此外,你不能像使用NSString那样做静态初始化。

 

方法

声明语法

方法没有返回值类型时,用void定义:

  1. // Does not return anything or take any arguments 
  2. - (void)someMethod; 

 

用“+”调用之前声明的类方法:

  1. // Call on a class (e.g. [MyClass someClassMethod]); 
  2. + (void)someClassMethod; 

用“-”调用之前声明的类的实例方法:

  1. // Called on an instance of a class (e.g. [[NSString alloc] init]); 
  2. - (void)someClassInstanceMethod; 

 

在“:”后面声明方法参数,方法签名应该描述参数类型:

  1. // Does something with an NSObject argument 
  2. - (void)doWorkWithObject:(NSObject *)object; 

 

使用强制转换语法声明参数和返回值类型:

  1. // Returns an NSString object for the given NSObject arguments 
  2. - (NSString *)stringFromObject:(NSObject *)objectandSomeOtherObject:(NSObject *)otherObject; 

 

方法调用

使用方括号语法调用方法: [self someMethod]或者[selfsometMethodWithObject:object];

 

self是对包含类的方法的一个引用。self变量存在于所有Objective-C方法中。它是传递给代码用以执行方法的两个隐藏参数之一。另外一个是_cmd,用于识别接收到的消息。

 

有时,很有必要使用[super someMethod];在父类中调用一个方法。

 

在高级选项下,方法通过消息传递实现,并且转换成了这两个C函数其中一个的:

  1. id objc_msgSend(id self, SEL op, ...); 
  2. id objc_msgSendSuper(struct objc_super *super, SEL op, ...); 

 

这有一个很棒的Objective-C教程系列的初学者指南,涵盖了更多关于方法调用的细节。请访问:Calling Methods in Objective-C。(http://ios-blog.co.uk/tutorials/objective-c-guide-for-developers-part-2/#methods)

 

测试选择器

如果你想要测试一个类是否在被发送(或者可能会崩溃)之前响应一个特定的选择器,你可以这样做:

  1. if ([someClassOrInstance respondsToSelector:@selector (someMethodName)]) 
  2.  
  3.     // Call the selector or do something here 

当你实现一个委托,并且在委托对象上调用这些声明之前,你需要对声明为@optional的方法进行测试,这种模式很常见。

 

属性和变量

声明一个Objective-C属性允许你保留类中对象的一个引用或者在类间传递对象。

 

在头文件 ( .h)中声明公共属性:

  1. @interface MyClass : NSObject 
  2. @property (readonly, nonatomic, strong) NSString *fullName; 
  3. @end 

 

在实现文件 ( .m)的匿名类或者扩展类中声明私有属性:

  1. #import "MyClass.h" 
  2.  
  3. // Class extension for private variables / properties 
  4.  
  5. @interface MyClass () 
  6.     // Instance variable 
  7.     int somePrivateInteger; 
  8.  
  9.     // Private properties 
  10.     @property (nonatomic, strong) NSString *firstName; 
  11.     @property (nonatomic, strong) NSString *lastName; 
  12.     @property (readwrite, nonatomic, strong) NSString *fullName; 
  13. @end 
  14.  
  15. @implementation MyClass 
  16.  
  17. // Class implementation goes here 
  18.  
  19. @end 

 

LLVM编译器自动综合所有属性,因此不再需要为属性写明@synthesize语句。当一个属性被综合时,就会创建accessors,允许你设置或者获得属性的值。尽管你可能不会看到它们,因为它们是在构建时创建的,但是一对getter/setter可以显示为:

  1. - (BOOL)finished 
  2.  
  3.     return _finished; 
  4.  
  5. - (void)setFinished:(BOOL)aValue 
  6.  
  7.     _finished = aValue; 

 

你可以重写属性的getter和seeter来创建自定义的行为,或者甚至是使用这个模式来创建瞬态属性,如下:

  1. - (NSString *)fullName 
  2.  return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName]; 

 

属性后面通常会有一个带有前导下划线的实例变量,因此创建一个名为fistName的属性会带有一个名为_firstName的实例变量。如果你重写getter/setter或者你需要在类的init方法中设置ivar,你只需要访问私有实例变量。

 

属性特性

当指定一个属性时,使用如下语法:

  1. @property SomeClass *someProperty; 
  2. // Or 
  3. @property (xxx) SomeClass *someProperty; 

 

xxx可以与什么组合:

【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站  
【转载】Objective-C学习备忘单(一) - 远行的风 - 风的驿站

 

访问属性

使用括号或者点操作都可以访问属性,点操作读起来更清晰:

  1. [self myProperty]; 
  2. // Or 
  3. self.myProperty 

 

局部变量

局部变量只存在于方法的范围内。

  1. - (void)doWork  
  2.    NSString *localStringVariable = @"Some local string variable."
  3.  
  4.    [self doSomethingWithString:localStringVariable]; 

 

命名约定

一般的经验法则: 清晰和简洁都是重要的,但是清晰更重要。

 

方法和属性

都是用驼峰式拼写法,第一个单词的首字母为小写,其他单词的首字母都大写。

 

类名和协议

都是用大写字母,每个单词的首字母都大写。

 

方法

如果执行一些动作,那么应该使用动词(如performInBackground)。你应该推断出知道发生了什么,方法需要什么参数,或者只通过阅读一个方法签名就知道返回了什么。例如:

  1. // Correct 
  2. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
  3.     // Code 
  4.  
  5. // Incorrect (not expressive enough) 
  6. - (UITableViewCell *)table:(UITableView *)tableView cell:(NSIndexPath *)indexPath 
  7.     // Code 

 

属性和局部变量

使用属性时,在内部创建一个带有前导下划线的实例变量,因此创建myVariableName为_myVariableName。然而,Objective-C现在为你综合这些属性,因此你不再需要直接访问带有下划线的实例变量,除非在一个自定义setter中。

 

相反,通常用selfl访问和变异(mutated)实例变量。

 

局部变量不能有下划线。

 

常量

常量通常以k和 XXX命名方式, XXX是一个前缀,或许你的首字母可以避免命名冲突。你不应该害怕你要表达的常量名称,尤其是全局变量时。使用kRPNavigationFadeOutAnimationDuration比fadeOutTiming好的多。

 

Blocks

在Objective-C中,块(block)实际上是一个匿名函数,用来在方法间传递代码或者在函数回调时执行代码。由于Block实现为闭包,周围的语句也被捕获(有时会导致retain cycles)。

 

语法

  1. // As a local variable 
  2. returnType (^blockName)(parameterTypes) = ^returnType(parameters) {  
  3.     // Block code here 
  4. }; 
  5.  
  6.  
  7. // As a property 
  8. @property (nonatomic, copy) returnType (^blockName)(parameterTypes); 
  9.   
  10.  
  11. // As a method parameter 
  12. - (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName { 
  13.    // Block code here 
  14. }; 
  15.  
  16.  
  17. // As an argument to a method call 
  18.  
  19. [someObject someMethodThatTakesABlock: ^returnType (parameters) { 
  20.  
  21.     // Block code here 
  22.  
  23. }]; 
  24.  
  25.  
  26. // As a typedef 
  27. typedef returnType (^TypeName)(parameterTypes); 
  28.  
  29. TypeName blockName = ^(parameters) { 
  30.  
  31.     // Block code here 
  32. }; 

 

查看我们专门的文章了解更多细节Objective-C Programming with blocks

 

变异的block变量

由于block中的变量正是它们在block区域外部的一个快照,你必须在block内将你的变量用_block变异,例如:

  1. __block int someIncrementer = 0; 
  2.  
  3. [someObject someMethodThatTakesABlock:^{ 
  4.  
  5.     someIncrementer++; 
  6.  
  7. }]; 

 

Retain cycles

由于block有力地捕捉区域内的所有变量,你必须谨慎设置block代码,以下为retain cycle的两个例子:

  1. [someObject someMethodThatTakesABlock:^{ 
  2.  
  3.     [someObject performSomeAction];  // Will raise a warning 
  4.  
  5. }]; 
  6.  
  7.  
  8. [self someMethodThatTakesABlock:^{ 
  9.  
  10.     [self performSomeAction];       // Will raise a warning 
  11.  
  12. }]; 

 

这两个例子中,执行block的对象都拥有block,block也拥有对象。这行形成一个回路,或者一个retain cycle,这就意味着内存最终将会泄露。

 

为了解决这个警告你可以重构代码:

  1. [self someMethodThatTakesABlock:^{ 
  2.  
  3.     [object performSomeAction];   // No retain cycle here 
  4.  
  5. }]; 

 

或者你可以用一个_weak对象:

  1. __weak typeof(self) weakSelf = self; 
  2.  
  3. [self someMethodThatTakesABlock:^{ 
  4.  
  5.     [weakSelf performSomeAction];  // No retain cycle here 
  6.  
  7. }]; 

 

转自:http://www.cocoachina.com/applenews/devnews/2014/0428/8255.html





  评论这张
 
阅读(201)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017