黑马程序员IOS开发基础班+就业班之基础班2:Objective-C学习笔记(上)

P1:OC概述

  • Objective-C:简称OC,面向对象的C语言,OC的本质还是C语言,将C语言复杂的、繁琐的语法封装的更为简单,OC语言完全兼容C语言.

P6:源文件后缀名

  • 源文件后缀名:.m,m代表OC中最重要的机制——消息机制.
  • main函数:仍然是OC程序的入口和出口,int类型的返回值(main函数的返回值类型为int)代表程序的结束状态.

P7:#import指令

  • #import指令:以#号开头,是一个预处理指令,比#include指令更强(可以防止头文件重复导入)

P8:Foundation框架

  • 框架:是一个功能集,苹果或者第三方事先将一些程序开发经常要用的功能封装好,将它们封装在类或者函数之中,类和函数的集合就叫框架.
  • Foundation框架:该框架提供了一些最基础的功能(输入和输出),及一些数据类型,Foundation.h文件中包含了框架中其他所有的头文件.
#import <Foundation/Foundation.h>
//表示引入foundation框架中的foundation头文件

P9:自动释放池与NSLog函数

  • 自动释放池
@autoreleasepool
  • NSLog函数:Foundation框架中的函数,是printf函数的增强,向控制台输出信息.
    语法
NSLog(@"格式控制字符串",变量列表);
或者
NSLog(@"要输出的信息");

改进之处
1.会输出一些跟调试相关的信息(执行这段代码的时间,项目名称,进程编号,线程编号).
2.会自动换行.
3. OC中新增的数据类型只能用NSLog函数输出.


P10:NSString

  • OC中的字符串必须要使用前缀@符号
  • NSString:是OC中设计的存储字符串的
  • OC中使用%@,输出对象

P11:NS前缀和@符号

  • NS前缀:来自NextStep,标记类来自哪里
  • @符号
    1.将C字符串转换为OC字符串
    2.OC中的绝大部分的关键字是以@符号开头

P12:注释和函数的定义和调用

  • 注释:和C语言的注释一样,分为单行注释和多行注释
  • 函数的定义和调用:与C语言的函数的定义和调用是一样的

P13:OC程序的编译、链接、执行

  • OC程序的编译、链接、执行
    1.在.m文件中写上源代码
    2.使用编译器将源代码编译为.o目标文件
    3.链接
    4.成功以后会生成.out可执行文件
  • 编译过程
    1.预处理
    2.检查语法
    3.编译

P14:OC的数据类型

  • OC支持C语言中的所有数据类型
    1.基本数据类型:int、double、float、char
    2.构造类型:数组、结构体、枚举类型
    3.指针类型
    4.空类型:void
    5.typedef自定义类型
  • OC特有的数据类型
    1.BOOL类型:YES、NO(推荐使用)
    2.Boolean类型:true、false
    两者本质上是一样的
    3.class类型:类
    4.id类型:万能指针
    5.nil:同NULL差不多
    6.SEL:方法选择器
    7.block:代码段

P15:OC语言完全兼容C语言

  • OC支持C语言中所有的运算符
    1.赋值运算符:=
    2.算术运算符:+ - * / %
    3.复合赋值运算符:+= -= *= /= %=
    4.自增与自减:++ –
    5.关系运算符:> >= < <= == !=
    6.逻辑运算符:&& || !
    7.取地址运算符:&
    8.指针访问运算符:*
    9.位运算符:& | ^ ~
  • OC支持C语言所有的控制语句
    1.if结构
    2.switch-case结构
    3.while
    4.do-while
    5.for
    6.数组
    7.指针
    8.函数
  • OC支持C语言中全部的关键字,且效果一致
  • OC新增了一些关键字
  • OC与C语言的函数定义与调用完全一致

P17:代码中的面向过程与面向对象

  • 面向过程面向对象的优缺点:
    1.面向过程的缺点:后期的维护和修改不方便
    2.面向过程的优点:后期的维护和修改方便

P19:类和对象

  • 对象:是现实生活中的具体存在,是类的实体化
  • :对具有相同特征或行为的事物的统称,类是抽象的

P20:类和对象之间的关系

  • 类和对象之间的关系:类是模板,类的对象是根据这个模板创建出来的

P21:类的设计和名词提炼法

  • 设计类的三要素
    1.类的名字
    2.类的属性/成员变量/实例变量/字段(属性名通常以下划线开头)
    3.类的行为
  • 名词提炼法:分析整个业务流程,分析出现了哪些名词,名词就是业务需要的类

P22:类的定义

  • 类的定义
    1.位置:直接写在源文件之中,不要写在main函数之中
    2.类的定义分为两个部分:

1).类的声明

@interface 类名:NSObject
{
      
	将类的属性定义为变量
	数据类型 变量名
}
	方法的声明
@end

2).类的实现

@implement
	方法的实现
@end

3.注意:类名的每个首字母大写


P23:类的对象的创建

  • 创建对象
类名 *对象名 = [类名 new];
类名 *对象名 = [[类名 alloc] init];

P24:访问对象的属性

  • 对象的属性
    1.默认情况下,对象的属性不允许外界直接访问
    2.如果允许对象的属性可以被外界访问,那么就在声明属性前加一个@public关键字
  • 访问对象的属性
方式一:对象名 -> 属性名(推荐使用)
方式二:(*对象名).属性名

对象.xxx 的语法后跟的不是成员变量,是一个可以被访问的方法名,之所以让你感觉"对象.成员"便令这种方式调用,是因为用@property定义或者手动设置了这个变量的setter和getter方法的方法名和成员变量一样,实际调用的是方法


P26:方法的声明、实现、调用

  • 无参数的方法
    1.声明:

在@interface的大括号的外面
语法:- (返回值类型)方法名称

2.实现:在@implementation之中实现
3.调用:

[对象名 方法名];
  • 带一个参数的方法
    1.声明:
语法:- (返回值类型)方法名称:(参数类型)形参名称;

2.实现:同上
3.调用:

[对象名 方法名:实参];
  • 带参数的方法声明的规范
    1.如果方法只有一个参数,方法名最好命名为:
    xxxWith:/xxxWithXxx:
    2.如果方法有多个参数,方法名最好命名为:
    xxxWith:(参数类型)参数名称 and:(参数类型)参数名称 and:(参数类型)参数名称/xxxWithXxx:(参数类型)参数名称 andXxx:(参数类型)参数名称 andXxx:(参数类型)参数名称

P27:同一个类的多个对象

  • 注意
    1.同一个类可以创建无数个对象
    2.同一个类的多个对象之间毫无关系

P28:方法中直接访问属性

  • 注意:在类中、方法中可以直接访问属性

P31:类加载

  • 内存中的五大区域
    1.栈:存储局部变量
    2.堆:程序员手动申请的字节空间
    3.BSS段:存储未被初始化的全局变量、静态变量
    4.数据段(常量区):存储已被初始化的全局变量、静态变量、常量数据
    5.代码段:存储程序的代码
  • 类加载
    1.在创建对象的时候,会访问类
    2.声明一个类的指针变量也会访问类
    在程序运行期间,当某个类第一次被访问到的时候,会将这个类存储到内存中的代码段区域——类加载
    只有在类第一次被访问的时候才会进行类加载,一旦类被加载到代码段以后,直到程序结束的时候才会被释放

P32:对象在内存中的存储

Person *p1 = [Person new];
  • Person *p1:会在栈内存中申请一块空间
  • [Person new]:new的作用是:1.在堆内存中申请一块合适大小的空间;2.在这个空间中根据类的模板创建对象;3.初始化对象的属性(如果属性的类型是基本数据类型:赋值为0;如果属性的类型是C语言的指针类型:赋值为NULL;如果属性的类型是OC的类指针类型:赋值为nil);4.返回对象的地址
  • 注意
    1.对象中还有另外一个属性,叫做isa,是一个指针,指向对象所属的类在代码段中的地址
    2.对象的内存空间中只有属性,没有方法(通过isa指针找到类中的方法,然后调用)
  • 不将方法存储在对象之中的原因:减少空间的占用

P33:nil和NULL

  • NULL:只能作为指针变量的值,代表这个指针不指向内存中的任何一块空间(等价于0)
  • nil:只能作为指针变量的值,代表这个指针不指向内存中的任何一块空间(等价于0)
  • NULL和nil其实是一样的
  • 使用建议:C指针用NULL,OC的类指针用nil

P34:多个指针指向同一个对象

Person *p1 = [Person new];
p1 -> _name = @"小明";
Person *p2 = p1;
p2 -> _name = @"小花";
  • p1和p2此时指向同一个对象,因此修改p2的属性会导致p1的属性也发生改变
  • 注意:同类型的指针变量之间是可以相互赋值的

P35:分组导航标记

  • 分组导航标记:相当于一种注释
#pragma mark 分组名
#pragma mark -
#pragma mark - 分组名

P36:函数与方法的对比

  • 相同点:都是用来封装代码,只要被调用,被封装的代码就会被执行
  • 不同点
    1.语法不通
    2.定义的位置不一样:OC方法的声明只能写在@interface中、实现只能写在@implementation中
    3.调用方式不同
    4.方法是属于类的,函数是独立的

P37:常见错误

  • 属性不允许声明的时候初始化

P38:多文件开发

  • 多文件开发:将一个类写在一个模块之中,而一个模块包含两个文件(.h:写类的声明、.m:写类的实现)

补充:在写oc代码时,常常会发现,在.h文件中,有@interface的申明,在.m文件中,也有
.h里面的@interface,它是供其它Class调用的。它的@property和functions,都能够被其它Class“看到”(public)
而.m里面的@interface,在OC里叫作Class Extension,是.h文件中@interface的补充。但是.m文件里的@interface,对外是不开放的,只在.m文件里可见(private)
因此,我们将对外开放的方法、变量放到.h文件中,而将不想要对外开放的变量放到.m文件中(.m文件的方法可以不声明,直接用)

  • 注意
    1.类名一般和文件名保持一致
    2.注意引入头文件

P39:对象作为方法的参数

  • 类的本质:类是我们自定义的一个数据类型
  • 数据类型的本质:数据类型是在内存中开辟空间的一个模板
  • 语法注意
    1.当对象作为方法的参数时,参数类型是类指针
    2.当对象作为方法的参数传递的时候,是地址传递(原因:使用指针变量作为参数),故在方法内部通过形参修改形参指向的对象的时候,会影响实参变量指向的对象的值

P41:对象作为方法的返回值

  • 使用对象作为方法返回值的条件:当方法执行完之后,如果有一个对象方法的内部是未知的,且这个对象是调用方法者需要的,此时将对象作为返回值
  • 如果方法的返回值是一个对象,那么方法的返回值类型应该写类指针(原因:OC中的对象都是类指针)

P42:对象作为类的属性

  • 属性的本质:属性的本质是变量
  • 如果对象的属性是另外一个类的对象,创建对象时,这个属性仅仅是一个指针变量,并没有对象产生,要记得给属性赋值

P43:类的属性和方法

  • 一个Target中的类无法直接在另外一个Target中访问
  • 属性是类拥有的东西,方法是类拥有的行为

P51:异常的基本使用

  • 错误:一般指我们写的源代码不符合语法规范,然后编译报错
  • bug:程序可以编译、链接、执行,但程序的执行结果不符合我们的预期
  • 异常:程序可以编译、链接、执行,当程序在执行的时候,处于某种特定条件下,程序的执行会被终止
  • 处理异常
    1.目的:为了让程序在执行的时候如果发生异常不崩溃,而是继续往下执行
    2.语法:
@try
{
     
	//存放有可能发生异常的代码,当@try中的代码发生异常时不会崩溃,而是会立即跳转到@catch中的代码,当@catch的代码执行完毕之后,直接往下运行;若代码没发生异常,就会略过@catch往下执行
}
@catch(NSException *ex)
{
     
	//写处理异常的代码
}
@finally
{
     
	//无论@try中是否发生异常,@finally中的代码都会执行
}

P52:异常处理使用注意

  • @catch的参数NSException *ex,通过打印出ex指向的对象的值,可以得到发生异常的原因
  • @try…@catch并不是万能的,不是所有的运行时错误都能处理,且无法处理C语言的异常
  • 实际开发中@try…@catch使用并不多,通常避免异常的方式还是使用逻辑判断

P53:类方法的声明和调用

  • OC方法的分类
    1.对象方法/实例方法(-):如果想调用对象方法就必须先创建对象,通过对象名来调用
    2.类方法(+):类方法的调用不依赖于对象,如果想调用类方法不需要创建对象,直接通过类名来调用
  • 类方法的调用
[类名 方法名];

P54:类方法的特点

  • 类方法的特点
    1.节约空间:因为调用方法不需要创建对象,节约了空间
    2.提高效率:直接通过类调用类方法
    3.会破坏封装性
  • 注意
    1.在类方法中不能直接访问属性(原因:属性是在对象创建的时候,跟随着对象一起创建在对象之中)
    2.在类方法中不能通过self调用对象方法(原因:???)
    3.在对象方法中可以直接调用类方法

P55:类方法的定义规范

  • 类方法的定义规范
    1.如果我们写一个类,那么要求为这个类提供一个和类名同名的类方法,这个方法创建一个最纯洁的对象返回
    2.如果希望创建的对象的属性的值由调用者指定,那么就为这个类方法带参数

P56:NSString的本质是一个类

  • NSString的本质:NSString是Foundation框架中的1个类,所以OC中的字符串本质上使用NSString对象来储存的

P57:NSString常用方法

  • NSString常用的类方法
1.+ (nullable instancetype)stringWithUTF8String:(const char *)nullTerminatedCString;
/*
instancetype作为返回值,代表返回的是当前这个类的对象
作用:将C语言的字符串转换为OC字符串对象,参数为C语言字符串
*/
使用方法:
char *str0 = "rose";
NSString *str1 = [NSString stringWithUTF8String:str0];
2.+ (instancetype)stringWithFormat:(NSString *)format,...
/*
作用:拼接一个字符串对象,使用变量或其他数据拼接成OC字符串
*/
使用方法:
int age = 19;
NSString *name = @"小明";
NSString *str = [NSString stringWtihFormat:@"大家好,我叫%@,我今年%d岁",name,age];
  • NSString常用的对象方法
1.@property (readonly) NSUInteger length;
/*
作用:length方法返回值为NSUIneteger(实际是unsigned long),得到字符串的字符个数,可以处理中文
*/
使用方法:
NSString *str = @"itcast";
NSUInteger len = [str length];
2.- (unichar)characterAtIndex:(NSUInteger)index;
/*
作用:得到字符串中指定下标的字符,返回值为unichar(实际是unsigned short),如果要输出unichar变量使用%C
*/
使用方法:
NSString *str = @"itcast";
unichar ch = [str characterAtIndex:2];
NSLog(@"ch = %C", ch);
//结果为c
3.- (BOOL)isEqualToString:(NSString *)aString;
/*
判断两个字符串内容是否相同不要使用==判断
作用:判断两个字符串的内容是否相同
*/
使用方法:
NSString *str1 = @"jack";
NSString *str2 = [NSString stringWithFormat:@"jack"];
if([str1 isEqualToString:str2]) {
     
	//相等
}
else {
     
	//不相等
}
4.- (NSComparisonResult)compare:(NSString *)string;
/*
作用:比较两个字符串大小,NSComparisonResult为枚举类型,返回值为-1:小于;0:等于;1:大于
*/
使用方法:
NSString *str1 = @"jack";
NSString *str2 = @"rose";
NSComparisonResult res = [str1 compare:str2];
*/

P58:匿名对象

  • 匿名对象:没有名字的对象,创建一个对象,没有使用一个指针指向这个对象,那么称这个对象为匿名对象
  • 匿名对象的使用
[Preson new]->_name = @"jack";
[[Preson new] sayHi];
//注意:上面是创建了两个对象
  • 注意
    1.匿名对象只能使用一次
    2.每次创建匿名对象都是不同的对象
  • 匿名对象的使用场景
    1.如果某个对象只会被我们使用一次,那么可以使用匿名对象
    2.如果方法的参数是一个对象,而调用者为这个参数赋值的对象,就是专门来给这个方法传递的,那么就可以直接为方法传递一个匿名对象

P59:面向对象的三大特性

  • 面向对象的三大特性
    1.封装
    2.继承
    3.多态
  • 封装:类就是更高级别的封装,类将数据和行为封装成了一个整体
  • 封装的优点
    1.屏蔽内部的实现
    2.方便操作
    3.后期的维护十分便利

P60:setter的封装

  • 为类提供一个方法,这个方法专门为属性赋值——setter方法:
    1.这个方法一定要是对象方法(因为要为对象的属性赋值)
    2.这个方法无返回值
    3.这个方法的名称:必须以set开头,跟上首字母大写的属性名(例:setAge)
    4.该方法有参数,参数的类型和属性的类型一致,参数的名称和属性的名称一致
    5.方法的内部逻辑:在方法的实现中,判断传入的数据是否符合逻辑,如果符合逻辑则赋值,否则做默认处理
    6.方法的使用方法:外界想要为对象的属性赋值,就调用这个对象的setter方法,将要赋值的数据传入给这个方法

P62:getter的封装

  • 为类提供一个方法,用来返回属性的值——getter方法:
    1.这个方法一定要是对象方法(因为要取得对象属性的值)
    2.这个方法有返回值,返回值的类型和属性的类型一致
    3.这个方法的名称:直接就是属性的名称(例:age)
    4.这个方法没有参数
    5.方法的内部逻辑:直接将属性的值返回
    6.方法的使用方法:对象直接调用这个方法

P64:封装的规范与只读只写封装

  • setter和getter方法的使用条件
    1.只要属性需要被外界访问,就要为这个属性封装settet和getter方法,哪怕属性没有任何逻辑验证
    2.如果属性只在内部访问,则不需要封装setter和getter方法
  • 只读封装和只写封装
    1.只读封装:只为属性提供getter方法
    2.只写封装:只为属性提供setter方法

P65:类与类之间的关系之组合关系

  • 组合关系:一个类是由其他几个类组合而成(例:一个类的属性是其他类,且这个类是由其他的类组合起来的)

P66:类与类之间的关系之依赖和关联关系

  • 依赖关系:一个对象的方法和参数是另外的对象(例:b类是a类方法的参数,则说a类依赖于b类)
  • 耦合度:修改一个对象对另外一个对象的影响程度
  • 高内聚:一个对象仅仅做自己相关的事情
  • 单一职责原则:一个类只做自己的事情
  • 关联关系:一个类是另外一个类的属性,但是它们两者是拥有关系

P71:static关键字

  • static关键字
    1.static不能修饰属性、方法
    2.可以修饰方法中的局部变量(如果使用static修饰方法中的局部变量,那么该变量就会变成静态变量,存储在静态区,当方法执行完毕之后不会回收,下次再执行这个方法的时候直接使用而不会再声明)
  • 注意:类方法如果返回的是当前类的对象,最好使用instancetype关键字

P72:在对象方法中使用self

  • self关键字:在对象方法中self指向当前对象
  • self的使用场景
    1.可以使用self访问当前对象的属性(self->属性)
    2.可以使用self调用当前对象的其他对象方法

P73:在类方法中使用self

  • self关键字:在类方法中self指向当前类
  • 取到类在代码段中的地址的方式
    1.调试查看对象的isa指针
    2.在类方法中查看self的值
    3.调用对象的对象方法class,就会返回这个对象所属的类在代码段中的地址
    4.调用类的类方法class,就会返回这个类在代码段中的地址
  • 注意
    1.对象方法不可以重名
    2.类方法不可以重名
    3.类方法和对象方法可以重名
  • self的使用场景
    1.可以使用self调用其他的类方法
  • 注意
    1.不可以在对象方法中使用self调用类方法(原因:在对象方法中self代表对象,而调用类方法是要使用类名)
    2.不可以在类方法中使用self调用对象方法

P74:继承的简单使用

  • 继承的语法
@interface 类名:父类名
  • 继承的效果:子类拥有父类所有的成员

P75:使用继承注意与满足继承的关系

  • 注意
    1.继承是类在继承,而不是对象在继承
  • 满足继承的关系:满足继承的关系是is关系

P76:继承的注意

  • 注意:只要有一个成员不是所有子类都拥有的,那么这个成员就不应该定义在父类中

P77:继承的特点

  • 继承的特点
    1.单根性:一个类只能有一个父类,不能有多个父类
    2.传递性:A类从B类继承,B类从C类继承,那么A类拥有B、C全部的特性

P78:NSObject类是所有类的祖宗类

  • NSObject类:是Foundation框架中的类,这个类中有一个类方法new,这个方法是用来创建对象的,方法的返回值是创建的对象的指针,故如果要让我们的类具备创建对象的能力,就必须要让我们的类直接的或者间接的从NSObject类继承;NSObject类之中还定义了一个isa属性

P79:super关键字

  • 注意
    1.子类中不能出现和父类同名的属性
  • super关键字
    1.可以使用在类方法和对象方法中
    2.在对象方法中可以使用super关键字调用当前对象从父类继承来的对象方法
    3.在类方法中可以使用super关键字调用当前类从父类继承来的类方法
    4.super关键字只能调用父类的方法,不可以使用super访问属性

P80:访问修饰符

  • 访问修饰符:用来修饰属性,限定对象的属性可以在哪个范围中访问
    1.@private:私有(只能在本类的内部访问)
    2.@protected:受保护的(只能在本类或者本类的子类中访问)
    3.@package:包(可以在当前框架中访问)
    4.@public:公共的(可以在任意地方访问)
  • 如果不为属性指定修饰符,默认为@protected
  • 如果父类的属性被修饰为@private,子类仍然可以继承父类的私有属性,但子类中无法直接访问从父类访问过来的私有属性,除非父类中有一个方法为这个属性赋值或取值,那么子类可以间接访问父类的私有属性
  • 访问修饰符的作用域:从写访问修饰符的地方开始往下,直到遇到另外一个访问修饰符或结束大括弧为止,中间所有的属性都应用这个访问修饰符
  • 使用建议
    1.@public:无论什么情况都不要使用
    2.@private:如果属性只想在本类中使用,不想在子类中使用
    3.@protected:如果属性只想在在本类和子类中使用(推荐)
  • 访问修饰符只能用来修饰属性,不能用来修饰方法

P81:私有属性

  • 将属性写在@implementation下的大括号里面,实现私有属性

P82:私有方法

  • 在.m文件中写方法的实现,.h文件中的声明删除,实现私有方法,只能在本类的其他方法中调用,不能在其他类中调用

P83:里氏替换原则

  • 里氏替换原则:子类可以替换父类的位置,并且程序的功能不受影响
  • 里氏替换原则成立的原因
    1.原本父类指针需要一个父类对象,子类对象就是一个父类对象,所以将子类对象赋值给父类对象的指针
    2.父类中拥有的成员子类都有,因此程序的功能不会受到影响
  • 里氏替换原则的表现形式:当一个父类指针指向子类对象的时候,就是里氏替换原则
  • 里氏替换原则的作用
    1.一个指针中不止可以存储本类对象的地址,还可以存储子类对象的地址
    2.如果一个指针的类型是NSObject,那么该指针可以存储任意OC对象的地址
    3.如果一个数组的元素类型是一个OC指针类型的,那么这个数组不仅可以存储本类对象还可以存储子类对象
    例:
Person *p[3];
p[0] = [Person new];
p[1] = [Student new];
p[2] = [ItClassStudent new];
//ItClassStudent继承Student,Student继承Person

4.如果一个数组的元素类型NSObject类型,那么任何的OC对象都可以存储到这个数组中
5.如果一个方法的参数是一个对象,为该方法传值的时候可以传递一个本类对象也可以传递一个子类对象

  • 当父类指针指向一个子类对象的时候,只能通过这个父类指针去掉用子类对象中的父类成员,子类独有的成员无法访问

P84:方法的重写

  • 重写:拥有父类的行为,但是行为的具体实现和父类的不一样,那么子类就按照自己的方式重写方法
  • 当一个父类指针指向一个子类对象的时候,通过父类指针调用的方法如果在子类中重写了,调用的是子类重写的方法(多态)

P85:多态

  • 多态:同一个行为,对于不同事物具有完全不同的表现形式(同一个行为具有多种形态)
  • 多态的表现形式:重写

P86:description方法

  • 当使用%@打印一个对象的时候,NSLog函数的底层实现
    1.调用传入的对象的description方法
    2.拿到该方法的返回值,返回值是一个字符串
    3.将字符串输出
  • description方法是定义在NSObject类之中的,因此每一个OC对象都有这个方法,可以重写
  • description方法在NSObject中返回的字符串格式:@"<对象所属的类名:对象的地址>"

P89:子类在内存中的存储和方法调用过程

  • 对象在内存中的分配
    1.子类对象中有自己的属性和所有父类的属性
    2.代码段(类加载的地方)中的每一个类都有一个isa指针,指向它的父类,一直指到NSObject类
  • 方法调用过程:先从本类中寻找方法,如果有执行,如果没有则根据类的isa指针在父类中寻找方法,一直寻找到NSObject

P90:结构体与类的区别

  • 结构体与类的相同点:都可以将多个数据封装为一个整体
  • 结构体与类的不同点
    1.结构体只能封装数据,而类不仅可以封装数据还可以封装行为
    2.结构体变量分配在栈空间(如果是局部变量的情况下),而对象分配在堆空间
  • 栈的特点:空间相对较小,但是存储在栈中的数据访问的效率更高
  • 堆的特点:空间相对较大,但是存储在堆中的数据访问的效率低一些
  • 应用场景
    1.如果表示的实体不仅有数据还有行为,只能使用类封装
    2.如果表示的实体没有行为只有属性,可以定义为结构体,分配在栈空间提高效率(但如果属性太多,定义为类,分配在堆空间)

P91:类是以class对象存储在代码段

  • 类第一次被访问的时候,就会被加载到代码段存储
  • 类一旦加载到代码段之后是不会被回收的,除非程序结束
  • 类存储在代码段的形式
    1.任何存储在内存中的数据都有数据类型
    2.用来在代码段存储类的空间

你可能感兴趣的:(ios)