1#pragma mark - Day03_01_对象作为方法的返回值
1) 对象是可以作为方法的返回值的,返回值应该写这个类指针类型.
- (MkDog *)buyDog;
代表方法执行完毕之后,有1个HMDog对象返回.
这个时候.在方法结束之前,就必须要使用return返回1个符合类型的对象.
2) 本质上来说.
其实返回的是1个指定对象的地址
不用担心对象会被销毁.因为对象是存储在堆区的.
#pragma mark - Day03_02_类的属性和方法
1) 一个Target中的类无法直接在另外1个Target中访问.
2) 类的属性代表什么?
a. 类的属性代表这类事物具有的共同的特征
b. 类的属性代表这个类所拥有的东西.
c. 如何分析类有哪些属性?
就分析这个类拥有哪些东西?
拥有的东西就可以作为类的属性.
3. 类的方法代表什么?
a. 代表这个类所具备的行为. 这个类所具备的功能.
b. 一个类有什么方法 就去分析这个类有什么功能.
#pragma mark - Day03_03_对象作为类的属性(较难)
对象可以作为类的属性
1)属性的本质是变量.
在创建对象的时候,对象中的属性是按照类模板中的规定挨个挨个的创建出来的.
类模板中属性是什么类型.那么对象中的属性就是什么类型.
如果对象的属性是另外1个类的对象,这个属性仅仅是1个指针变量而已.并没有对象产生.
这个时候 还要为这个属性赋值1个对象的地址 才可以正常使用.
2) A类可以作为B类的属性. 代表B拥有A.
属性仅仅是1个变量而已. 是1个指针变量而已.默认值是nil 并没有创建对象.
这个时候如果你要正常的使用的话. 还要为B对象的A属性赋值1个对象.
#pragma mark - Day03_04_玩家类的设计
练习
1.猜拳游戏的流程
1). 玩家出拳.
2). 机器人出拳.
3). 裁判宣布比赛结果.
2. 面向对象的重点在于找类.
玩家类:
属性:姓名、选择的拳头、得分.
方法:出拳 -> 自行选择1个拳头来出.
机器人类:
属性:姓名、选择的拳头、得分.
方法:出拳. -> 随机出拳
1) 枚举或者结构体定义在什么地方.
如果只是1个类要用.那么就定义在这个类的头文件中.
如果多个类要用.那么就定义在1个单独的头文件中.谁要用 谁就去引就可以了
2) 如果要在方法中调用当前对象的另外1个方法.
[self 方法名];
self代表当前对象.
/**
* 玩家类:代表1个玩家.
*/
@interface MKPlayer : NSObject
{
@public
/**
* 玩家对象的姓名
*/
NSString *_name;
/**
* 玩家对象的得分.
*/
int _score;
/**
* 玩家对象选择的拳头.
*/
MKFistType _selectedType;
}
/**
* 出拳的方法.
*/
- (void)showFist;
/**
* 根据传入的整型的数返回对应字符串拳头
*
* @param numebr 整型的数
*
* @return 对应的拳头类型.
*/
- (NSString *)fistTypeWithNumber:(int)numebr;
@end
@implementation MKPlayer
/**
* 出拳的方法.
*/
- (void)showFist
{
//1. 先提示用户选择拳头.
NSLog(@"亲爱的玩家[%@]请选择你要出的拳头 1.剪刀 2.石头 3.布",_name);
//2. 接收用户输入拳头
int userSelect = 0;
scanf("%d",&userSelect);
//3. 显示用户选择拳头
// 要取出整型的数代表的字符串的拳头的类型.
NSString *type = [self fistTypeWithNumber:userSelect];
NSLog(@"玩家[%@]出的拳头是:%@",_name,type);
//4. 将用户选择的拳头存储在当前对象的属性中.
_selectedType = userSelect;
}
/**
* 根据传入的整型的数返回对应字符串拳头
*
* @param numebr 整型的数
*
* @return 对应的拳头类型.
*/
- (NSString *)fistTypeWithNumber:(int)numebr
{
switch (numebr)
{
case 1:
return @"剪刀";
case 2:
return @"石头";
default:
return @"布";
}
}
@end
1) 枚举或者结构体定义在什么地方.
如果只是1个类要用.那么就定义在这个类的头文件中.
如果多个类要用.那么就定义在1个单独的头文件中.谁要用 谁就去引就可以了
2) 如果要在方法中调用当前对象的另外1个方法.
[self 方法名];
self代表当前对象.
#pragma mark - Day03_05_机器人类的设计
机器人类的设计
/**
* 机器人类
*/
@interface HMRobot : NSObject
{
@public
/**
* 机器人对象的姓名
*/
NSString *_name;
/**
* 机器人选择的拳头
*/
MKFistType _selectedType;
/**
* 机器人对象的得分.
*/
int _score;
}
/**
* 机器人出拳的方法.
*/
- (void)showFist;
/**
* 根据传入的整型的数返回对应字符串拳头
*
* @param numebr 整型的数
*
* @return 对应的拳头类型.
*/
- (NSString *)fistTypeWithNumber:(int)numebr;
@end
@implementation MKRobot
/**
* 机器人出拳的方法.
*/
- (void)showFist
{
//1. 随机出拳.
int robotSelect = arc4random_uniform(3)+1;
//2. 显示随机出的拳头.
NSString *type = [selffistTypeWithNumber:robotSelect];
NSLog(@"机器人[%@]出的拳头是:%@",_name,type);
//3. 将出的拳头保存在当前对象的属性中.
_selectedType = robotSelect;
}
/**
* 根据传入的整型的数返回对应字符串拳头
*
* @param numebr 整型的数
*
* @return 对应的拳头类型.
*/
- (NSString *)fistTypeWithNumber:(int)numebr
{
switch (numebr)
{
case 1:
return @"剪刀";
case 2:
return @"石头";
default:
return @"布";
}
}
@end
#pragma mark - Day03_06_猜拳游戏结束
裁判类的设计
/*
机器人类
属性:姓名、选择的拳头、得分.
方法:出拳. -> 随机出拳
*/
#import <Foundation/Foundation.h>
#import "MKFistType.h"
@interface MKRobot : NSObject
{
@public
/**
* 机器人对象的姓名
*/
NSString *_name;
/**
* 机器人选择的拳头
*/
MKFistType _selectedType;
/**
* 机器人对象的得分.
*/
int _score;
}
/**
* 机器人出拳的方法.
*/
- (void)showFist;
/**
* 根据传入的整型的数返回对应字符串拳头
*
* @param numebr 整型的数
*
* @return 对应的拳头类型.
*/
- (NSString *)fistTypeWithNumber:(int)numebr;
@end
@implementation MKRobot
/**
* 机器人出拳的方法.
*/
- (void)showFist
{
//1. 随机出拳.
int robotSelect = arc4random_uniform(3)+1;
//2. 显示随机出的拳头.
NSString *type = [self fistTypeWithNumber:robotSelect];
NSLog(@"机器人[%@]出的拳头是:%@",_name,type);
//3. 将出的拳头保存在当前对象的属性中.
_selectedType = robotSelect;
}
/**
* 根据传入的整型的数返回对应字符串拳头
*
* @param numebr 整型的数
*
* @return 对应的拳头类型.
*/
- (NSString *)fistTypeWithNumber:(int)numebr
{
switch (numebr)
{
case 1:
return @"剪刀";
case 2:
return @"石头";
default:
return @"布";
}
}
@end
#pragma mark - Day03_07_如何取到当前对象的属性
1) 类中的方法的参数,可以使用当前类的对象作为参数
2) 类中的属性,可以使用当前类的对象作为属性
#pragma mark - Day03_08_异常处理
1) 错误:
1). 一般情况下,指的是我们的程序的源代码有语法错误.
2). 错误的后果: 无法编译 更谈不上执行.
2). 解决方案: 将错误的代码修改为符合语法规范的代码不就OK了
2) BUG
1. 指的是,程序可以编译、链接、执行. 只不过程序执行出来的结果并不是我们所预设的那样.
2. 解决方案: 99%的Bug都是因为变量的值没有按照我们所预想的那样去变化.
3) 异常
1.概念: 指的是,程序可以编译、链接、执行.
当程序在运行的时候,程序处于某种特殊情况下的时候 程序的执行就会报错,这种情况我们叫做异常.
2.特点: 异常不是一定会发生.而是当程序在运行的时候处于某种特定情况的时候才会发生.
3.后果: 程序立即终止运行.后面的代码不会执行.
闪退的原因:
a. 程序所占用的空间太大.
b. 程序发生了异常
.....
4) 异常的处理.'
1. 处理异常的目的: 希望程序在执行的时候,如果发生了异常. 程序不要崩溃,而是继续往下执行代码.
2. 使用@try...@catch处理异常.
3. 将有可能发生异常的代码使用@try围起来.
4.作用: 让代码在执行的时候如果发生了异常 而不崩溃.
5. 使用注意
1. 在@try中的代码执行的时候,如果发生了异常.
会将发生异常的信息.封装为1个 NSException 对象, 把这个对象的地址,赋值给@catch的参数,然后再执行@catch的代码. 所以,@catch的参数指向了错误对象,在@catch中如果想要拿到发生异常的原因.就可以访问这个参数对象.
2. @catch中的代码只有在发生异常的时候,才会执行.
所以.@catch中一般我们写处理异常的代码.
3. @catch后面还可以跟1个@finally代码块.
无论@try中是否有异常发生.@finally中的代码都会被执行 .
4. @try..@catch并不是万能的 不是所有的异常都可以处理.
C语言的异常处理不了. 只能处理OC的异常.
5. @try..@catch在我们的代码中很少使用.
我们一般情况下都是 通过逻辑判断来减少异常的发生.
#pragma mark - Day03_09_类方法的基本使用
1. OC中的方法分两种.
-> 对象方法/实例方法: 我们之前学习到的方法就叫做对象方法.
对象方法必须使用对象名来调用.
也就是说,想要去调用对象方法 就必须要创建1个对象.
-> 类方法: 类方法的调用不依赖于对象,而是依赖于类.
要调用类方法 不需要创建对象 而是直接通过类名就可以调用.
2. 声明
1). 对象方法的声明使用一个 - 号
- (void)sayHi;
2). 类方法的声明使用一个 + 号.
+ (void)classMethod;
3. 调用
1). 要调用对象方法就必须要创建1个对象,通过对象名来调用.
[对象名 对象方法名];
2). 要调用类方法,不需要创建对象. 直接使用类名可以调用.
[类名 类方法名];
需要注意的是. 对象方法只能通过对象名来调用.
类方法只能通过类名来调用.
3. 类方法的特点:
1). 节约空间: 因为类方法的调用不需要创建对象.
而对象方法的调用还要首先创建1个对象.
2). 提高效率: 类方法的调用.直接找到代码区中的类,找到类中的类方法执行.
对象方法要先通过指针找到对象,再通过对象的isa指针找到类.再找到类中的方法执行.
4. 类方法的局限性
在类方法中无法直接访问类的属性.
也不能通过self关键字去调用当前类的对象方法.
因为类方法的调用不需要创建对象的. 而属性只有对象创建了以后才有.
所以,类方法在执行的时候,对象有可能还没有呢.对象都没有 如何访问属性呢?
同样的原理;在类方法执行的时候,还没有对象,而对象方法的调用必须要依赖于对象来调用.
所以.在类方法中不能直接使用self调用当前类的.对象方法.
5. 什么时候,我们需要将方法定义为类方法呢?
如果我们的方法不需要访问属性.也不需要直接调用当前类中的对象方法.
那么就可以将这个方法定义为类方法,来节约空间提高效率.
#pragma mark - Day03_10_使用类方法需要注意的问题
1). 对象方法之间是不能重名的.
2). 类方法之间也是不能重名的.
3). 类方法和对象方法可以同名.
如果通过类名来调用,那么调用的就是类方法.
如果通过对象来调用,那么调用的就是对象方法.
4). 对象方法只能通过对象来调用.
类方法只能通过类来调用.
5). 类方法中虽然不能直接访问属性和调用对象方法
但是.可以创建1个对象,访问这个对象的属性和对象方法.
6). 类方法中不能直接调用当前类的对象方法.除非创建1个对象,通过这个创建的对象调用.
在对象方法中可以直接使用类名来调用类方法.
#pragma mark - Day03_11_类方法的规范
1. 我们写1个类 就要为这个类提供1个和类名同名的类方法.这个类方法来返回1个纯洁的对象.
纯洁的对象: 对象的属性的值都是默认值.
+ (MKPerson *)person
{
MKPerson *p1 = [MKPerson new];
return p1;
}
2. 如果希望创建出来的对象的属性的值是由创建者指定的.
那么这个时候,就可以为这个类方法带参数. 在方法内部创建对象. 并初始化对象的属性.
返回.
+ (MKPerson *)personWithName:(NSString *)name andAge:(int)age
{
MKPerson *p1 = [MKPerson new];
p1->_name = name;
p1->_age = age;
return p1;
}
#pragma mark - Day03_12_new其实是1个类方法
对象的创建.
MKPerson *p1 = [MKPerson new];
new其实是1个类方法.
做的事情: 创建对象、初始化对象.
返回值: 返回创建的这个对象的地址.
#pragma mark - Day03_13_NSString的本质是1个类
1) NSString是1个数据类型,用来保存OC字符串的.
2) 实际上. NSString应该是1个类.
既然是1个类.所以,完整的创建NSString对象的方式应该是这样的
NSString *str0 = [NSString new];
NSString *str1 = [NSString string];
因为NSString是OC中最常用的1个对象.如果每次都这么创建字符串对象的话,就太累了.所以,苹果就提供了1种快捷的方式来创建1个NSString对象.
@"jack" 这个本质上是1个NSString对象. 这是苹果提供的一种简写方式.
@"rose" 是1个NSString对象.这是1个创建NSString对象的简写方法.
NSString对象是来保存字符串的.
1. 要存储字符串的完整的方式.
a. 先创建NSString对象.
b. 把字符串存储到这个对象中.
2. 但是这么做太麻烦了. 所以,苹果提供了一个简写的方式,使用@符号.
@"jack" ; 创建1个NSString对象,然后把字符串"jack"存储到这个对象中去.
%p: 代表打印指针变量的值.只不过这个指针变量的值是1个地址.
%@: 代表打印指针指向的对象.
NSString *str = [NSString new];
这种方式创建的字符串是1个空字符串 @"" 不是nil
#pragma mark - Day03_14_NSString的常用方法
1) 常用的类方法.
a. 将C语言的字符串转换为OC字符串对象.
+ (nullable instancetype)stringWithUTF8String:(const char *)nullTerminatedCString;
nullable: 代表返回的对象有可能是nil
b. 将变量拼接成1个新的OC字符串.
+ (instancetype)stringWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2);
2) 常用的对象方法.
a. 得到字符串的长度.
- (NSUInteger)length;
NSUInteger 这货其实就是unsigned long
b. 得到指定下标的字符.
- (unichar)characterAtIndex:(NSUInteger)index;
在OC语言中 1个中文占据2个字节.
返回值是unichar 占据2个字节.
OC字符串中的字符 如果是英文字符占据1个字节 .如果是中文字符就占据2个字节.
打印unichar字符使用%C 这是大C
c. 判断两个字符串的内容是否相同.
如果要判断两个字符串的内容是否相同.不要使用==来判断.会出问题.
- (NSComparisonResult)compare:(NSString *)string;
返回的是1个枚举值.
NSOrderedAscending : 当前字符串比传入的字符串小. 升序 123 左边(对象) < 右边 (传进来的字符串)
NSOrderedSame: 一样
NSOrderedDescending 当前字符串比传入的字符串大 降序 321 左边(对象) > 右边 (传进来的字符串)
如果枚举记不住,用整型就可以了.
d. 只判断两个字符串是否相同.;
- (BOOL)isEqualToString:(NSString *)aString;
"作业
1) 设计类
狗类
属性: 名字,年龄
对象方法:
叫几声
类方法:
1.快速创建类方法
2.快速创建类,并设置属性方法.
车类
属性: 品牌,公里数
对象方法:
给车一个速度,车开动,并且公里数增加
类方法:
1.快速创建类方法
2.快速创建类,并设置属性方法.
人类
属性: 姓名,年龄,狗,父亲
对象方法:
1.给他一辆车,让车跑
2.遛狗
类方法:
1.快速创建类方法
2.快速创建类,并设置属性方法(除去'父亲').
3.给他两个人对象(儿子,父亲),判断这两个人对象是不是父子关系
需求:
1. 用普通方式创建一条狗对象(d1),并设置d1的属性
2. 用普通方式创建一个人的对象(p1),并且设置属性,把d1赋值给p1的狗属性,然后遛狗
3. 用类方法创建一个车对象(car),然后让p1开车
4. 用类方法创建一个人对象(p2),并把p2赋值给p1的父亲
5. 用类方法创建一个狗,并设置属性,赋值给p2,然后通过p1打印出这条狗的名字
6. 调用人类的类方法,判断 p2 是不是 p1 的父亲
2) 字符串练习
1. 使用三种方式创建一个'值为空'的字符串(!nil)
2. 使用两种方式创一个值为'xiaoming'的字符串
3. 打印 @"123456778900987654321"的长度
4. 把这三个字符串(@"123" @"cvb" @"你好,世界!")拼接到一起,并打印
5. 比较 @"abc" 和 @"abd" 的大小
6. 判断 @"abcdefg" 和 @"abCdefg" 存的值是否相等
7. 获取 @"我英文不好a" 第5个字符的值