iOS 客户端-iOS系统框架之Foundation框架 | 青训营笔记

361 阅读8分钟

这是我参与「第四届青训营 」笔记创作活动的的第17天

一、前言

今天学习到的是【iOS 客户端专场 学习资料一】第四届字节跳动青训营的第二节:iOS系统框架之Foundation框架;在IOS开发中,Foundation框架是包含常用一些结构体、枚举、类的一个框架;Foundation框架定义了一下功能;基本的对象:NSNumber 、NSString 、NSDate;常用结构体和枚举:基本集合:NSArray 、NSDictionary 、NSSet;内存管理:操作系统服务:文件操作、URL、进程

二、本节课知识点大纲:

image.png

Foundation框架

Foundation框架

框架 Foundation

Foundation框架为 App和其他框架提供了基础的能力,包括 数据存储持久化,文本处理,日期时间计算,排序筛选,还有网路。并且Foundation框架的能力是MacOS, iOS, watchOS, tvOS通用的

Foundation.h

上面那行 import <Foundation/Foundation.h>就是引入Foundation框架的Foundation头文件,

而Foundation头文件里面的内容呢,就是把所有Foundation框架中公开类的头文件给引入了,那这样我们一行引入就等于把所有的类的声明都给引入了,像Foundation.h这种没有其他声明,但是把所有公开类都引入的头文件,我们称作 Umbrella Header 伞头文件

NSObject 类

  • 所有类的根类 (root Class)
  • 大量的适应Objective-C语言的方法
  • NSObject是一个遵守NSObject协议的类

NSObject - 分配内存空间 & 初始化

在创建任何一个对象时,都会用到这两个方法 alloc 和 init

首先调用的静态方法 alloc 系统会为这个对象分配内存并返回一个空的实例

之后在调用init实例方法进行初始化,通常子类也会覆盖这个方法去做相应的初始化

还有另外一个用法 new ,它等于 alloc + init,我们自己定义的类或是其他系统类,也都可以使用 new 去创建对象,代替 alloc + init

NSObject - 发送消息(方法调用)

透过 performSelector这种方式调用呢,不会在编译时做任何的较验,也就是你可以去创建一个该对象没有在interface声明的方法选择器,并调用,那由于没有编译器把关,如果该方法确实没有实现那就会崩溃,所以一般在使用时会搭配 respondsToSelector 提前确认该对象是否响应消息

通常这种 interface没有声明还要使用performSelector去掉用的情况:

  • 第一个可能是这个方法是在运行时透过Runtime添加进来的方法,在编译时不存在
  • 第二种可能是在明确知道该对象有些实现私有方法,但没有声明在interface时,会使用 performSelector去掉用

NSObject - 类关系判断

判断类别常用在你不确定某个对象的类型时,例如你从一个数组或字典里取出来一个对象,你只能确定这个对象保存的可能是字符串,数字,或是某个字定义类,这时候你就需要先使用if判断加上 isKindOfClass方法,你能确定他是某个类型后,在去做类型转换根方法调用

类关系判断使用场景

// 字典对应的不确定类型
NSObject *getValue = [dictionary1 objectForKey:@"key1"];
if ([getValue isKindOfClass:NSString.class]) {
    // 确定是NSString 在转型成NSString
    NSString *strValue = (NSString *)getValue;
    [strValue length];
} else if([getValue isKindOfClass:ByteDancer.class]) {
    // 确定是ByteDancer 在转型成ByteDancer
    ByteDancer *byteDacner1 = (ByteDancer *)getValue;
    [byteDacner1 sayHello];
} else {
    NSLog(@"unkown class");
}
复制代码

数据类型

NSString 字符串

NSString是在Objective-C语言里最常用的专门处理字符串的类,OC的字符串纯值可以使用C语言的 char形式的纯字符串。而NSString 它继承自NSObject,有方法有变量,妥妥的是个类,不过一般开发不太会使用纯字符串,因为他不好跟其他数据交互,而是使用NSString,所以我们还是把它视为OC里的字符串。

NSString - 创建

NSString有许多种的创建方式,若是双引号前面不加 @符号,那就是纯的C字符串,如果使用了 @双引号,那实际上创建了一个NSString对象

NSString - 类型转换

如果要将其他类型单独或组合转换成字符串,可以使用initWithFormat初始化方法,使用类似C语言的格式化表达创建,其中常用的格式例如 %d表达整数,%f 表达浮点数,还有一种 %@ 去获得一个对象的描述

如果%@是用在NSString对象上那就是该字符串的值,如果是用在其他对象上则会获得该对象description方法里的回传值,通常是该对象的类和内存地址描述

如果要将现有的字符串转成基础类型,可以直接使用 NSString提供的方法转成 int, float, double等等

NSArray 数组

NSArray跟NSString一样是NSObject子类,NSArray它也不是纯值类型了,所以具备了许多实现好的数组访问方法。如果你用过C语言的数组,就会觉得OC的NSArray实在是太方便了。

跟NSString一样,创建NSArray也有简写,使用 @ + 方框 就相当于创建一个NSArray对象

需要注意的是:NSArray中不能存放 int, float, bool 等基本类型,只能保存Objective-C对象,但是一个数组对象里面可以保存不同Class的对象,

因为每个Objc的对象实际是一个指针,所以从指针的这个角度来看的话,数组存放的每一项不管是什么类的对象都是等长的。这样处理比如length,get、add等操作的时候就非常简单了。

如果想保存基本类型的话可以透过NSNumber这个类去封装后在放进数组里

NSArray 查询

需要特别注意得是数组的查询都是针对对象指针的,也就是如果你拿另外一个虽然是同样内容的字符串查询,但因为不是同个对象,也会有查询不到的情况。

如果你想要寻找同等值的,可以使用 for循环去遍历数组,并比较字符串的内容

  • 对象数据可能被修改
  • 线程不安全
  • 查找性能较差
  • 一般用作方法内的临时变量,可做增删
  • 传进去的对象不会被修改
  • 线程安全
  • 查找性能好
  • 用于属性声明或是方法参数/回传值
// NSArray -> NSMutableArray
NSMutableArray *mutableArr1 = [[NSMutableArray alloc] initWithArray:numberArrayObject];
// NSMutableArray -> NSArray
NSArray *fixArr1 = [[NSArray alloc] initWithArray:mutableArr1];
复制代码

NSMutableArray 数据增删

如果在声明数组时没有限制数组的存放类型的话,那么任何对象都能被新增到数组里

可以单独新增对象,可以指定添加的位置,还能和入另外一个Array

删除则可以使用 删除末尾, 删除指定位置,和移除全部...等

除了这些方法还有需多修改方法,同学们可以查看NSMutableArray的头文件了解更多。

//MARK: NSMutableArray 数组增删 NSMutableArray *mutableArrayObject = [[NSMutableArray alloc] init];
// 新增任意对象
[mutableArrayObject addObject:@"StringObject1"];
// 在指定下标添加对象
[mutableArrayObject insertObject:@(0) atIndex:0];
// 批量添加
[mutableArrayObject addObjectsFromArray:@[@"StringObject2", @(1)]];

// 移除末尾
[mutableArrayObject removeLastObject];
// 删除指定下标
[mutableArrayObject removeObjectAtIndex:0];
// 移除全部
[mutableArrayObject removeAllObjects];
复制代码

NSDictionary 字典

字典它是一个基于Key-Value键值对访问的数据类型,我们在上一堂的实战中有使用到NSDictionary 来保存我们的JSON数据

跟字符串和数组类似,使用 @花括号就可以快捷的创建字典对象,

一般就使用NSString当做字典的Key做访问,而Value呢跟数组一样必须是个Objective-C的对象,如果要保存基础类型一样可以先转成NSNumber。

NSDictionary本身也是个OC对象,所以字典的Value也可以是字典对象,

// @{} = 创建NSDictionary对象
NSDictionary *dict1 = @{
    @"key1":@"value1"
};
// 效果同上
NSDictionary *dict2 = [NSDictionary dictionaryWithObject:@"key1" forKey:@"value1"];

// 多Key
NSDictionary *dict1 = @{
    @"key1":@"value1",
    @"key2":@"value2"
};
//效果同上
NSDictionary *dict5 = [[NSDictionary alloc]initWithObjects:@[@"value1",@"value2"] 
                                                   forKeys:@[@"key1",@"key2"]];
// 指定保存类型   
NSDictionary<NSString*, NSNumber*> *dictionaryObject = @{
    @"numberKey1": @(0),
    @"numberKey2": @(1),
}                                                                  

NSDictionary 访问

NSDictionary字典的访问方法跟NSArray数组类似,不过把访问的下标从整数替换成了字符串

如果这个字典在声明时没有加上类型限制Value是什么类型那不管使用key下标直接访问或是透过 objectForKey 方法访问,返回的都是id类型,也就是可能是任意类型的对象,

在调用这个从字典里取出来的对象方法时,谨慎一点都要先判断过类型,否则如果这对象不是我们预期的类型,我们还去掉用方法,就会导致崩溃

NSMutableDictionary 增删

字典也分为了不可变字典NSDictionary以及可变字典NSMutableDictionary

如果在声明字典对象时没有指定任何类型,那这个字典就可以添加任何的NSObject子类对象。

引用参考:

课外补充引用:

文章学习来源:

感谢以上作者的文章,今天的学习收获满满!!Thanks and HappyCoding!