SlideShare a Scribd company logo
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:atIndex


int 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)value
serialNumber:(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);
 }

More Related Content

PDF
05 MapKit and Text Input
PDF
14 Saving Loading and Application States
PDF
17 Localization
PDF
16 CoreData
PDF
03 Managing Memory with ARC
PDF
07 View Controllers
PDF
Network and Multitasking
KEY
冲浪 Object-c
05 MapKit and Text Input
14 Saving Loading and Application States
17 Localization
16 CoreData
03 Managing Memory with ARC
07 View Controllers
Network and Multitasking
冲浪 Object-c

What's hot (20)

PPTX
iOS程序设计-数据持久化
PDF
深入淺出 Web 容器 - Tomcat 原始碼分析
PPTX
jQuery源码学习
PPT
Underscore
PPT
面向对象的Js培训
PPTX
Javascript share
PDF
合久必分,分久必合
PPTX
Docker進階探討
PDF
Kissy editor开发与设计
PDF
千呼萬喚始出來的 Java SE 7
PDF
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
PPT
J Query Learn
PPTX
Script with engine
PPT
页游开发中的 Python 组件与模式
PDF
论 Python 与设计模式。
PDF
Node way
PDF
KISSY for starter
PPTX
從 Singleton 談 constructor
PPTX
IOS入门分享
PDF
09 UITableView and UITableViewController
iOS程序设计-数据持久化
深入淺出 Web 容器 - Tomcat 原始碼分析
jQuery源码学习
Underscore
面向对象的Js培训
Javascript share
合久必分,分久必合
Docker進階探討
Kissy editor开发与设计
千呼萬喚始出來的 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
J Query Learn
Script with engine
页游开发中的 Python 组件与模式
论 Python 与设计模式。
Node way
KISSY for starter
從 Singleton 談 constructor
IOS入门分享
09 UITableView and UITableViewController
Ad

Similar to 02 Objective-C (20)

PPT
ios分享
PPT
iPhone,ios,Object-c基础入门
PPT
iPhone,ios,Object-C基础入门
PDF
Objc under the_hood_2013
PDF
iOs app 101
PDF
Programming in Objective-C
PDF
105-2 iOS程式設計(二)
PDF
PDF
PDF
PDF
PDF
PDF
SurveyiOSCodingStyleFromAppleDocument
PDF
Swift 程序语言介绍
PDF
NeteaseBlog Objective-C Style Guide
PDF
掌星 移动互联网开发笔记-Vol001
DOC
Lesson 2 Basicstructure
PDF
I os 02
PDF
Xcode开发员入门导引(简体中文版)
PDF
Xcode开发员入门导引
ios分享
iPhone,ios,Object-c基础入门
iPhone,ios,Object-C基础入门
Objc under the_hood_2013
iOs app 101
Programming in Objective-C
105-2 iOS程式設計(二)
SurveyiOSCodingStyleFromAppleDocument
Swift 程序语言介绍
NeteaseBlog Objective-C Style Guide
掌星 移动互联网开发笔记-Vol001
Lesson 2 Basicstructure
I os 02
Xcode开发员入门导引(简体中文版)
Xcode开发员入门导引
Ad

More from Tom Fan (20)

PDF
PhoneGap 通信原理和插件系统
PDF
HTML5 Web workers
PDF
Web sockets
PDF
Storage
PDF
Semantics
PDF
Multimedia
PDF
Intro to-html5
PDF
Html5 history
PDF
Geolocation
PDF
File api
PDF
Deviceaccess
PDF
Css3
PDF
Webstorage
PDF
Html5 最重要的部分
PDF
AT&T 的 HTML5 策略和应用现状
PDF
PhoneGap 2.0 开发
PDF
Android 平台 HTML5 应用开发
PDF
HTML5 生态系统和应用架构模型
PDF
18 NSUserDefaults
PDF
15 Subclassing UITableViewCell
PhoneGap 通信原理和插件系统
HTML5 Web workers
Web sockets
Storage
Semantics
Multimedia
Intro to-html5
Html5 history
Geolocation
File api
Deviceaccess
Css3
Webstorage
Html5 最重要的部分
AT&T 的 HTML5 策略和应用现状
PhoneGap 2.0 开发
Android 平台 HTML5 应用开发
HTML5 生态系统和应用架构模型
18 NSUserDefaults
15 Subclassing UITableViewCell

02 Objective-C

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