OC加强DAY04 - 协议与代理

  • 协议
    • 协议的基本使用
      • 协议 专门用来写方法的声明的协议中不能写属性
      • 声明一个协议
      • 类遵守协议
      • 继承是单继承协议是可以多遵守的
      • required 与 optional
    • 协议的基本使用
      • 协议可以继承并且可以多继承
        • 协议如何继承另外一个协议
      • NSObject是个类是所有OC类的父类
      • 协议 延展 分类的比较
    • 协议的类型限制
      • 声明一个遵守协议的指针
      • 为什么要做类型限制
  • 代理
    • 应用场景-找女朋友
    • 代理设计模式
      • 设计一个类HMTableView
      • 为方法传递数据的方式
  • Foundation框架
    • 不同的框架中的类是用来做不同的事情的
    • 后面要学的类
    • NSString类
      • NSString是一个类定义在Foundation框架中的
      • NSString对象的作用用来存储字符串数据的
      • NSString是OC当中最常用的对象
      • 本质
    • NSString的恒定性
      • 我们创建字符串对象的时候如果使用来创建
      • 什么叫恒定性
      • 当系统要在内存中创建一个字符串对象的时候
      • 常量区中的数据是不会被回收肚的
    • NSString 最常用的5个方法
    • NSString 常用方法

协议

协议的基本使用

协议: protocol

1. 协议: 专门用来写方法的声明的,协议中不能写属性.

遵守了协议的类,这个类就拥有了这份协议中的所有的方法的声明,而不用自己去定义.

2. 声明一个协议

@protocol 协议名称 <NSObject>
//这里写方法的声明;
@end
  1. 协议中不能写属性.
  2. 可以写方法的声明
    也可以写(开发中不会写)@property,但是协议中的@property只会生成get set的声明,没有实现.

3. 类遵守协议.

  1. 如果一个类想要拥有某个协议中的所有的方法的声明,就只要遵守这个协议就可以了.

    //遵守协议的格式
    @interface 类名 : 父类名 <协议名称>
    // : 冒号 是继承  <>尖括号是遵守协议
    @end
  2. 类遵守协议的效果:就是拥有协议的声明 ,不会自动实现.如果没有实现协议中的方法,编译的时候会给一个警告,执行的时候如果调用了没实现的方法,就会报错.如果父类遵守协议,相当于子类也继承了.

4. 继承是单继承.协议是可以多遵守的

@interface 类名 : 父类名 <协议名1,协议名2,......>
@end
//如果一个类遵守了多分协议,这个类就拥有了所有协议中的方法和声明

5. @required@optional

  1. 遵守协议可以获得方法,但是还是要自己去实现
  2. 这两个关键字是用来修饰协议中的方法的
  3. @required修饰的方法,如果遵守这个协议的类不去实现的话,编译器就会报警告
  4. @optional修饰的方法,如果遵守这个协议的类不去实现的话,编译器不会报警告
  5. 无论是哪一个,如果不实现,编译的时候都不会飘红(报错)
  6. 唯一的作用:在于程序员之间的沟通.
  7. 我写一份你来遵守,@required是必须遵守实现的,@optional可以不实现.
  8. 默认值是@required.

协议的基本使用

1. 协议可以继承并且可以多继承

协议如何继承另外一个协议?

@protocol HMSportPotocol<NSObject>

@protocol HMStudyProtocol<HMStudyPorocol,HMPlayPotocol>

@interface HMPerson : NSObject <HMStudyPotocol>//继承study协议同时自动继承了它的父协议Sport,Play协议.

2. NSObject是个类,是所有OC类的父类

Foundation框架中有个协议也叫NSObject.协议名字和类名一样不冲突
NSObject类遵守了NSObject协议.
所以NSObject类里面拥有了NSObject协议中的所有声明.
所以所有的OC类都拥有了NSObject协议中的方法声明
协议的规范:要求##所有的协议##直接或者间接的##从NSObject基协议继承##.

3. 协议 延展 分类的比较

分类: 将一个类分为多个模块,为一个类添加方法
延展: 专门用来私有化类的成员的
协议: 定义一份协议,可以让其他的类来遵守这个协议,遵守后获得协议中所有方法声明
继承: 子类继承父类,子类就拥有了父类的所有的成员

协议的类型限制

1. 声明一个遵守协议的指针

  • 请声明1个指针,这个指针可以指向任意的OC对象.
    • 但是要求这个对象必须要遵守指定的协议.
    • 如果指针指向的对象不遵守这个协议,起码要给我1个大大的警告.
//NSObject指针或者id指针都可以.回一下有啥区别?
id<协议名> 指针名;
id id1;
//这样,id1指针要求指向的对象必须遵守HMSportProtocol协议,否则就给黄色警告.
  • 声明1个指针,这个指针可以指向任意的OC对象.
    • 要求这个指针指向的对象,遵守多个协议
      • id id1;
    • 要求指向一个人对象,并且这个人对象要遵守指定的协议.
      • HMPerson

2. 为什么要做类型限制

  1. 只有遵守了协议的类,才100%拥有这个协议中的方法
  2. 我们后面要调用这个对象中的协议方法
  3. 为了保证这个对象中一定有这个协议方法,所以我们要求指针指向的对象要遵守指定的协议

代理

应用场景-找女朋友

  1. 用面向对象模拟李凯找女朋友的过程
    • 李凯找女朋友的需求
    • 会洗衣服
    • 会做饭
    • 有国企工作优先考虑..
  2. 找类:
人类:

女朋友类:
    美国女孩.
    印度女孩.
    火星女孩.
    狗...
    只要会洗衣服,会做饭,就可以
@protocol HMGFProtocol <NSObject>
- (void)xiYiFu;
- (void)cook;
@optional
- (void)haveAGoodJob;
- @end


@interface HMPerson : NSObject
@property(nonatomic,strong)NSString *name;
@property(nonatomic,assign)int money;
//重点是下面的,人类拥有一个女朋友对象,谁都行,只要遵守GF协议这个也就是代理对象.帮助当前对象来完成某件事情
//下面的实际实在
@property(nonatomic,strong)id girlFriend;//@implementation中的.
- (void)talkLove;
{
    NSLog(@"哈尼,我回来了~");
    [_girlFriend xiYiFu];
    [_girlFriend cook];
    NSLog(@"亲爱的你真好,明天继续哦~");
}
@end

int main()
{
    HMPerson *p1 = [HMPerson new];
    p1.name = @"李凯";
    p1.money = INT32_MAX;
    HMGirl *fj = [HMGirl new];
    p1.girlFriend = fj;//如果没有遵守协议这句话就黄了,报警高
    [p1 talkLove];//如果没有实现方法,就会谈崩了.
    return 0;
}

代理设计模式

1. 设计一个类HMTableView

提供一个方法打印表格.

2. 为方法传递数据的方式

  • 为方法传递数据的方式,可以用代理传数据
    • 参数:
      • 参数只适合比较少的数据,10个以内
      • 如果太多的话,就感觉在也不会爱了
    • block
      • 主要传递代码
    • 代理,==适合传输多个数据==
      • 当数据较多的时候
      • 调用代理中的方法获得返回值
      • 在类中实现方法,控制返回值.

Foundation框架

苹果或者牛X的第三方事先将程序员在编程的时候经常要用到的一些功能写好.把这些功能封装在一个一个的类中,这些类的集合就叫做框架.

不同的框架中的类是用来做不同的事情的

-不同的框架中的类是用来做不同的事情的
- Foundation: 包.有很多类 函数 数据类型.
- 基础,基本,这个框架中定义的是我们最基础的类
- 其他的框架都是基于Foundation框架的
- AVFoundation : 音频视频相关的
- UIKit: 做界面的
- CoreLocation : 定位有关的

  • 这几天为大家介绍Foundation框架中最常用的类.
    • 特点:
      • 简单到爆~只学怎么用.不要研究底层
      • 量大,各种记.
      • 介绍最常用的.

后面要学的类

NSString
NSURL
NSMutableString
NSArray
NSMutableArray
NSNumber
NSDictionary
NSMutableDictionary
NSFileManager
NSData
NSDate
CGPoint
CGSize
CGRect
NSValue
copy
单例

NSString类.

NSString是一个类,定义在Foundation框架中的.

NSString对象的作用:用来存储字符串数据的.

标准的创建方式NSString *str1 = [[NSString alloc] init];.
这样的方式创建的字符串对象中存储的数据是@"",空字符串.

NSString是OC当中最常用的对象.

所以为了快速的创建NSString对象
OC提供了一种更为快捷的方式创建NSString对象.
使用@符号
@”jack” 是创建NSString对象的简写方式
本质上是一个NSString对象,对象存储的是”jcak”这个字符串
str中存储的是对象的地址. NSString *str = @"jack";.
实际上是创建了一个字符串对象,将jack存储进去.

%@本质.

%p 是打印地址
%@ 是打印指针指向的对象.调用对象description方法.

NSString的恒定性.

我们创建字符串对象的时候,如果使用@来创建

那么这个字符串对象是存储在常量区中的.
如果调用类方法来创建字符串对象,这个对象是存储在堆空间中的
NSString *str1 = @”jack”; //这个字符串对象存储在常量区的(数据段)
NSString *str2 = [NSString new]; //这个字符串对象是存储在堆区的.
NSLog(@”str1 = %p”,str1);
NSLog(@”str2 = %p”,str2);
你会发现,这两个对象的地址相差很多 说明他们不在1个区中.

什么叫恒定性

存储在内存中的字符串对象,无论是在堆区还是常量区
这个字符串对象的内容是无法更改的.

字符串一旦创建,这个字符串对象中存储的字符串数据就不能改变
永远都只能存储这个

为NSString指针重新赋值一个字符串的时候,并不是修改原来的哪个字符串
而是重新的创建了一个字符串对象,将这个新的字符串对象的地址赋值给指针

==不可更改性,即针对堆区,也针对常量区字符串对象==

当系统要在内存中创建一个字符串对象的时候.

比如:当准备要在常量区创建字符串对象的时候,会先检查常量区中是否有内容相同的字符串对象,如果有,直接指向,没有才会创建.

堆区:
1. 如果字符串创建在堆区,不回去检查常量区.
2. 只会检查堆区中是否有相同内容的字符串对象,如果有直接指向,如果没有才会重新创建

常量区中的数据是不会被回收肚的.

存储爱常量区中的字符串不会被回收.
NSString *str1 = @"jcak"; str1 = nil;.

为什么不回收.因为对象的引用计数器不为0;
为什么字符串不允许回收呢?
为了提高效率.不止苹果,所有的语言都认为字符串你用了一次肯定还会用第二次
提高效率, 当第二次使用的时候,效率就高了.因为不用创建字符串对象了.

NSString 最常用的5个方法.

  1. 得到字符串的长度@property (readonly) NSUInteger length;
  2. 得到指定下标的字符- (unichar)characterAtIndex:(NSUInteger)index;返回值是unichar,打印用大C %C .
  3. ==以拼接变量的方式组成一个新的字符串==+ (instancetype)stringWithFormat:(NSString *)format, ... , ... 代表随便给多少个参数
  4. ==判断两个字符串是否相等== - (BOOL)isEqualToString:(NSString *)aString;;

== 判断的是左右两边的值是否相等.

NSString *str1 = @"jack";
NSString *str2 = [NSString stringWithFormat:@"jack"];

这个str1 和 str2的值就不一样了,在不同的区
所以判断两个字符串的内容是否相等千万不要用 ==
而是用对象方法.

  1. 将C语言的字符串转换为OC字符串对象.+ (nullable instancetype)stringWithUTF8String:(const char *)nullTerminatedCString;

nullable 代表返回的对象可能是nil.当转换失败的时候.

  1. 将OC字符串转换为C字符串. [str UTF8String]; 不太常用
    @property (nullable, readonly) __strong const char *UTF8String

NSString 常用方法.

  1. 将字符串写入到指定的文件当中- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error;
path : 路径
encoding: 字符编码 建议NSUTF8StringEncoding
NSString *str = @"我爱你!";
NSError *err = nil;
BOOL res = [str writeToFile:@"/Users/admin/Desktop/abc.txt" atomically: NO encoding:NSUTF8StringEncoding error:&err];
// YES 创建临时文件,成功在拷贝到指定目录.NO 效率高,不安全. 要效率,建议NO
//二级指针,error:如果发生错误err就会指向一个错误对象,可以得到错误的信息.
  1. 从指定的文件中读取字符串数据+ (nullable instancetype)stringWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error;

str的值如果是nil 说明失败.
err的值如果不是nil 说明失败

  1. 字符串还可以从网络上读写数据

可以读取一个网页的源代码.ftp服务器上的文件也可以读取.
URL:同意资源路径,也就是一个网址ftp文件的地址.磁盘上的文件的地址.

网址的URL标准写法: http://www.itheima.com
ftp文件的URL标准写法: ftp://server.itheima.com/aa.avi
磁盘文件路径: file:///Users/Itcast/Desktop/abc.txt

NSString可以从一个URL路径中读写数据.

  • 先将URL路径封装在1个NSURL对象中
    • NSURL *url1 = [NSURL URLWithString:@"http://www.itheima.com"];
    • NSURL *url2 = [NSURL URLWithString:@"ftp://server.itheima.com/1.txt"];
    • NSURL *url3 = [NSURL URLWithString:@"file:///Users/Itcast/Desktop/abc.txt"];
  • 使用类方法从NSURL对象中读取数据.
    • + (nullable instancetype)stringWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error;
  • 往NSURL中写入数据

    • - (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error;

      1. 字符串比较方法
        - (NSComparisonResult)compare:(NSString *)string; 返回值是枚举-1 0 1
  • 指定选项的比较

    • 忽略大小写的比较
      • int len = [str1 compare:str2 options:NSCaseInsensitiveSearch];;
      • 如果忽略大小写一样的话返回0;
    • 完全匹配的比较
      • int len = [str1 compare:str2 options: NSLiteralSearch];
      • 等于没给参数.
    • 比较字符串中的数字的大小
      • int len = [str1 compare:str2 options: NSNumericSearch];
      • 比较的是字符串中的数字的大小.
      • 前提是:两个字符串的格式要相同,一般情况下用来比较两个路径.
  • 判断字符串是否以指定的字符串开始的
    • - (BOOL)hasPrefix:(NSString *)str;
  • 判断字符串是否以指定的字符串结束的.
    • - (BOOL)hasSuffix:(NSString *)str;
  • 在字符串中搜索子字符串的范围
    @"i love rose";

    @"love";

    范围: 起始下标是:2 长度: 4


    - (NSRange)rangeOfString:(NSString *)searchString

    返回值代表子字符串在主串中的范围.
    返回值是个NSRange 这是1个结构体.

     typedef struct _NSRange {
        NSUInteger location;
        NSUInteger length;
     } NSRange;

     location:  代表这段范围的起始下标.
     length: 代表匹配的长度.


     如果在主串中没有找到子串. 返回的NSRange结构体变两的length的值就是0.location的值就是NSUInteger的最大值.
     所以,如果我们要判断是否在主串中找了子串.
     1). 判断返回的NSRange结构体的length是否为0
     2). 也可以判断location的值是否为最大值.NSNotFound就代表它的最大值.

     如果找到的情况下:
     location的值 是第一次匹配到的下标.
     length的值就是子串的长度.

你可能感兴趣的:(oc加强)