• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
02 Objective-C
 

02 Objective-C

on

  • 282 views

Objective-C 基础:类,实例,对象,消息,初始化方法,类方法,数组,字符串和格式化字符串,访问器,异常

Objective-C 基础:类,实例,对象,消息,初始化方法,类方法,数组,字符串和格式化字符串,访问器,异常

Statistics

Views

Total Views
282
Views on SlideShare
282
Embed Views
0

Actions

Likes
0
Downloads
2
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    02 Objective-C 02 Objective-C Presentation Transcript

    • Objective-C范圣刚,princetoad@gmail.com,www.tfan.org
    • • Objc 基础• 通过⼀一个RandomPossessions 的⼩小程序看⼀一下有 关:类,实例,对象,消息,初始化⽅方法,类⽅方 法,数组,字符串和格式化字符串,访问器,异 常
    • Objective-C• iOS 应⽤用• Objective-C: C 语⾔言的扩展• Cocoa Touch: Objective-C 类的集合• ⾯面向对象编程(object-oriented programming)
    • 对象
    • Party的表⽰示• 属性 • 名称 • ⽇日期 • 受邀⼈人列表• 操作 • 发送email提醒 • 打印名称标签 • 取消party
    • C• 结构体 • 数据成员 • 类型和名称• malloc• C 函数
    • Class•类•实例•结构体成员和实例变量•⽅方法:名称,返回值类型,参数列表,实例变量访问•运⾏行⽅方法:message
    • 使⽤用实例
    • 使⽤用实例• 使⽤用类的实例• 指向对象的变量• 指针变量 -> 对象在内存中的地址• 指向对象的变量声明:Party *partyInstance;• 只是⼀一个可以指向 Party 对象的变量,不是对象本⾝身。
    • 创建对象• 对象的⽣生命周期:被创建,发送消息,不⽤用的时 候销毁• alloc 消息:Party *partyInstance = [Party alloc];• 当你拥有⼀一个指向实例的指针时,就可以向它发 送消息• 第⼀一个消息 -> initialization 消息:[partyInstance init];• 合并:Party *partyInstance = [[Party alloc] init];• nested message send
    • 发送消息
    • 消息剖析• 中括号中• 三个部分 • receiver: ⼀一个指向被要求执⾏行⽅方法的对象的指针 • selector: 要执⾏行的⽅方法的名称 • arguments: 作为参数提供给⽅方法的值• [partyInstance addAttendee:somePerson] • 发送 addAttendee: 消息给 partyInstance(receiver) 触发 addAttendee: ⽅方法(通过 selector 命名)并且传⼊入 somePerson(⼀一个argument)• message 可以有⼀一个参数,多个参数,或者没有参数
    • 发送消息receiver 是被发送消息的 selector 是被触发的⽅方法 arguments 被⽅方法使⽤用对象指针 的名称 [ partyInstance addAttendee: somePerson withDish: deviledEggs ]
    • 其他语⾔言 partyInstance.addAttendeeWithDish(somePerson, deviledEggs)Objective-C [partyInstance addAttendee:somePerson withDish:deviledEggs];
    • 销毁对象• partyInstance = nil;
    • nil • if (venue == nil) ... • if (!venue) ... • 向 nil 变量发送消息 • if (venue) { [venue sendConfirmation]; } • nil-check 是没有必要的
    • 开始 RandomPossessions
    • 把模板代码换成创建和销毁数组实例 #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { // // insert code here... // NSLog(@"Hello, World!"); // 创建⼀一个 mutable 数组对象,把它的地址保存到 items 变量 NSMutableArray *items = [[NSMutableArray alloc] init]; // 销毁 items 指向的对象 items = nil; } return 0; }
    • • ⼀一但实例化完数组以后,我们就可以给它发送消 息了,例如 addObject: 和 insertObject:atIndexint main(int argc, const char * argv[]){ @autoreleasepool {// // insert code here...// NSLog(@"Hello, World!"); // 创建⼀一个 mutable 数组对象,把它的地址保存到 items 变量 NSMutableArray *items = [[NSMutableArray alloc] init]; // 向 items 发送 addObject: 消息,每次传递⼀一个字符串 [items addObject:@"One"]; [items addObject:@"Two"]; [items addObject:@"Three"]; // 发送另外⼀一个消息 insertObject:atIndex 给同样的数组对象 [items insertObject:@"Zero" atIndex:0];
    • • 为了确认这些 string 被添加到了数组,我们来加⼀一段代码把它们打印出来• 构建并运⾏行,看⼀一下控制台的输出 // 遍历数组 for (int i=0; i < [items count]; i++) { // 隐式发送 description 消息 NSLog(@"%@", [items objectAtIndex:i]); }
    • 创建字符串• [items addObject:@”One”];• @符号 + 字符串 = Objective-C 中的硬编码字符串• NSString 的实例• alloc?• @:仅针对 NSString 的⽅方便的⽣生成字符串的缩写 NSString *myString = @"Hello, World!"; int len = [myString length]; len = [@"Hello, World" length]; myString = [[NSString alloc] initWithString:@"Hello, World!"]; len = [myString length];
    • 格式化字符串• NSLog 打印到控制台,接收可变数量的参数• 第⼀一个参数是必须的,⽽而且必须是 NSString 实例,称 作 format string,包含⽂文本和⼀一些 token。• token 以百分号%作为前缀• 每⼀一个传给函数的附加参数替换掉 format string 中的 ⼀一个token• token 同时也指定了他们对应的参数的类型 int a = 1; float b = 2.5; char c = A; NSLog(@"整数: %d 浮点数: %f 字符: %c", a, b, c);
    • %@• 任何对象• description 消息,返回⼀一个 NSString• 所有对象都实现了 description 消息
    • NSArray 和 NSMutableArray• NSArray • 不可变数组 • 实例化之后就不能再增加或者删除对象了• NSMutableArray • NSArray ⼦子类 • 可变数组 • 可以被修改(动态增加删除对象)
    • 指针,引⽤用和内存地址
    • 数组能放什么?• 数组只能持有 Objective-C 对象的引⽤用• 基本数据类型和 C 结构体不能增加到数组• ⼀一个单独的数组可以包含不同类型的对象• 和强类型语⾔言不同
    • 数组操作• ⼤大⼩小:int numberOfObjects = [array count];• addObject: 在数组最后增加对象• insertObject:atIndex: 在特定位置插⼊入对象• 注意:不能往数组中增加 nil ,可以使⽤用 NSNull • [array addObject:[NSNull null]]• objectAtIndex: 获取数据
    • ⼦子类化⼀一个 Objective-C 类• 层次结构 (hierarchy)• 只有⼀一个超类(superclass)• NSObject • root class • ⾓角⾊色是实现所有 Cocoa Touch 中的对象的基本⾏行为 • alloc, init, description
    • 类的层次结构• 扩展• 重写
    • 创建⼀一个NSObject 的⼦子类• target 勾选• BNRItem, BNRItem.h, BNRItem.m• 保留所有的 C 语⾔言关键字• Objective-C 额外的关键字使⽤用@前缀区分• 关键字 @interface 在 Objective-C 中声明⼀一个类• 冒号后跟⽗父类• 只允许单⼀一继承 • @interface ClassName : SuperclassName • @end 指⽰示类已经被完全声明了
    • 实例变量类的实例变量紧跟类的声明之后,在⼤大括号中进⾏行声明#import <Foundation/Foundation.h>@interface BNRItem : NSObject{ NSString *itemName; NSString *serialNumber; int valueInDollars; NSDate *dateCreated;}@end
    • BNRItem 实例
    • 访问器⽅方法• 有了实例变量之后,要能够 get,或 set 他们的值• get/set 实例变量的⽅方法称作 accessors, 或者分别 叫做getters 和 setters.• Objective-C 的 setter ⽅方法名:set + 实例变量名• getter ⽅方法名:和实例变量名⼀一样
    • BNRItem 访问器⽅方法#import <Foundation/Foundation.h>@interface BNRItem : NSObject{ NSString *itemName; NSString *serialNumber; int valueInDollars; NSDate *dateCreated;}- (void)setItemName:(NSString *)str;- (NSString *)itemName;- (void)setSerialNumber:(NSString *)str;- (NSString *)serialNumber;- (void)setValueInDollars:(int)i;- (int)valueInDollars;- (NSDate *)dateCreated;@end
    • 实例⽅方法 • description • 重写:在实现⽂文件中定义,不需要再做声明// 重写 description- (NSString *)description{ NSString *descriptionString = [[NSString alloc] initWithFormat:@"%@ (%@): 价值 $%d, 登记⽇日期 %@", itemName, serialNumber, valueInDollars, dateCreated]; return descriptionString;}
    • 初始化器• alloc -> ⽣生成⼀一个实例,返回⼀一个指向它的指针• init -> 给所有的实例变量初始化值• ⾃自定义初始化过程简化代码• 命名习惯:以init开头
    • BNRItem 的 Initializer• ⽅方法名(或者叫selector)是: initWithItemName:valueInDollars:serialNumber:• 这个selector 具有三个 label:initWithItemName:, valueInDollars:, 和 serialNumber:。表明⽅方法接收三 个参数• 这些参数每个都有⼀一个类型和⼀一个参数名• 类型在圆括号中,参数名紧跟类型 } - (id)initWithItemName:(NSString *)name valueInDollars:(int)value serialNumber:(NSString *)sNumber; - (void)setItemName:(NSString *)str;
    • id• 返回值类型是id• 指向任意对象的指针• BNRItem * ?• ⼦子类化的问题
    • isa• 从 initializer 返回的对象的类型我们是知道的(向 类发送 alloc )• 对象⾃自⾝身也知道它⾃自⼰己的类型 isa 指针• 每个对象都有⼀一个名为 isa 的实例变量• 当⼀一个实例通过向类发送 alloc 创建的时候,类把 返回的对象的 isa 实例变量设成指回到⽣生成它的类• isa 指针的意思就是说这个对象是⼀一个这个类的实 例
    • isa 指针
    • 实现designated initializer • 第⼀一件事,使⽤用 super 调⽤用超类的初始化器 • 最后,使⽤用 self 返回成功初始化过的对象// 实现初始化⽅方法- (id)initWithItemName:(NSString *)name valueInDollars:(int)valueserialNumber:(NSString *)sNumber{ // 调⽤用⽗父类的指定的初始化器 self = [super init]; // 给实例变量初始化值 [self setItemName:name]; [self setSerialNumber:sNumber]; [self setValueInDollars:value]; dateCreated = [[NSDate alloc] init]; // 返回初始化对象的地址 return self;}
    • 理解 self• 在⽅方法内部,self 是隐式的本地变量• 不需要声明,⾃自动设成指向被发送消息的对象• 可以⽤用于给⾃自⾝身发消息的情况下• return self;
    • 理解 super• 重写⽅方法时保持超类⽅方法中的操作,在其上增加 新的内容• super:编译器指⽰示符• 指定名称的⽅方法的查找顺序:对象类⾃自⾝身 -> 超类 -> 超类的超类• 给 super 发消息,直接跳过 self 本⾝身, 从其超类 开始• initializer 失败的话返回 nil• self = [super init];
    • 其他初始化器以及初始化链 • ⼀一个或多个初始化⽅方法 • 初始化⽅方法链式调⽤用的好处 • 减少出错的机会 • 代码更容易维护// 使⽤用初始化⽅方法链,没有的参数可以传⼊入默认值- (id)initWithItemName:(NSString *)name{ return [self initWithItemName:name valueInDollars:0 serialNumber:@""];}
    • 重写 init- (id)init{ return [self initWithItemName:@"Item" valueInDollars:0 serialNumber:@""];}
    • Initializer 链
    • initializer 简单规则• 类从其超类继承了所有的 initializer,同时可以根据 其⺫⽬目的任意增加• 每个类选择⼀一个 initializer 作为其 designated initializer• designated initializer 调⽤用超类的 designated initializer• 类的任意其他 initializer 调⽤用类的 designated initializer• 如果类声明了⼀一个和其超类不同的 designated initializer,超类的 designated initializer 必须被重写 来调⽤用新的 designated initializer
    • 使⽤用 initializer• 检查重写的 init 是否⽣生效• 使⽤用 designated initializer 替换掉设置实例变量的 代码
    • 类⽅方法• ⽅方法 • 实例⽅方法 • 类⽅方法• 实例⽅方法被发送给类的实例(像init)• 类⽅方法被发送给类本⾝身(像alloc)• 类⽅方法⼀一般不是被⽤用来创建⼀一个类的新的实例, 就是⽤用来提取类的⼀一些全局属性• 类⽅方法不能在实例上操作,或者访问实例变量
    • 声明类⽅方法• 实例⽅方法的声明: 在返回值前⾯面 使⽤用减号“-” 表⽰示• 类⽅方法的声明:使⽤用加号“+” 字符• convenience method:stringWithFormat, randomItem, 返回⾃自⾝身类型的对象• 类⽅方法中的 self • 指向类本⾝身,⽽而不是实例 • ⼦子类调⽤用的问题
    • 测试⼦子类 for (int i=0; i<10; i++) { BNRItem *p = [BNRItem randomItem]; [items addObject:p]; } for (int i = 0; i < 10; i++) { NSLog(@"%@", [items objectAtIndex:i]); }
    • 异常和⽆无法识别的 Selectors
    • 异常• ⼀一个对象只会响应它的类实现了相关⽅方法的消息• 动态类型的objc,编译时⽆无法确定• 异常exception,run-time errors(运⾏行时错误,和 编译时错误相对compile-time errors)
    • 快速枚举 for (int i = 0; i < 10; i++) { NSLog(@"%@", [items objectAtIndex:i]); }• Objective-C 2.0 引⼊入了fast enumeration for (BNRItem *item in items) { NSLog(@"%@", item); }