www.2527.com_澳门新葡8455手机版_新京葡娱乐场网址_
做最好的网站

IOS暑假小学期实训,内容根据iOS编程编写

2019-09-16 08:45 来源:未知

现在好多Dev都开始创建并使用工具类,因为把一些很多地方用到得方法写到工具类里面会显得很简单明了,最主要的是使用起来方便。这里想用了直接包含以下头文件调用以下就可以,比如iToast类,只是显示一个类似安卓提示的一个小黑框而已,每次只需要调用一下传进去要显示的字符串就可以了。---哎呀废话太多了。现在我跟大家分享下自己创建的工具类

Objective-C 对象(内容根据iOS编程编写),objective-cios

  开发iOS程序需要使用 Objective-C 语言和Cocoa Touch框架。Objective-C 源于 C 语言,是 C 语言的扩展。 Cocoa Touch框架是一个Objective-C类的集合。本篇文章用来介绍一些Objective-C基础知识。

  •   对象

  假设有一场聚会。该聚会有若干特有的属性,例如聚会的名称,日期和一根受邀请的名单。此外,还有“聚会”需要做些事情,比如向受邀请者发送一封提醒邮件,或者取消聚会。

  如果使用C语言,那么我们可以定义一个 结构体 ,用于保存这场聚会的数据类型。

  如果使用 Objective-C 来定义这些数据类型,我们就需要用到 类 。 类就像是制造汽车的工厂,通过工厂(类:聚会)我们可以制造汽车(具体的某一场特性的聚会),这些汽车都是工厂的的实例,每个实例对象都能为某一个特定的聚会保存数据。

  所有的对象,都是在内存中的一块数据,类似于结构体。对象要通过实例变量保存属性(例如:汽车的颜色,形状,型号。聚会的名称,等都是属性)。在  Objective-C 中实例变量名之前通常会加上一个下划线。因此,我们的 Party 对象定义实例变量: _name(名称),_date(日期),_budget(预算) 消息 

  •   使用对象

  

  要使用某个类的对象,就需要必须先得到一个指向该对象的变量。 这类“指针变量”保存的就是对象在内存中的地址。申明实例 Party * partyInstance  。知识创建了一个对阵,并没有创建任何对象,仅仅申明了一个可以指向某个Party的指针变量。

  创建对象

对象是有生命周期的,出生到死亡。首先是被创建出来,之后介绍消息,最后不需要的时候要被释放。

创建类实例变量 Party * partyInstance = [[Party alloc] init]; 这种完成初始化的方法叫做“嵌套消息发送”,在oc编程中是很常见的。

 

发送消息

一旦某个对象完成了初始化,就可以向其发送消息。消息必须写到一个方括号正,一个消息包含三个部分:

  1. 接收方 :指针,指向执行方法的对象

  2. 选择器 :需要执行方法的方法名

  3. 实参    :一边两形式传给方法的数值

下面我们以Party为例,向Party发送 addAttendee:消息  [partyInstance addAttendee:somePerson] ,这里我们向 partyInstance(接收方)发送 addAttendee:方法(取决于选择器)并传入 somePerson(实参);在iOS中可以有很多参数,也可以没有参数

 

释放对象

将指向对象的变量设置为 nil,可以要求程序释放该对象; partyInstance = nil; 表示会释放 partyInstance 变量所指向的对象;在iOS中允许向 nil 发送消息。

  • 编写第一个命令行工具 RandomItems

选择Xcode,进入命令行工具,RandomItems的第一个版本将创建一个包含4个字符串的数组。 数组 包含一组按照顺序排列的对象,可以通过下表索引来存取数组中数据。跟 Python 中的 list 比较相似。

 1 #import <Foundation/Foundation.h>
 2 
 3 int main(int argc, const char * argv[]) {
 4     @autoreleasepool {
 5         // 创建一个NSMutableArray对象,并用items变量保存该对象的地址
 6         NSMutableArray * items = [[NSMutableArray alloc] init];
 7         
 8         // 向items 所指向的NSMutableArray对象发送addObject:消息
 9         // 每次传入一个字符串
10         [items addObject:@"One"];
11         [items addObject:@"Two"];
12         [items addObject:@"Three"];
13         
14         // 继续向同一个对象发送消息,这次是insertObject:atIndex:
15         [items insertObject:@"Zero" atIndex:0];
16         
17         // 释放items 所指向的 NSMutableArray 对象
18         items = nil;
19     }
20     return 0;
21 }

  每次加入的对象是一个NSString字符串对象,可以通过 @“” 来快速创建一个字符串。

  2.  遍历数组

  这里我们可以直接使用for循环,也可以使用快速遍历。使用for循环的原理是:数组中下标索引是从0开始,到数组中最后一个对象是数组总数量-1.

 1 #import <Foundation/Foundation.h>
 2 
 3 int main(int argc, const char * argv[]) {
 4     @autoreleasepool {
 5         // 创建一个NSMutableArray对象,并用items变量保存该对象的地址
 6         NSMutableArray * items = [[NSMutableArray alloc] init];
 7         
 8         // 向items 所指向的NSMutableArray对象发送addObject:消息
 9         // 每次传入一个字符串
10         [items addObject:@"One"];
11         [items addObject:@"Two"];
12         [items addObject:@"Three"];
13         
14         // 继续向同一个对象发送消息,这次是insertObject:atIndex:
15         [items insertObject:@"Zero" atIndex:0];
16         
17         // 使用for循环来遍历数组中对象
18         for (NSInteger i = 0; i < items.count; i  ) {
19             NSString * item = [items objectAtIndex:i];
20             NSLog(@"%@",item);
21         }
22         
23         // 释放items 所指向的 NSMutableArray 对象
24         items = nil;
25     }
26     return 0;
27 }

  输出结果:

1 2016-09-03 08:04:50.323 RandomItems[5255:279975] Zero
2 2016-09-03 08:04:50.324 RandomItems[5255:279975] One
3 2016-09-03 08:04:50.324 RandomItems[5255:279975] Two
4 2016-09-03 08:04:50.324 RandomItems[5255:279975] Three

  当然,我们同样可以使用快速遍历的方法来输出结果:

1         // 使用快速枚举法来遍历
2         for (NSString * item in items) {
3             NSLog(@"%@",item);
4         }

  这段代码同样可以工作。这种遍历数组的语法出错率更低,更重要的是经过编译器的优化,通常比for循环更快。在数组比较多,或者比较调用比较频繁的时候最好使用这种方法。但是有一个限制,如果需要在循环体中添加或者删除对象,那么就不能使用快速枚举方法。

  现在我们来对这段代码进行简单剖析。在我们创建的RandItems程序中一共有5个对象:其中一个是  NSMutableArray  对象,4个  NSString 对象。

  1. 使用快捷键  command N  来创建一个新的文件,之后选中 OS X -> Source来创建一个新的文件,可以选则文件存放位置等。这里我们命名为 JXItem

  2. 新创建的类文件继承至  NSObject 创建好文件之后在代码控制板中我们可以发现有两个文件: JXItem.h  JXItem.m ;其中 .h 文件是头文件,也叫作接口文件,赋值声明类的类名,父类,实例变量及该类实现的全部方法; .m 文件就是一个实现文件,用来包含该 .h文件中中声明的全部方法等。

  实例变量:

  实例变量就相当于我们真是世界中的 比如说你拥有的一辆汽车,汽车有品牌,颜色,价钱等固有属性;实例变量就相对于我们真是世界中的物品的属性。下面我们来声明一些实例变量。

 1 #import <Foundation/Foundation.h>
 2 
 3 @interface JXItem : NSObject
 4 {
 5     NSString *_itemName;
 6     NSString *_serialNumber;
 7     int _valueInDollars;
 8     NSDate *_dateCreated;
 9 }
10 @end

  声明了实例变量之后就相当于我们在声明每个 JXItem 对象之后都会在内存中有四个空位,用来存放我们声明的实例变量(物体的属性)。其中一个是用来存放  int 证书,另外三个用来存放指向对象的指针,分别是两个指向  NSString 对象和一个 NSDate 对象。

  存取实例变量:

  给对象添加了实例变量之后,我们要开始使用它,通过添加存取变量的方法,我们就可以顺利的使用这些数据,这样的方法在OC中我们叫做  存取方法 。如果是既可以存进去,也可以取出来的我们叫做存取方法;如果是只能读出来,但是不能存进去的我们叫做只读的,这类属性只需要取方法。

 1 #import <Foundation/Foundation.h>
 2 
 3 @interface JXItem : NSObject
 4 {
 5     NSString *_itemName;
 6     NSString *_serialNumber;
 7     int _valueInDollars;
 8     NSDate *_dateCreated;
 9 }
10 
11 // 存方法
12 - (void)setItemName:(NSString *)str;
13 // 取方法
14 - (NSString *)itemName;
15 
16 - (void)setSerialNumber:(NSString *)str;
17 - (NSString *)serialNumber;
18 
19 - (void)setValueInDollars:(int)v;
20 - (in)valueInDollars;
21 
22 - (NSDate *)dateCreated;
23 @end

  在OC中,村方法的命名规则为英文set加上要修改的实例变量的变量名(首字母要大写)。

  接下来我们开始实现存取方法。任何一个类的实现文件,都必须在顶部导入自己的头文件。类的实现需要知道响应你的类是如何声明的。在OC中我们使用 #import 来导入,作用和C语言中  #include 作用相同。唯一的差别是 #import 可以确保不会重复导入用一个文件,所以在OC中建议使用 #import 

 1 #import "JXItem.h"
 2 
 3 @implementation JXItem
 4 
 5 - (void)setItemName:(NSString *)str {
 6     _itemName = str;
 7 }
 8 - (NSString *)itemName {
 9     return _itemName;
10 }
11 
12 - (void)setSerialNumber:(NSString *)str {
13     _serialNumber = str;
14 }
15 - (NSString *)serialNumber {
16     return _serialNumber;
17 }
18 
19 - (void)setValueInDollars:(int)v {
20     _valueInDollars = v;
21 }
22 - (int)valueInDollars {
23     return _valueInDollars;
24 }
25 
26 - (NSDate *)dateCreated {
27     return _dateCreated;
28 }
29 @end

  在这段代码中,存方法是将传入的参数直接赋值给了实例变量,当然也可以将传入的参数进行一定的运算之后传给实例变量;取方法则就是取得是返回实例变量的值。

  下面,我们开始测试新创建的类和存取方法。首先在 main.m 中导入  JXItem.h 头文件。因为 JXItem 类位于仅包含自己一个类的类文件中,所以必须要明确的导入,否则编译器编译的时候就会报错。

 1 #import <Foundation/Foundation.h>
 2 #import "JXItem.h"
 3 
 4 int main(int argc, const char * argv[]) {
 5     @autoreleasepool {
 6         // 创建一个NSMutableArray对象,并用items变量保存该对象的地址
 7         NSMutableArray * items = [[NSMutableArray alloc] init];
 8         
 9         // 向items 所指向的NSMutableArray对象发送addObject:消息
10         // 每次传入一个字符串
11         [items addObject:@"One"];
12         [items addObject:@"Two"];
13         [items addObject:@"Three"];
14         
15         // 继续向同一个对象发送消息,这次是insertObject:atIndex:
16         [items insertObject:@"Zero" atIndex:0];
17 
18         // 使用快速枚举法来遍历
19         for (NSString * item in items) {
20             NSLog(@"%@",item);
21         }
22         
23         JXItem * item = [[JXItem alloc] init];
24         NSLog(@"%@ %@ %@ %d",item.itemName,item.dateCreated,item.serialNumber,item.valueInDollars);
25         
26         // 释放items 所指向的 NSMutableArray 对象
27         items = nil;
28     }
29     return 0;
30 }

  打印结果:

1 2016-09-04 08:31:50.302 RandomItems[9471:742805] Zero
2 2016-09-04 08:31:50.303 RandomItems[9471:742805] One
3 2016-09-04 08:31:50.303 RandomItems[9471:742805] Two
4 2016-09-04 08:31:50.303 RandomItems[9471:742805] Three
5 2016-09-04 08:31:50.303 RandomItems[9471:742805] (null) (null) (null) 0
6 Program ended with exit code: 0

  可以看到现在我们仅仅初始化了我们创建的类,并没有将之赋值,所以的实例变量都是默认值。因为当实例变量是指向对象的指针,那么相应的初始值为nil;而如果实例变量是int这样的基本类型,那么其值就会是0 。

  下面,我们为新创建的对象设置一些有意义的值。

 1 #import <Foundation/Foundation.h>
 2 #import "JXItem.h"
 3 
 4 int main(int argc, const char * argv[]) {
 5     @autoreleasepool {
 6         // 创建一个NSMutableArray对象,并用items变量保存该对象的地址
 7         NSMutableArray * items = [[NSMutableArray alloc] init];
 8         
 9         // 向items 所指向的NSMutableArray对象发送addObject:消息
10         // 每次传入一个字符串
11         [items addObject:@"One"];
12         [items addObject:@"Two"];
13         [items addObject:@"Three"];
14         
15         // 继续向同一个对象发送消息,这次是insertObject:atIndex:
16         [items insertObject:@"Zero" atIndex:0];
17 
18         // 使用快速枚举法来遍历
19         for (NSString * item in items) {
20             NSLog(@"%@",item);
21         }
22         
23         JXItem * item = [[JXItem alloc] init];
24         item.itemName = @"Ferrari";
25         item.serialNumber = @"PC23138";
26         item.valueInDollars = 783234;
27         NSLog(@"%@ %@ %@ %d",item.itemName,item.dateCreated,item.serialNumber,item.valueInDollars);
28         
29         // 释放items 所指向的 NSMutableArray 对象
30         items = nil;
31     }
32     return 0;
33 }

  打印结果:

1 2016-09-04 08:41:44.566 RandomItems[9554:749674] Zero
2 2016-09-04 08:41:44.567 RandomItems[9554:749674] One
3 2016-09-04 08:41:44.567 RandomItems[9554:749674] Two
4 2016-09-04 08:41:44.567 RandomItems[9554:749674] Three
5 2016-09-04 08:41:44.567 RandomItems[9554:749674] Ferrari (null) PC23138 783234
6 Program ended with exit code: 0

  解释:有些人可能会纳闷,这里我们并没有调用 set方法来给我们自定义的类的实例变量来赋值,为什么这里就可以打印出来了。这是因为我们这里使用了点语法。 点语法的格式为:消息接受者(item)后面加上一个 “.” ,在加上实例变量的名字。这样子就可以取代我们的 set方法。值得注意的是,点语法虽然很方便,但是会经常给我们造成困扰,你会发现点语法放在等号的左边和右边效果是不一样的。他们的区别是:如果点语法用在赋值号的左边,就表示存方法(set方法);如果在右边就代表是取方法。

类方法和实例方法

  在OC中,方法可以分为类方法和实例方法。

  类方法的作用通常是创建一个对象,获取类的某些全局的属性。类方法不会创建到对象上,也不会存取实例变量。类就好比是一个法拉利工作,对象就是一台法拉利。工厂只会有一些生产规划时间等,而某个法拉利自身的属性,比如说是创建时间,只有他自己知道,工厂只能知道在一段时间内有多少台法拉利被生产。

  实例变量方法:用来操作类的对象。

  当我们调用实例方法时,需要向类的对象发送消息;调用类方法时,只需要向类本身发送消息。

  例如,我们在创建  JXItem 对象的时候,首先向  JXItem 类发送  alloc (类方法)消息,然后使用  alloc 方法创建的对象发送 init (实例方法)消息。

 

覆盖方法

  子类可以覆盖父类的方法。我们这里以  description 为例,向某个  NSObject 对象发送  description 消息是,可以得到一个  NSString 对象来描述当当前对象的类名和其在内存中的地址信息。通常格式为  <JXItem: 0x1002042b0>  。 下面我们来尝试覆盖整个方法,来自定义。

 1 #import "JXItem.h"
 2 
 3 @implementation JXItem
 4 
 5 - (void)setItemName:(NSString *)str {
 6     _itemName = str;
 7 }
 8 - (NSString *)itemName {
 9     return _itemName;
10 }
11 
12 - (void)setSerialNumber:(NSString *)str {
13     _serialNumber = str;
14 }
15 - (NSString *)serialNumber {
16     return _serialNumber;
17 }
18 
19 - (void)setValueInDollars:(int)v {
20     _valueInDollars = v;
21 }
22 - (int)valueInDollars {
23     return _valueInDollars;
24 }
25 
26 - (NSDate *)dateCreated {
27     return _dateCreated;
28 }
29 
30 - (NSString *)description {
31     NSString * descriptionString = [[NSString alloc] initWithFormat:@"%@ (%@): Worth $%d,recorded on %@",self.itemName,self.serialNumber,self.valueInDollars,self.dateCreated];
32     return descriptionString;
33 }
34 @end

  调用方法:

 1 #import <Foundation/Foundation.h>
 2 #import "JXItem.h"
 3 
 4 int main(int argc, const char * argv[]) {
 5     @autoreleasepool {
 6         // 创建一个NSMutableArray对象,并用items变量保存该对象的地址
 7         NSMutableArray * items = [[NSMutableArray alloc] init];
 8         
 9         // 向items 所指向的NSMutableArray对象发送addObject:消息
10         // 每次传入一个字符串
11         [items addObject:@"One"];
12         [items addObject:@"Two"];
13         [items addObject:@"Three"];
14         
15         // 继续向同一个对象发送消息,这次是insertObject:atIndex:
16         [items insertObject:@"Zero" atIndex:0];
17 
18         // 使用快速枚举法来遍历
19         for (NSString * item in items) {
20             NSLog(@"%@",item);
21         }
22         
23         JXItem * item = [[JXItem alloc] init];
24         item.itemName = @"Ferrari";
25         item.serialNumber = @"PC23138";
26         item.valueInDollars = 783234;
27         NSLog(@"%@",item);
28         
29         // 释放items 所指向的 NSMutableArray 对象
30         items = nil;
31     }
32     return 0;
33 }

  打印结果:

1 2016-09-04 09:16:59.595 RandomItems[9666:763580] Zero
2 2016-09-04 09:16:59.596 RandomItems[9666:763580] One
3 2016-09-04 09:16:59.596 RandomItems[9666:763580] Two
4 2016-09-04 09:16:59.596 RandomItems[9666:763580] Three
5 2016-09-04 09:16:59.596 RandomItems[9666:763580] Ferrari (PC23138): Worth $783234,recorded on (null)

  解释:当我们在程序中调用  NSLog(@"%@",item); 这句话会首先调用  description 方法。

 

  •   初始化方法

  我们创建的  JXItem  目前还只能充  NSObject  类继承来的  init 方法来初始化对象。现在我们就来创建两个新的实例方法用于初始化对象;这种用于初始化类的对象的方法我们称之为初始化方法。

 1 #import <Foundation/Foundation.h>
 2 
 3 @interface JXItem : NSObject
 4 {
 5     NSString *_itemName;
 6     NSString *_serialNumber;
 7     int _valueInDollars;
 8     NSDate *_dateCreated;
 9 }
10 
11 // 初始化方法
12 - (instancetype)initWithItemName:(NSString *)name
13                   valueInDollars:(int)value
14                     serialNumber:(NSString *)sNumber;
15 
16 - (instancetype)initWithItemName:(NSString *)name;
17 // 存方法
18 - (void)setItemName:(NSString *)str;
19 // 取方法
20 - (NSString *)itemName;
21 
22 - (void)setSerialNumber:(NSString *)str;
23 - (NSString *)serialNumber;
24 
25 - (void)setValueInDollars:(int)v;
26 - (int)valueInDollars;
27 
28 - (NSDate *)dateCreated;
29 @end

  每个初始化方法的方法名都会以 init 开头。这种初始化方法的命名模式只是一种约定,但是在 OC 中我们应该严格遵守这种约定。这类自定义的初始化方法一般都会带有参数,为的就是应付各种不同的初始化需要。

 

  • 指定初始化方法

  任何一个类,不管有多少个初始化方法,都必须选定其中一个作为 指定初始化 方法。

  instancetype

  上面我们创建的两个初始化方法的返回值类型都是  instancetype 。该关键字表示方法的返回类型个调用方法的对象类型相同。 init 方法的返回类型都应该声明为  instancetype 。这里可能会有疑问,为什么我们不反悔这个类本身的类型呢?这是因为我们有可能会继续写一个类来继承这个类,由于子类可以继承父类的方法,其中包括初始化方法和返回类型。如果是这个类的子类调用初始化方法,那么返回同样是这个类对象,而不是这个类的子类对象。所以为了避免这个问题,我们使用  instancetype 来动态获取当前类对象。

  实现JXItem类的指定初始化方法

  在  JXItem.m 中为该类实现指定初始化方法

 1 #import "JXItem.h"
 2 
 3 @implementation JXItem
 4 - (instancetype)initWithItemName:(NSString *)name
 5                   valueInDollars:(int)value
 6                     serialNumber:(NSString *)sNumber {
 7     // 调用父类的初始化方法
 8     self = [super init];
 9     
10     // 判断父类的指定初始化方法是否是成功创建
11     if (self) {
12         // 为实例变量设置初始值
13         _itemName = name;
14         _serialNumber = sNumber;
15         _valueInDollars = value;
16         
17         // 设置 _dateCreated 的值为系统当前时间
18         // 因为我们没有为该实例变量设置 set 方法来从外部获取 (只是一个只读属性)
19         _dateCreated = [NSDate date];
20     }
21     // 返回初始化后的对象的新地址
22     return self;
23     
24 }
25 
26 - (void)setItemName:(NSString *)str {
27     _itemName = str;
28 }
29 - (NSString *)itemName {
30     return _itemName;
31 }
32 
33 - (void)setSerialNumber:(NSString *)str {
34     _serialNumber = str;
35 }
36 - (NSString *)serialNumber {
37     return _serialNumber;
38 }
39 
40 - (void)setValueInDollars:(int)v {
41     _valueInDollars = v;
42 }
43 - (int)valueInDollars {
44     return _valueInDollars;
45 }
46 
47 - (NSDate *)dateCreated {
48     return _dateCreated;
49 }
50 
51 - (NSString *)description {
52     NSString * descriptionString = [[NSString alloc] initWithFormat:@"%@ (%@): Worth $%d,recorded on %@",self.itemName,self.serialNumber,self.valueInDollars,self.dateCreated];
53     return descriptionString;
54 }
55 @end

  初始化方法中的实例变量

  在自定义的初始化方法中我们可以看到有在初始化实例变量。但是在OC中有个雷区就是千万不要直接访问实例变量,最好直接通过存取方法来访问。但是这个雷区在初始化方法总相反,我们要直接访问实例变量

  其他初始化方法与初始化方法链

  接下来我们来实现第二个初始化方法。实现  initWithItemName:(NSString *)name 方法时,我们不需要再将其他初始化方法搬过来重新写一遍。这里我们只需要调用一下其他指定初始化方法,将我们获取到的实参作为 _itemName 传入,其他的实参则使用某个默认值传入

  JXItem 还有一个默认的初始化方法  init 。如果我们直接向对象发送这个消息,那么程序就不会调用我们自定义的初始化方法,辛苦白费了。当然了,我们是不会让这种情况发生的。

 1 #import "JXItem.h"
 2 
 3 @implementation JXItem
 4 - (instancetype)initWithItemName:(NSString *)name
 5                   valueInDollars:(int)value
 6                     serialNumber:(NSString *)sNumber {
 7     // 调用父类的初始化方法
 8     self = [super init];
 9     
10     // 判断父类的指定初始化方法是否是成功创建
11     if (self) {
12         // 为实例变量设置初始值
13         _itemName = name;
14         _serialNumber = sNumber;
15         _valueInDollars = value;
16         
17         // 设置 _dateCreated 的值为系统当前时间
18         // 因为我们没有为该实例变量设置 set 方法来从外部获取 (只是一个只读属性)
19         _dateCreated = [NSDate date];
20     }
21     // 返回初始化后的对象的新地址
22     return self;
23     
24 }
25 
26 - (instancetype)initWithItemName:(NSString *)name {
27     return [self initWithItemName:name
28                    valueInDollars:0
29                      serialNumber:@""];
30 }
31 
32 // 默认的初始化方法,调用自定义的初始化方法,并将之出入一个默认值
33 - (instancetype)init {
34     return [self initWithItemName:@"Item"];
35 }
36 
37 - (void)setItemName:(NSString *)str {
38     _itemName = str;
39 }
40 - (NSString *)itemName {
41     return _itemName;
42 }
43 
44 - (void)setSerialNumber:(NSString *)str {
45     _serialNumber = str;
46 }
47 - (NSString *)serialNumber {
48     return _serialNumber;
49 }
50 
51 - (void)setValueInDollars:(int)v {
52     _valueInDollars = v;
53 }
54 - (int)valueInDollars {
55     return _valueInDollars;
56 }
57 
58 - (NSDate *)dateCreated {
59     return _dateCreated;
60 }
61 
62 - (NSString *)description {
63     NSString * descriptionString = [[NSString alloc] initWithFormat:@"%@ (%@): Worth $%d,recorded on %@",self.itemName,self.serialNumber,self.valueInDollars,self.dateCreated];
64     return descriptionString;
65 }
66 @end

  下面我们来观察一下初始化之间的关系

[super init] )

  4.  如果某个类所声明的指定初始化方法与其父类的不同,就必须覆盖父类的指定初始化方法,并调用新的指定的初始化方法

 

  使用初始化方法

  

 1 #import <Foundation/Foundation.h>
 2 #import "JXItem.h"
 3 
 4 int main(int argc, const char * argv[]) {
 5     @autoreleasepool {
 6         // 创建一个NSMutableArray对象,并用items变量保存该对象的地址
 7         NSMutableArray * items = [[NSMutableArray alloc] init];
 8         
 9         // 向items 所指向的NSMutableArray对象发送addObject:消息
10         // 每次传入一个字符串
11         [items addObject:@"One"];
12         [items addObject:@"Two"];
13         [items addObject:@"Three"];
14         
15         // 继续向同一个对象发送消息,这次是insertObject:atIndex:
16         [items insertObject:@"Zero" atIndex:0];
17 
18         // 使用快速枚举法来遍历
19         for (NSString * item in items) {
20             NSLog(@"%@",item);
21         }
22         
23         JXItem * item = [[JXItem alloc] initWithItemName:@"Ferrari" valueInDollars:783234 serialNumber:@"PC23138"];
24         NSLog(@"%@",item);
25         
26         // 释放items 所指向的 NSMutableArray 对象
27         items = nil;
28     }
29     return 0;
30 }

  运行结果:

1 2016-09-04 10:33:33.600 RandomItems[9893:797491] Zero
2 2016-09-04 10:33:33.600 RandomItems[9893:797491] One
3 2016-09-04 10:33:33.600 RandomItems[9893:797491] Two
4 2016-09-04 10:33:33.601 RandomItems[9893:797491] Three
5 2016-09-04 10:33:33.608 RandomItems[9893:797491] Ferrari (PC23138): Worth $783234,recorded on 2016-09-04 02:33:33  0000
6 Program ended with exit code: 0

 

  • 异常与未知选择器

  在运行的时候,当某个对象收到消息后,会根据创建该对象的类,执行和相应的消息匹配的方法。这种特性和多数编译语言不同,在这些编译语言中,需要执行的方法在编译时就决定了。

  在OC 中,所有对象都有一个名为  isa 的实例变量。对象可以通过 isa 知道自身的类型。类在创建了一个对象后,就会为新创建的对象的 isa 实例变量进行赋值,将其指向自己,即创建该对象的类,虽然在开发中很少用,但是 OC 的很多特性都源自于 isa 实例变量。

  对象只能响应(respond)类(isa指向的类)中具有响应实现方法的消息。而对象的类型又只能在运行时才能确定,因此xcode没办法在编译时判断某个对象是否能响应特定的消息。如果xcode判断应用汇先给某个对象发送其无法响应的消息,只能显示警告,但是不会报错。  

对象(内容根据iOS编程编写),objective-cios 开发iOS程序需要使用Objective-C语言和Cocoa Touch框架。Objective-C 源于 C 语言,是 C 语言的扩...

2016/07/09

1.创建工具类

很显然是继承自NSObject的,自己打开Xcode创建一个继承自NSObject的类,我的起名字叫做KK_Utils,在.h中写类名,全部是类方法,调用起来方便,在.m中实现。

OC基本语法

//

//  main.m

//  OC基本语法

//

//  Created by lanou on 16/7/9.

//  Copyright © 2016年yhy. All rights reserved.

//

#import

int main(int argc, const char * argv[]) {

@autoreleasepool {

// insert code here...

NSLog(@"Hello, World!");

//整型

NSInteger a = 10;

NSLog(@"a = %ld",a);

//浮点型

CGFloat b = 2.3;

NSLog(@"b = %.2f",b);

//布尔类型

BOOL flag = YES;

//字符串

NSString *str = @"a淮南师范de";

NSLog(@"str=%@",str);

NSLog(@"str的长度=%ld",str.length);

//字符串相等

if([str isEqualToString:@"a淮南师范de"])

{

NSLog(@"是的");

}

//前缀相等

if ([str hasPrefix:@"a"])

{

NSLog(@"前缀等于a");

}

//后缀相等

if ([str hasSuffix:@"师范de"])

{

NSLog(@"后缀等于师范");

}

//格式化创建字符串

NSString *str1 = [NSString  stringWithFormat:@"%@ ",str];

NSLog(@"str1 = %@",str1);

}

return 0;

}

//

//  main.m

//  oc基础语法2

//

//  Created by lanou on 16/7/9.

//  Copyright © 2016年yhy. All rights reserved.

//

#import

int main(int argc, const char * argv[]) {

@autoreleasepool

{

//数组(NSArray/NSMutableArray)

//不可变数组

NSArray *array1 =@[@"a",@"b",@"c",@"d"];

//创建

NSLog(@"array1 = %@",array1);

//数组元素个数.count

NSLog(@"count = %ld",array1.count);

//通过下标访问数组里面的元素

NSString *str = array1[0];

NSLog(@"str = %@",str);

//可变数组

NSMutableArray *mutableArray= [NSMutableArray arrayWithObjects:@"1",@"2",@"3",@"4",nil];

NSLog(@"mutableArray = %@",mutableArray);

//元素个数:count

//添加个数:addobject

[mutableArray addObject:@"5"];

NSLog(@"已添加------%@",mutableArray);

//移除元素:removeobject

[mutableArray removeObject:@"3"];

NSLog(@"已移除----%@",mutableArray);

//字典

//        (NSDictionary,NSMutableArrayDictionary)

NSDictionary *dict = @{@"key1":@"value1",@"key2":@"value2",@"key3":@"value3"};

NSLog(@"dict = %@",dict);

NSString *string = [dict objectForKey:@"key1"];

NSLog(@"string = %@",string);

//所有的key值,所有的value值

NSLog(@"allKeys = %@,allValues = %@",dict.allKeys,dict.allValues);

return 0;

}

}

2.实现具体方法

OC方法格式

//

//  ViewController.m

//  OC方法格式

//

//  Created by lanou on 16/7/9.

//  Copyright © 2016年 yhy. All rights reserved.

//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

//视图加载好的时候调用

- (void)viewDidLoad {

[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

//    调用方法用空格,方法调用结束用中括号调用

[self func1];

NSInteger num = [self func2];

NSLog(@"num = %ld",num);

NSInteger length = [self lengthofString:@"abcdef"];

NSLog(@"length = %ld",length);

NSString *str5 = [self stringIsStr1:@"hallow" withStr2:@"world"];

NSLog(@"str3 = %@",str5);

}

//OC方法的格式

// 表示类方法,只能用类调用,-表示实力方法只能用对象调用

//无参数输入的方法格式: /- (方法的返回值)方法名

//有参数输入的方法格式: /-(方法的返回值)方法名:(参数1类型)参数1名 方法名:(参数2类型)参数2名

//输入字符串返回字符串的长度

-(NSInteger)lengthofString:(NSString*)string{

return string.length;

}

-(void)func1{

NSLog(@"%s",__func__);}

-(NSInteger)func2{

NSLog(@"%s",__func__);

return 20;

}

-(NSString *)stringIsStr1:(NSString *)str1 withStr2:(NSString *)str2{

NSString *str3 = [NSString stringWithFormat:@"%@%@",str1,str2];

return str3;

}

//内存溢出时调用

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

@end

总结:

OC基础语法实质和我们学习过的C语言是基本类似的,整体框架相似。例如:头文件、变量定义、函数、方法的实现等。当然也有所差别,语言代码的编写、符号等,都有差别。

第一天的实训,让我们初步了解了IOS开发的一些常识问题,初步接触一些简单的语法知识,在今后的学习中将会试着尝试开发一些小游戏、简单的应用程序。当然,学习OC之前应熟练掌握C、C 、Java等语言,编程语言都是相通的。

* 1在iOS编程中必不可少的就是十六进制的颜色值,所以十六进制颜色转换必不可少
/* * 十六进制颜色值转换成UIColor对象 */  (UIColor *) hexStringToColor: (NSString *) stringToConvert;  (UIColor *) hexStringToColor: (NSString *) stringToConvert{ NSString *cString = [[stringToConvert stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; // String should be 6 or 8 characters if ([cString length] < 6) return [UIColor blackColor]; // strip 0X if it appears if ([cString hasPrefix:@"0X"]) cString = [cString substringFromIndex:2]; if ([cString hasPrefix:@"#"]) cString = [cString substringFromIndex:1]; if ([cString length] != 6) return [UIColor blackColor]; // Separate into r, g, b substrings NSRange range; range.location = 0; range.length = 2; NSString *rString = [cString substringWithRange:range]; range.location = 2; NSString *gString = [cString substringWithRange:range]; range.location = 4; NSString *bString = [cString substringWithRange:range]; // Scan values unsigned int r, g, b; [[NSScanner scannerWithString:rString] scanHexInt:&r]; [[NSScanner scannerWithString:gString] scanHexInt:&g]; [[NSScanner scannerWithString:bString] scanHexInt:&b]; return [UIColor colorWithRed: r / 255.0f) green: g / 255.0f) blue: b / 255.0f) alpha:1.0f];}

一:OC介绍

1.OC简介  

OC是以SmallTalk为基础,建立在C语言之上,是C语言的超集。20世纪80年代早期由Brad J.Cox设计,2007年苹果公司发布了OC2.0,并在iPhone上使用OC进行开发。

www.2527.com,2.IDE

编写OC程序最主要的编译环境是Xcode,它是苹果官方提供的IDE,官网中的SDK包括Xcode,可以通过下载SDK来获得它。但是Xcode只支持MacOSX,所以如果要在其它环境下编写OC程序,要使用其它IDE。Linux/FreeBSD用GNUStep,Windows NT5.x(2000,XP)要先安装cywin或mingw,然后安装GNUStep。同时仅仅通过文本编辑器,GCC的make工具也可以用于开发。

注:如果要使用到Cocoa的话,只能在Apple公司的Xcode上。

3.框架

OC编程中主要用到的框架是Cocoa,它是MacOSX中五大API之一,它由两个不同的框架组成FoundationKit和ApplicationKit。Foundation框架拥有100多个类,其中有很多有用的、面向数据的低级类和数据类型,如NSString,NSArray,NSEnumerator和NSNumber。ApplicationKit包含了所有的用户接口对象和高级类。

4.OC代码特点

初次接触OC时,会发现许多和其它语言不同的地方,会看到很多的 ,-,[ ,] ,@,NS等符号,这些符号在以后的编程中将经常看到。

#import"ClassA.h"

#import

intmain( int argc, const char *argv[] ) {

ClassA*c1= [[ClassAalloc]init];

ClassA*c2= [[ClassAalloc]init];

//print count

printf("ClassAcount: %i\\n", [ClassAinitCount] );

ClassA*c3= [[ClassAalloc]init];

//print count again

printf("ClassA count: %i\\n", [ClassA initCount] );

[c1release];

[c2release];

[c3release];

return0;

}

7.优缺点

优点:类别、扮演(Posing)、动态类型、指针计算、弹性信息传递、不是一个过度复杂的c衍生语言、可通过Objective-c 与c 结合

缺点:没有命名空间、没有操作符重载、不像c 那样复杂

* 2反过来颜色转换成十六进制的字符串,这个基本上没有什么人会用到,我基本上不用
/* * UIColor对象转换成十六进制颜色值字符串 */  (NSString *)changeUIColorToRGB:(UIColor *)color;//颜色转换为字符串  (NSString *) changeUIColorToRGB:(UIColor *)color{ const CGFloat *cs=CGColorGetComponents(color.CGColor); NSString *r = [NSString stringWithFormat:@"%@",[self ToHex:cs[0]*255]]; NSString *g = [NSString stringWithFormat:@"%@",[self ToHex:cs[1]*255]]; NSString *b = [NSString stringWithFormat:@"%@",[self ToHex:cs[2]*255]]; return [NSString stringWithFormat:@"#%@%@%@",r,g,b]; }

二:对C的扩展

1.扩展名

OC是ANSI版本C的一个超集,它支持相同的C语言基本语法。与C一样,文件分为头文件和源文件,扩展名分别为.h和.m。如果要加入c 的语法,需要用到.mm

.h

头文件。头文件包涵类的定义、类型、方法以及常量的声明

.m

源文件。这个典型的扩展名用来定义源文件,可以同时包含C和Objective-C的代码。

2.#import

在OC里,包含头文件有比#include更好的方法#import。它的使用和#include相同,并且可以保证你的程序只包含相同的头文件一次。相当于#include #pragma once的组合。

例如要包含Foundation框架中的Foundation.h文件,可以像下面这样。

#import

注:每个框架有一个主的头文件,只要包含了这个文件,框架中的所有特性都可以被使用。

3.@符号

@符号是OC在C基础上新加的特性之一。常见到的形式有@”字符串”,%@ , @interface,@implement等。@”字符串”表示引用的字符串应该作为Cocoa的NSString元素来处理。@interface等则是对于C的扩展,是OC面向对象特性的体现。

注:小技巧,只要看到@符号,就可以认为它是对于C的一个扩展。

4.NSLog()

在OC中用的打印函数是NSLog(),因为OC是加了一点”特殊语料”的C语言,所以也可以用printf()但是NSLog()提供了一些特性,如时间戳,日期戳和自动加换行符等,用起来更方便,所以推荐使用NSLog()。下面是两种输出的对比。

使用NSLog()输出任意对象的值时,都会使用%@格式说明。在使用这个说明符时,对象通过一个名为description的方法提供自己的NSLog()格式。

下面分别是使用NSLog()和使用printf()的相应输出:

2016-07-09 15:54:21。42610_15[1973:207] Hello World!

HelloWorld!

注:NS前缀告诉你函数来自Cocoa而不是其他工具包。

5.BOOL

BOOL是OC中的布尔类型,它和C中的bool有如下区别

BOOL

YES(1),NO(0)

bool

true(!0),false(0)

6.id

这是OC新加的一个数据类型,它是一般的对象类型,能够存储任何类型的方法。

7.nil

在OC中,相对于C中的NULL,用的是nil。这两者是等价的。下面是nil的定义。

#definenil NULL

* 3这个方法是我比较喜欢的,利用颜色来创建图片,修改导航颜色的时候很好用
/* * 使用UIColor创建UIImage */  (UIImage *) createImageWithColor: (UIColor *)color;// 使用UIColor创建UIImage  (UIImage *)createImageWithColor: (UIColor *)color;{ CGRect rect=CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); UIGraphicsBeginImageContext(rect.size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(context, [color CGColor]); CGContextFillRect(context, rect); UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return theImage;}

三:创建对象

1.接口和实现

在OC中定义一个类需要有两个部分:接口和实现。接口文件包含了类的声明,定义了实例变量和方法。实现文件包含了具体的函数的实现代码。下面的代码显示了MyClass这个类的实现代码。就像类的定义规则一样,类实现文件也被两个标识框起来,一个是 @implementation,还有一个是@end。这两个指令标识符告诉编译器程序从哪里开始编译到哪里结束。类中的方法名称的定义和它接口文件中的 定义是一样的,除了实现文件中有具体的代码以外。

@implementationMyClass

-(id)initWithString:(NSString *) aName

{

if(self = [super init]) {

countcount = 0;

data= nil;

name= [aName copy];

returnself;

}

}

(MyClass *)createMyClassWithString: (NSString *) aName

{

return[[[self alloc] initWithString:aName] autorelease];

}

@end

当你要把一个对象保存进变量,要使用指针类型。OC同时支持强和弱变量对象。强类型对象在变量类型定义的时候包含了类名。弱对象使用id类型作为实例变量。下面的例子同时显示了定义MyClass中的强弱两种类型的变量

MyClass*myObject1;// Strong typing

idmyObject2;// Weak typing

2.方法

一个方法定义包含了方法类型,返回类型,一个或者多个关键词,参数类型和参数名。在OC中一个类中的方法有两种类型:实例方法,类方法。实例方法前用(-)号表明,类方法用( )表明,通过下图可以看到,前面有一个(-)号,说明这是一个实例方法。

在OC中,调用一个方法相当于传递一个消息,这里的消息指的是方法名和参数。所有的消息的分派都是动态的,这个体现了OC的多态性。消息调用的方式是使用方括号。如下面的例子中,向myArray对象发送insertObject:atIndex:这个消息。

[myArrayinsertObject:anObj atIndex:0];

这种消息传递允许嵌套

[[myAppObjectgetArray] insertObject:[myAppObject getObjectToInsert] atIndex:0];

前面的例子都是把消息传递给实例变量,你也可以把消息传递给类本身。这时要用类方法来替代实例方法 。你可以 把他想象成静态C 类(当然不完全相同)。

类方法的定义只有一个不一样那就是用加号( )代替减号(-)。下面就是使用一个类方法。

NSMutableArray*myArray = nil;// nil is essentially the same as NULL

//Create a new array and assign it to the myArray variable.

myArray =[NSMutableArray arrayWithCapacity:0];

3.属性

属性提供了比方法更方便的访问方式。通过property标识符来替代getter和setter方法。使用方法就是在类接口文件中用@property标识符,后面跟着变量的属性,包括 copy, tetain, assign ,readonly , readwrite,nonatomic,然后是变量名。同时在实现文件中用@synthesize标识符来取代getter和setter方法。

@propertyBOOL flag;

@property(copy) NSString* nameObject;

//Copy the object during assignment.

@property(readonly) UIView* rootView;// Create only a getter method

接口文件中使用@property

@synthesizeflag,nameObject,rootView;

实现文件中使用@synthesize

属性的另一个好处就是,可以使用点(.)语法来访问,如下所示:

myObject.flag= YES;

CGRectviewFrame = myObject.rootView.frame;

* 4弹出矩形黑色提示窗需要下载一个类iToast,文件减小易用,下载下来添加到工程里面就可以了,但是我在使用过程中发现了一个bug,就是传入要显示的字符串为nil的时候被导致崩溃,因为这个类里面用了属性字符串,遇到nil会崩溃,自己可以在崩溃的地方自行加一个判断。

在.m中包含头文件

#import "iToast.h"

显示位置可以设置多个,这里提供两个位置一个是中间,一个是中偏下的位置

  showItoast:(NSString *)str;  showItoastInCenter:(NSString *)str;  showItoast:(NSString *)str{ dispatch_async(dispatch_get_main_queue(), ^{ iToast *itost = [[iToast makeText:str] setGravity:iToastGravityBottom]; [itost setDuration:iToastDurationNormal]; [itost show:iToastTypeWarning]; }); }  showItoastInCenter:(NSString *)str{ dispatch_async(dispatch_get_main_queue(), ^{ iToast *itost = [[iToast makeText:str] setGravity:iToastGravityCenter]; [itost setDuration:iToastDurationShort]; [itost show:iToastTypeNotice]; });}

四:继承

继承的语法如下,冒号后的标识符是需要继承的类。

@interfaceCircle : NSObject

1.不支持多继承

要注意的是OC只支持单继承,如果要实现多继承的话,可以通过类别和协议的方式来实现。

2.Super关键字

OC提供某种方式来重写方法,并且仍然调用超类的实现方式。当需要超类实现自身的功能,同时在前面或后面执行某些额外的工作时,这种机制非常有用。为了调用继承方法的实现,需要使用super作为方法调用的目标。下面是代码示例:

@implementationCircle

-(void)setFillColor:(ShapeColor) c

{

if(c== kRedColor){

c= kGreenColor;

}

[supersetFillColor: c];

}

@end

Super来自哪里呢?它既不是参数也不是实例变量,而是由OC编译器提供的某种神奇功能。向super发送消息时,实际上是在请求OC向该类的超类发送消息。如果超类中没在定义该消息,OC将按照通常的方式在继承链中继续查找对应的消息。

* 5 同上显示菊花也是一样,网络请求或者加载数据时候难免会用到菊花我使用的是

MBProgressHUD。

 showHUD:(NSString *)text andView:view andHUD:(MBProgressHUD *)hud; showHUD:(NSString *)text andView:view andHUD:(MBProgressHUD *)hud{ [view addSubview:hud]; hud.labelText = text;//显示提示 hud.dimBackground = YES;//使背景成黑灰色,让MBProgressHUD成高亮显示 hud.square = YES;//设置显示框的高度和宽度一样 hud.removeFromSuperViewOnHide = YES; [hud show:YES];}//使用示例 MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:self.view]; [KK_Utils showHUD:@"正在加载" andView:self.view andHUD:hud];//关闭时执行代码:hud.hidden = YES;

五:对象初始化

1.分配与初始化

对象的初始化有两种方法:一种是[类名new], 第二种是[[类名 alloc]init]。这两种方法是等价的,不过,通常的Cocoa惯例是使用alloc和init,而不使用new.一般情况下,Cocoa程序员只是在他们不具备足够的水平来熟练使用alloc和init方法时,才将new作为辅助方法使用。

[[类名alloc]init]有两个动作。alloc是分配动作,是从操作系统获得一块内存并将其指定为存放对象的实例变量的位置。同时,alloc方法还将这块内存区域全部初始化为0。与分配动作对应的是初始化。有如下两种初始化写法。

Car *car =[[Class alloc] init];

写法1

Car*car = [Car alloc];

[carinit];

写法2

应该使用第一种写法,因为init返回的对象可能不是以前的那个。

2.编写初始化方法

下面是一段初始化的代码

-(id)init

{

if(self = [superinit]){

engine = [Enginenew];

}

}

使用self= [super init]的作用是使超类完成它们自己的初始化工作。同时因为init可能返回的是不同的对象,实例变量所在的内存位置到隐藏的self参数之间的跳离又是固定的,所以要这样使用。

3.总结

这个工具类会持续更新,比如MD5加密字符串等等,希望大神们多多指教,欢迎评论Star。欢迎关注我的微博和博客

六:协议

这里的协议是正式协议,相对的还有非正式协议。正式协议是一个命名的方法列表。它要求显式地采用协议。采用协议意味着要实现协议的所有方法。否则,编译器会通过生成警告来提醒你。

1.声明协议

@protocolNSCopying

-(id)copyWithZone:(NSZone*)zone;

@end

2.采用协议

@interface Car :NSObject

{

// instancevariables

}

@end

协议可以采用多个,并且可以按任意顺序列出这些协议,没有什么影响。

3.OC 2.0的新特性

OC2.0增加了两个新的协议修饰符:@optional和@required,因此你可以像下面这样编写代码:

@protocolBaseballPlayer

-(void)drawHugeSalary;

@optional

-(void)slideHome;

-(void)catchBall;

@required

-(void)swingBat;

@end

因此,一个采用BaseballPlayer协议的类有两个要求实现的方法:-drawHugeSalary和-swingBat,还有3个不可选择实现的方法:slideHome,catchBall和throwBall。

七:委托

Cocoa中的类经常使用一种名为委托(delegate)的技术,委托是一种对象,另一个类的对象会要求委托对象执行它的某些操作。常用的是,编写委托 对象并将其提供给其他一些对象,通常是提供给Cocoa生成的对象。通过实现特定的方法,你可以控制Cocoa中的对象的行为。

通过下面的例子,可以更清楚地理解委托的实现原理。其中A对象需要把一些方法委托给其它对象来实现,例子中就是对象B,B实现了含A对象特定方法的协议ADelegate,从而可以在B中实现A委托的方法。

@protocolADelegate

-(void)aDelegateMethod;

……

@end

@interfaceA : NSObject {

……

iddelegate;

}

@property(readwrite, assign)

iddelegate;

……

@end

@implementationA

@synthesizedelegate;

-(void)aMethod{

[delegateaDelegateMethod];

……

}

@end

A类

@interfaceB : NSObject

@end

@implementationB

-(id)init {

……

[[AsharedA] setDelegate:self];

}

-(void)aDelegateMethod{//B中实现A委托的方法

……

}

@end

八: 类别

类别允许你在现有的类中加入新功能,这些类可以是框架中的类,并且不需要扩充它。

1.声明类别

@interfaceNSString (NumberConvenience)

-(NSNumber *)lengthAsNumber;

@end

该声明表示,类别的名称是NumberConvenience,而且该类别将向NSString类中添加方法。

2.实现类别

@implementationNSString (NumberConvenience)

-(NSNumber*) lengthAsNumber

{

unsigned intlength = [self length];

return([NSNumber numberWithUnsignedInt: length]);

}

@end

3.局限性

类别有两方面的局限性。第一,无法向类中添加新的实例变量。类别没有位置容纳实例变量。第二,名称冲突,即类别中的方法与现有的方法重名。当发生名称冲突时,类别具有更高的优先级。这点可以通过增加一个前缀的方法解决。

4.非正式协议和委托类别

实现委托除了第七节中应用协议的方式,还可以使用类别。具体做法就是把委托对象要实现的方法声明为一个NSObject的类别。如下面的代码所示:

@interfaceNSObject(NSSomeDelegateMethods)

-(void)someMethod;

@end

通过将这些方法声明为NSObject的类别,使得只要对象实现了委托方法,任何类的对象都可以成为委托对象。创建一个NSObject的类别称为“创建 一个非正式协议”。非正式协议只是一种表达方式,它表示“这里有一些你可能想实现的方法”。

非正式协议的作用类似于使用许多@optional的正式协议,并且前者正逐渐被后者所代替。

5.选择器

选择器只是一个方法名称,它以OC运行时使用的特殊方式编码,以快速执行查询。你可以使用@selector()预编译指令指定选择器,其中方法名位于圆括号中。如一个类中setEngine:方法的选择器是:@selector(setEngine:)。

因为选择器可以被传递,可以作为方法的参数使用,甚至可以作为实例变量存储。这样可以生成一些非常强大和灵活的构造。

第九节:Posing

Posing有点像类别,但不太一样。它允许你扩充一个类,并且全面性地扮演(pose)这个超类。例如:你有一个扩充NSArry的 NSArrayChild对象。如果你让NSArrayChild扮演NSArry,则在你的代码中所有的NSArray都会自动被替代为 NSArrayChild.

@interfaceFractionB: Fraction

-(void)print;

@end

@implementationFractionB

-(void)print {

printf("(%i/%i)", numerator, denominator );

}

@end

Fraction.m

intmain( int argc, const char *argv[] ) {

Fraction*frac = [[Fraction alloc] initWithNumerator: 3 denominator: 10];

//print it

printf("The fraction is: " );

[fracprint];

printf("\\n" );

//make FractionB pose as Fraction

[FractionBposeAsClass: [Fraction class]];

Fraction*frac2 = [[Fraction alloc] initWithNumerator: 3 denominator: 10];

//print it

printf("The fraction is: " );

[frac2print];

printf("\\n" );

//free memory

[fracrelease];

[frac2release];

return0;

}

Main.m

Thefraction is: 3/10

Thefraction is: (3/10)

输出

这个程序的输出中,第一个fraction会输出3/10,而第二个会输出(3/10),这是FractionB中实现的方式。poseAsClass这个方法是NSObject的一部分,它允许子类扮演超类。

第十节:动态识别 (Dynamictypes)

下面是应用动态识别时所用到的方法:

-(BOOL)isKindOfClass:classObj

是否是其子孙或一员

-(BOOL)isMemberOfClass:classObj

是否是其一员

-(BOOL)respondsToSelector:selector

是否有这种方法

(BOOL)instancesRespondToSelector:selector

类的对象是否有这种方法

-(id)performSelector:selector

执行对象的方法

通过下面的代码可以更清楚地理解动态类型的使用:

import"Square.h"

#import"Rectangle.h"

#import

“intmain( int argc, const char *argv[] ) {

Rectangle*rec = [[Rectangle alloc] initWithWidth: 10 height: 20];

Square*sq = [[Square alloc] initWithSize: 15];

//isMemberOfClass

//true

if( [sq isMemberOfClass: [Square class]] == YES ) {

printf("square is a member of square class\\n" );

}

//false

if( [sq isMemberOfClass: [Rectangle class]] == YES ) {

printf("square is a member of rectangle class\\n" );

}

//false

if( [sq isMemberOfClass: [NSObject class]] == YES ) {

printf("square is a member of object class\\n" );

}

//isKindOfClass

//true

if( [sq isKindOfClass: [Square class]] == YES ) {

printf("square is a kind of square class\\n" );

}

//true

if( [sq isKindOfClass: [Rectangle class]] == YES ) {

printf("square is a kind of rectangle class\\n" );

}

//true

if( [sq isKindOfClass: [NSObject class]] == YES ) {

printf("square is a kind of object class\\n" );

}

//respondsToSelector

//true

if( [sq respondsToSelector: @selector( setSize: )] == YES ) {

printf("square responds to setSize: method\\n" );

}

//false

if( [sq respondsToSelector: @selector( nonExistant )] == YES ) {

printf("square responds to nonExistant method\\n" );

}

//true

if( [Square respondsToSelector: @selector( alloc )] == YES ) {

printf("square class responds to alloc method\\n" );

}

//instancesRespondToSelector

//false

if( [Rectangle instancesRespondToSelector: @selector( setSize: )] ==YES ) {

printf("rectangle instance responds to setSize: method\\n" );

}

//true

if( [Square instancesRespondToSelector: @selector( setSize: )] ==YES ) {

printf("square instance responds to setSize: method\\n" );

}

//free memory

[recrelease];

[sqrelease];

return0;

}”

输出:

squareis a member of square class

squareis a kind of square class

squareis a kind of rectangle class

squareis a kind of object class

squareresponds to setSize: method

squareclass responds to alloc method

squareinstance responds to setSize: method

TAG标签:
版权声明:本文由澳门新葡8455手机版发布于www.2527.com,转载请注明出处:IOS暑假小学期实训,内容根据iOS编程编写