iOS开发核心语言Objective C —— 所有知识点总结

本分享是面向有意向从事iOS开发的伙伴及苹果产品的发烧友,亦或是已经从事了iOS的开发人员,想进一步提高者。假设您对iOS开发有极高的兴趣,可以与我一块儿探讨iOS开发。一块儿学习,共同进步。假设您是零基础。建议您先翻阅我以前分享的iOS开发分分钟搞定C语言系列,而后在開始Objective C语言的学习,假设您遇到问题也可以与我探讨。另外将无偿分享本身整理出来的大概400G iOS学习视频及学习资料,都是干货哦。可以新浪微博私信➕关注极客James,期待与您的共同窗习和探讨!css

ios

因为时间有限,天天在工做之余整理的学习分享,不免有不足之处,也但愿各路大神指正!数据库

本次整理的内容涵盖Objective C 语言很是多重要问题及细节。很是重要哦!设计模式


made by 极客James
这里写图片描写叙述api

C和OC对照

  1. OC中主要开发在什么平台上的应用程序?数组


    答:可以使用OC开发Mac OS X平台和iOS平台的应用程序安全

  2. OC中新增关键字大部分是以什么开头?
    答:OC中新增关键字大部分是以@开头ruby

  3. OC中新添加了那些数据类型?
    答:Block类型
    指针类型(Class, id类型)
    空类型
    特殊类型(SEL, nil)bash

  4. 面向对象特性是什么?markdown


    答:继承性,封装性,多态性

  5. import和#include有什么差异?

    答:import 的功能和 include同样, 是将右边的文件复制到当前import的位置.为了下降程序猿的负担, 防止反复导入, 避免程序猿去书写 头文件卫士, 那么OC给出来一个新的预处理指令import
    import长处: 会本身主动防止反复拷贝

  6. printf和NSLog有什么差异?


    答: NSLog会本身主动换行
    NSLog在输出内容时会附加一些系统信息
    NSLog和printf接收的參数不同

  7. Foundation有什么做用?
    答:Foundation.h咱们称之为主头文件, 主头文件里又拷贝了该工具箱中所有工具的头文件, 咱们仅仅需要导入主头文件就可以使用该工具箱中所有的工具, 避免了每次使用都要导入一个相应的头文件

面向对象基本概念

  1. 什么是面向对象?
    答:对象是人们要进行研究的不论什么事物,从最简单的整数到复杂的飞机等都可看做对象,它不只能表示详细的事物,还能表示抽象的规则、计划或事件。

  2. 面向对象和面向过程的差异?


    答:
    1>面向对象是相对面向过程而言
    2>面向对象和面向过程都是一种思想
    面向过程
    强调的是功能行为
    关注的是解决这个问题需要哪些步骤
    面向对象
    将功能封装进对象,强调具有了功能的对象
    关注的是解决这个问题需要哪些对象

类与对象

  1. 什么是对象?
    答:对象是人们要进行研究的不论什么事物。从最简单的整数到复杂的飞机等都可看做对象。它不只能表示详细的事物,还能表示抽象的规则、计划或事件。

  2. 什么是类?
    答:具备一样特性(数据元素)和行为(功能)的对象的抽象就是类。

    所以,对象的抽象是类。类的详细化就是对象。也可以说类的实例是对象,类实际上就是一种数据类型。

  3. 类由几部分组成?


    答: 类(Class) 一个类由3个部分构成
    类的名称:类名
    类的属性:一组包括数据的属性
    类的方法:赞成对属性中包括的数据进行操做的方法

  4. 怎么来定义一个类?

    书写类的格式
    答:定义类要分为两部分: 声明和实现

类的声明格式
@interface 类名 : 父类名(NSObject)
{
定义实例变量(成员变量,属性)
}
方法的声明

@end

类的实现格式
@implementation 类名
方法的详细实现
@end;

5.OC中属性写在类中哪一个位置?


答:OC类声明中属性仅仅能在写@interface和@end之间的{}中

6.怎样经过类建立对象?

书写建立对象格式
答: 建立对象格式:
类名 *指针名 = [类名 new];

7.实例化对象调用哪一个方法?实例化对象作了哪3件事?
答:实例化对象调用类方法new
1.给对象分配存储空间
2.初始化类中的实力变量
3.返回对象内存地址

8.怎样訪问对象中的属性?
答:使用指针訪问
格式: 指针名->_属性名;

OC方法

  1. 方法和函数的差异?


    答:
    1)OC中的行为和C语言中的函数同样, 都是用来保存一段特定功能的代码
    C语言中定义一个函数, 分为声明和实现, 声明写在.h中, 实现写在.c中
    OC中定义一个方法, 也分为声明和实现, 声明写在@interface中, 实现写在@implementation

  2. C语言的函数分为两种: 内部函数和外部函数
    OC中的方法也分为两种; 类方法和对象方法

  3. 怎么声明和实现无參无返回值方法的?调用方法的格式?

    (书写格式)
    答:
    方法的声明格式:

  4. (返回值类型)方法名;
    方法的实现格式:
  5. (返回值类型)方法名{
    }
    调用方法格式:
    [对象名 方法名];
    或者 [类名 方法名];

  6. 小括号在OC方法中有什么用法?


    答:OC方法中的()有特殊的用途, OC方法中的()是用来扩住数据类型的

  7. 有參数方法格式是怎样?


    带一个參数
    方法声明
    ·- (返回值类型)方法名:(參数类型)參数名;

方法实现
- (返回值类型)方法名:(參数类型)參数名{

}

带多个參数
方法声明
- (返回值类型)方法名1:(參数类型)參数名1 方法名2:(參数类型)參数名2;
- (返回值类型)方法名1:(參数类型)參数名1 and方法名2:(參数类型)參数名
- (返回值类型)方法名1:(參数类型)參数名1 :(參数类型)參数名2;
方法实现
- (返回值类型)方法名1:(參数类型)參数名1 方法名2:(參数类型)參数名2{
}

OC类方法

  1. 类方法和对象方法的差异?
    答:
    0). 对象方法以-开头
    类方法以+开头
    1). 对象方法必须用对象调用
    类方法必须用类来调用
    2).对象方法中可以直接訪问属性(成员变量)
    类方法中不可以直接訪问属性(成员变量)
    3). 类方法和对象方法可以进行相互调用(展现代码)

  2. 类方法的应用场景?


    答:
    类方法通常用于定义工具方法
    字符串查找
    文件操做
    数据库操做

  3. isa是什么数据类型?
    答: 类的第0个属性并不是咱们编写的_age, 而是一个叫作isa的属性
    isa是对象中的隐藏指针,指向建立这个对象的类,占8个字节

方法和函数的差异

  1. 函数和方法的差异?
    答:
    1).函数属于整个文件, 方法属于某一个类
    方法假设离开类就不行
    2).函数可以直接调用, 方法必须用对象或者类来调用
    注意: 尽管函数属于整个文件, 但是假设把函数写在类的声明中会不识别
    3).不能把函数当作方法来调用, 也不能把方法当作函数来调用

  2. 方法有哪些的注意点?
    答:

    方法可以没有声明仅仅有实现
    方法可以仅仅有声明没有实现, 编译不会报错, 但是执行会报错
    假设方法仅仅有声明没有实现, 那么执行时会报:
    reason: ‘+[Person demo]: unrecognized selector sent to class 0x100001140’
    发送了一个不能识别的消息, 在Person类中没有+开头的demo方法
    reason: ‘-[Person test]: unrecognized selector sent to instance 0x100400000’

    常见的错误有哪些?
    1.仅仅有类的声明。没有类的实现
    2.漏了@end

  3. @interface和@implementation嵌套
    4.成员变量没有写在括号中面
    5.方法的声明写在了大括号中面
    6.成员变量不能在{}中进行初始化、不能被直接拿出去訪问
    7.方法不能当作函数同样调用
    8.OC方法仅仅能声明在@interface和@end之间,仅仅能实现在@implementation和@end之间。也就是说OC方法不能独立于类存在
    9.C函数不属于类,跟类没有联系,C函数仅仅归定义函数的文件所有
    10.C函数不能訪问OC对象的成员
    11.低级错误:方法有声明。但是实现的时候写成了函数
    12.OC可以没有@interface一样可以定义一个类

多文件开发

  1. 为何要使用多文件?


    答:
    一个iOS项目可能会有多我的开发,假设多我的同一时候改动一个文件,那么就很是可能会产生冲突,比方这个添加一个方法,那我的把这方法删掉了。

    另外就是当把多我的写功能合并起来的时候,也很是困难,写到一个文件里,没法顺畅的进行团队合做

  2. OC中怎样进行多文件开发?
    答:
    在工做中,一般把不一样的类放到不一样的文件里,每个类的声明和实现分开
    声明写在.h头文件里,
    实现写在相应的.m文件里去,
    类名是什么,文件名称就是什么

  3. 使用多文件开发有什么长处?


    答:
    显著提升团队协做的效率
    提升程序的开发速度
    提升程序的可维护性
    提升代码的可读性

面向对象特性

  1. :面向对象三大特性有哪些?
    答:继承性,封装性,多态性

  2. 什么是封装?

    封装的长处?封装的规范?


    答:
    封装: 屏蔽内部实现的细节, 仅仅对外提供共同拥有的方法/接口
    长处: 保证数据的安全性,将变化隔离
    规范: 普通状况下不会对外直接暴露成员变量, 都会提供一些共同拥有的方法进行赋值
    成员变量都需要封装起来

  3. 为何要进行封装?


    答:一个类把本身的成员变量暴露给外部的时候,那么该类就失去对该成员变量的管理权,别人可以随意的改动你的成员变量。

geeter-setter方法

  1. 什么是setter方法?

    sett方法的书写格式?
    答:setter方法就是给成员变量赋值的方法
    格式:
    (1) setter方法必定是对象方法
    (2) 必定没有返回值
    (3) 必定以set开头, 并且set后面跟上需要设置的成员变量的名称去掉下划线, 并且首字母大写
    (4) 必定有參数, 參数类型必定和需要设置的成员变量的类型一致, 并且參数名称就是成员变量的名称去掉下划线

  2. getter方法就是获取成员变量值的方法
    格式:
    (1) getter方法必定是对象方法
    (2)必定有返回值, 并且返回值必定和获取的成员变量的类型一致
    (3)方法名称就是获取的成员变量的名称去掉下划线
    (4) 必定没有參数

  3. 成员变量下面划线开头有什么长处?
    答:
    1.用于区分局部变量/全局变量/形參
    2.方便程序编码, 提升编码效率

  4. 解释一下什么是仅仅读属性?什么是仅仅写属性?可读可写的属性?

    私有属性?
    答:
    一个属性可以仅仅有getter方法, 没有setter方法, 这样的属性咱们称之为仅仅读属性
    一个属性也可以仅仅有setter方法, 没有getter方法, 这样的属性咱们称之为仅仅写属性
    假设既有setter方法又有getter方法, 那么这样的属性咱们称之为可读可写的属性
    一个属性也可以没有getter和setter, 这样的属性咱们称之为私有属性

点语法和self关键字

  1. 什么是点语法?点语法的本质?


    答:假设给属性提供了getter和setter方法, 那么訪问属性就又多了一种訪问方式 , 点语法.
    点语法的本质是调用了一个类的setter和getter方法

  2. 怎样使用点语法?
    答:
    点语法是一个编译器的特性, 会在程序翻译成二进制的时候将.语法本身主动转换为setter和getter方法
    假设点语法在=号的左边, 那么编译器会本身主动转换为setter方法
    假设点语法在=号的右边, 或者没有等号, 那么编译器就会本身主动转换为getter方法

  3. 点语法注意事项?
    答:点语法通常用于给成员变量赋值, 假设不是给成员变量赋值普通状况下不建议使用, 但是也可以使用

  4. 什么是成员变量?什么是对象方法?

    什么是类方法?
    答:
    成员变量:
    成员变量是一个实例对象的详细状态特征,并且这些状态特征是可以改变的。如张三的年龄,身高,体重等

对象方法:
一个实例对象的行为。比方张三具备吃的行为,张三作出这样行为的时候,有可能会影响,自身的某些状态特征。比方张三吃可能会添加张三体重和身高。

类方法:
类方法是某个类的行为,可以直接经过类名调用;假设在类方法中需要使用某些数据,必须经过參数传入。类方法不能訪问成员变量。

  1. 怎样使用self?


    假设self在对象方法中, 那么self就表明调用当前对象方法的那个对象
    假设self在类方法中, 那么self就表明调用当前类方法的那个类
    总结:
    咱们仅仅用关注self在哪个方法中 , 假设在类方法那么就表明当前类, 假设在对象方法那么就表明”当前调用该方法的对象”

  2. self有哪些注意事项?


    答:
    (1)self会本身主动区分类方法和对象方法, 假设在类方法中使用self调用对象方法, 那么会直接报错
    (2)不能在对象方法或者类方法中利用self调用当前self所在的方法

  3. self的有哪些使用场景?
    答:
    可以用于在对象方法之间进行相互调用
    可以用于在类方法之间进行相互调用
    可以用于区分红员变量和局部变量同名的状况

继承基本概念

  1. 什么是继承?什么是父类?

    什么是子类?怎样实现继承?
    答:
    1)子类得到父类的特性就是继承
    2)被继承的这个类咱们称之为父类/ 超类
    3)继承了某个类的类咱们称之为子类
    4)在声明子类的时候。在子类名称后面经过:父类名称方式来实现继承
    @interface 子类名称 : 父类名称

@end类

当B类继承A类, 那么B类就拥有A类所有的属性和方法(类方法/对象方法)

2.什么叫方法重写?重写后是以什么顺序调用方法的?
答:
(1)假设子类中有和父类中同名的方法, 那么咱们称之为方法重写
注意: 继承中的方法调用顺序, 假设本身有就调用本身的, 假设本身没有就调用父类的
“方法的调用顺序, 先本身再父类, 假设父类中没有再爷爷类, 假设爷爷类再没有就找爷爷的爸爸类
假设一直找到NSObject类都没有找到, 那么就会报错
reason: ‘-[Iphone signalWithNumber:]: unrecognized selector sent to instance 0x1003043c0’
注意:在继承中方法可以重写, 但是属性(成员变量)不能重写

3.方法重写的使用场景?


答:使用场景:当从父类继承的某个方法不适合子类,可以在子类中重写父类的这种方法。

4.继承的条件是什么?
答:
不要觉得继承可以提升代码的复用性, 之后但凡发现多个类其中有反复代码就抽取一个父类
仅仅要知足必定的条件咱们才干使用继承
条件: XXXX 是 XXX / 某某某 is a 某某某

5.继承的长处是什么?
答:
提升代码的复用性
可以让类与类之间产生关系, 正是因为继承让类与类之间产生了关系因此才有了多态

6.继承的缺点是什么?


答:
耦合性太强(依赖性太强)

super关键字

  1. 什么是super?


    super是个编译器的指令符号,仅仅是告诉编译器在执行的时候,去调谁的方法.

  2. 怎么使用super?
    答:
    super在类方法中, 必定会调用父类的类方法
    super在对象方法中, 必定会调用父类的对象方法
    可以利用super在随意方法中调用父类中的方法

  3. super使用场景?
    答:
    子类重写父类的方法时想保留父类的一些行为

多态

  1. 什么是多态?程序中是怎么体现多态的?


    答:
    多态就是某一类事物的多种形态
    在程序中怎样表现:
    父类指针指向子类对象

  2. 多态的条件是什么?
    答:
    1)有继承关系
    2)子类重写父类方法
    3)父类指针指向子类对象

  3. 多态的长处是什么?
    答:提升了代码的扩展性,复用性

  4. 多态的注意点?


    答:假设父类指针指向子类对象, 需要调用子类特有的方法, 必须先强制类型转换为子类才干调用

description方法

  1. 使用%@了打印一个对象,输出的是什么内容?%@的原理是什么?


    答:%@是用来打印对象的, description方法默认返回对象的描写叙述信息(默认实现是返回类名和对象的内存地址).
    事实上%@的本质是用于打印字符串.
    仅仅要利用%@打印某个对象, 系统内部默认就会调用父类的description方法
    调用该方法, 该方法会返回一个字符串, 字符串的默认格式 <类的名称: 对象的地址>

  2. 重写description方法注意点?


    答:假设在description方法中利用%@输出self会形成死循环
    建议: 在description方法中尽可能不要使用self来获取成员变量
    因为假设你常常在description方法中使用self, 可能已不当心就写成了 %@, self

私有变量和私有方法

  1. 什么是私有变量?什么是私有方法?
    答:
    实例变量(成员变量)既可以在@interface中定义, 也可以在@implementation中定义
    私有变量:
    写在@implementation中的成员变量, 默认就是私有的成员变量, 并且和利用@private修饰的不太同样, 在@implementation中定义的成员变量在其余类中没法查看, 也没法訪问

私有方法:
在@implementation中定义的私有变量仅仅能在本类中訪问

property和synthesize基本使用

  1. @porperty是一个编译器指令
    在Xocde4.4以前, 可以使用@porperty来取代getter/setter方法的声明
    也就是说咱们仅仅需要写上@porperty就不用写getter/setter方法的声明

  2. 编译器仅仅要看到@property,就知道咱们要生成某一个属性的
    getter/setter方法的声明

  3. @propertyde格式?


    答:@property 数据类型 变量名;

  4. @synthesize是什么指令?做用是什么?
    答:
    synthesize是一个编译器指令, 它可以简化咱们getter/setter方法的实现

  5. @synthesize age = _age; 在给age赋值时,编译器作了哪些事?
    @synthesize age = _age;
    (1)在@synthesize后面的age,告诉编译器, 需要实现哪一个@property生成的声明
    (2)告诉@synthesize, 需要将传入的值赋值给谁和返回谁的值给调用者
    假设在@synthesize后面没有告诉系统将传入的值赋值给谁, 系统默认会赋值给和@synthesize后面写得名称一样的成员变量
    @synthesize age;

  6. property加强作了哪些事?
    答:
    (1)从Xcode4.4之后,对@property进行了加强, 之后仅仅要利用一个@property就可以同一时候生成setter/getter方法的声明和实现

(2)假设没有告诉@property要将传入的參数赋值给谁, 默认@property会将传入的属性赋值给_开头的成员变量

7.@property的使用场景?
答:
假设不想对传入的数据进行过滤, 仅仅是提供方法给外界操做成员变量, 那么就可以使用@property,并且系统会本身主动给咱们生成一个_开头的成员变量

8.使用property加强后,何时要重写getter/setter方法?
答:使用property加强,仅仅会生成最简单的getter/setter方法的声明和实现, 并不会对传入的数据进行过滤
假设想对传入的数据进行过滤, 那么咱们就必须重写getter/setter方法

9.重写getter/setter方法有哪些注意点?
答:
假设重写了setter方法, 那么property就仅仅会生成getter方法
假设重写了getter方法, 那么property就仅仅会生成setter方法
假设同一时候重写了getter/setter方法, 那么property就不会本身主动帮咱们生成私有的成员变量

property修饰符

  1. 加强@property使用修饰符后的的格式是什么?


    答:
    格式:
    @property(属性修饰符) 数据类型 变量名称;

  2. @property 有哪些修饰符?各有什么做用?
    答:readwrite: 表明既生成getter方法 , 也生成setter方法
    默认状况下 @property就是readwrite的
    @property(readwrite) int age;
    ‘readonly: 表明仅仅生成getter方法不生成setter方法’
    可以给setter方法起别名@property(setter=tiZhong:) double weight;
    可以给getter方法起别名@property(getter=isMarried) BOOL married;

静态数据类型和动态数据类型

  1. 静态数据类型的特色:
    在编译时就知道变量的类型,
    知道变量中有哪些属性和方法
    在编译的时候就可以訪问这些属性和方法,
    并且假设是经过静态数据类型定义变量, 假设訪问了不属于静态数据类型的属性和方法, 那么编译器就会报错

  2. 动态数据类型的特色:
    在编译的时候编译器并不知道变量的真实类型, 仅仅有在执行的时候才知道它的真实类型
    并且假设经过动态数据类型定义变量, 假设訪问了不属于动态数据类型的属性和方法, 编译器不会报错

  3. id和NSObject * 的差异?
    答:
    NSObject *是一个静态数据类型
    id 是一个动态数据类型

  4. 动态数据类型的应用场景?
    答:动态类型主要用在多态, 可以下降代码量, 避免调用子类特有的方法需要强制类型转换

  5. 动态数据类型的弊端是什么?
    答:因为动态数据类型可以调用随意方法, 因此有可能调用到不属于本身的方法, 而编译时又不会报错, 因此可能致使执行时的错误

  6. 推断数据类型的有哪些方法?(变量 改动为 对象)
    答:为了不动态数据类型引起的执行时的错误, 普通状况下假设使用动态数据类型保存一个对象, 在调用这个变量的方法以前会进行一次推断, 推断当前对象可否够调用这种方法

构造方法

  1. 什么是构造方法?
    答:
    在OC中init开头的方法, 咱们称之为构造方法

  2. 构造方法的用途?


    答:
    构造方法的用途: 用于初始化一个对象, 让某个对象一建立出来就拥有某些属性和值

  3. 怎样实现构造方法?
    答:
    重写init方法, 在init方法中初始化成员变量

  4. 怎样重写init方法?


    答:重写init方法必须依照苹果规定的格式重写, 假设不依照规定会引起一些未知的错误
    (1)必须先初始化父类, 再初始化子类
    (2)必须推断父类是否初始化成功, 仅仅有父类初始化成功才干继续初始化子类
    (3)返回当前对象的地址

- (instancetype)init
{
    // 初始化父类
    // 仅仅要父类初始化成功 , 就会返回相应的地址, 假设初始化失败, 就会返回nil
    // nil == 0 == 假 == 没有初始化成功
    self = [super init];
    // 推断父类是否初始化成功
    if (self != nil) {
      // 初始化子类
      // 设置属性的值
        _age = 6;
    }
    // 返回地址
    return self;
}

本身定义构造方法

  1. 什么是本身定义构造方法?

    为何要本身定义构造方法?
    (1)本身定义构造方法就是本身定义一个init方法
    (2)有时候咱们需要在建立某个对象的时候,让对象的某些属性就具备值,这时候就需要传入一些參数给对象的属性,为了知足这个需求,就需要本身定义构造方法

  2. 本身定义构造方法的格式?
    答:
    (1)必定是对象方法
    (2)必定返回id/instancetype
    (3)方法名称必定以init开头
    -(instancetype)initWithAge:(int)age;

  3. 本身定义构造方法在继承中有一个原则?
    答:本身的事情本身作,属于谁的属性就由谁来进行操做
    父类的属性交给父类的方法来处理,子类的方法处理子类本身独有的属性

  4. 本身定义构造方法在子类,怎样调用的父类构造方法的?
    答:子类在重写自定构造方法时,通常使用super 调用父类的构造方法,先让父类将父类的属性进行初始化

- (instancetype)initWithAge:(int)age andName:(NSString *)name andNo:(int)no
{
    if (self = [super initWithAge:age andName:name]) {
        _no = no;
    }
    return self;
}

instancetype和id差异

  1. instancetype和id差异?
    答:
    (1)id在编译的时候不能推断对象的真实类型
    instancetype在编译的时候可以推断对象的真实类型

    (2)假设init方法的返回值是instancetype, 那么将返回值赋值给一个其余的对象会报一个警告
    假设是在曾经, init的返回值是id, 那么将init返回的对象地址赋值给其余对象是不会报错的

    (3)id可以用来定义变量, 可以做为返回值, 可以做为形參
    instancetype仅仅能用于做为返回值

  2. instancetype 应用场景?
    答:之后但凡本身定义构造方法, 返回值尽可能使用instancetype, 不要使用id

类工厂方法

  1. 什么是类工厂方法?
    答:用于高速建立对象的类方法, 咱们称之为类工厂方法

  2. 类工厂方法应用场景?
    答:类工厂方法中主要用于 给对象分配存储空间和初始化这块存储空间

  3. 类工厂方法使用规范?
    答:规范:
    1.必定是类方法 +
    2.方法名称以类的名称开头, 首字母小写
    3.必定有返回值, 返回值是id/instancetype
    4.在类工厂方法实现中,调用本类的构造方法,建立实例对象,并返回实例对象

本身定义类工厂方法是苹果的一个规范, 普通状况下, 咱们会给一个类提供本身定义构造方法和本身定义类工厂方法用于建立一个对象。

类工厂方法在继承中的注意点
之后但凡本身定义类工厂方法, 在类工厂方法中建立对象必定要使用self来建立,必定不要使用类名来建立。

类的本质及存储细节

  1. 类的本质是什么?
    答:
    (1)类事实上也是一个对象, 这个对象会在这个类第一次被使用的时候建立
    (2)仅仅要有了类对象, 未来就可以经过类对象来建立实例对象
    (3)实例对象中有一个isa指针, 指向建立本身的类对象
    (4)类对象中保存了当前对象所有的对象方法
    (5)当给一个实例对象发送消息的时候, 会依据实例对象中的isa指针去相应的类对象中查找
    (6)所有类对象的继承关系就是元类对象的继承关系

类的启动过程

  1. 1.load方法
    “load方法调用时间:”
    仅仅要程序启动就会将所有类的代码载入到内存中, 放到代码区
    “调用次数”
    load方法会在当前类被载入到内存的时候调用, 有且仅会调用一次

  2. 2.initialize方法
    “initialize方法调用时间:”
    当当前类第一次被使用的时候就会调用(建立类对象的时候)
    “调用次数”

SEL类型

  1. SEL是什么类型?


    答:
    SEL类型表明着方法的签名,在类对象的方法列表中存储着该签名与方法代码的相应关系

  2. SEL有什么做用?


    答:
    (1)SEL类型的第一个做用, 配合对象/类来检查对象/类中有没有实现某一个方法
    (2)SEL类型的第二个做用, 配合对象/类来调用某一个SEL方法
    (3)配合对象将SEL类型做为方法的形參

  3. 哪一个方法是用来检验对象是否实现了某个方法?


    推断实例是否实现某个对象方法
    (BOOL)respondsToSelector: (SEL)selector
    推断类是否实现某个类方法
    (BOOL)instancesRespondToSelector:(SEL)aSelector;

  4. 哪些方法是用来调用对象中SEL类型相应的方法?
    答:
    让对象执行某个方法

- (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

内存管理

  1. 什么是堆?什么是栈?


    答:
    栈(操做系统):由操做系统本身主动分配释放,存放函数的參数值。局部变量的值等。其操做方式类似于数据结构中的栈(先进后出)。
    堆(操做系统):通常由程序猿分配释放。若程序猿不释放。程序结束时可能由系统回收,分配方式类似于链表。

  2. 什么是内存管理?
    答:
    所谓内存管理, 就是对内存进行管理, 涉及的操做有
    分配内存 : 比方建立一个对象, 会添加内存占用
    清除内存 : 比方销毁一个对象, 能减少内存占用

  3. 内存管理的本质是什么?
    答:
    OC对象存放于堆里面
    非OC对象通常放在栈里面(栈内存会被系统本身主动回收)

MRC内存管理

  1. 什么是引用计数器?


    答:每个OC对象都有本身的引用计数器,它是一个整数,表示有多少人正在用这个对象

  2. 引用计数器的做用?


    答:
    (1)当使用alloc、new或者copy建立一个对象时,对象的引用计数器默认就是1
    (2)当对象的引用计数器为0时,对象占用的内存就会被系统回收
    假设对象的计数器不为0,那么在整个程序执行过程,它占用的内存就不可能被回收(除非整个程序已经退出 )

  3. 怎么操做引用计数器?
    答:
    给对象发送一条retain消息,可以使引用计数器值+1(retain方法返回对象自己)
    给对象发送一条release消息, 可以使引用计数器值-1
    给对象发送retainCount消息, 可以得到当前的引用计数器值
    需要注意的是: release并不表明销毁\回收对象, 仅仅是计数器-1

  4. dealloc 方法的做用?
    答:对象即将被销毁时系统会本身主动给对象发送一条dealloc消息 (所以, 从dealloc方法有没有被调用,就可以推断出对象是否被销毁)

  5. 重写dealloc方法有什么注意点?


    答:重写dealloc方法, [super dealloc]必定要写到所有代码的最后

  6. 内存管理的原则?
    答:
    (1)谁建立谁release :
    假设你经过alloc、new、copy或mutableCopy来建立一个对象。那么你必须调用release或autorelease

(2)谁retain谁release:
仅仅要你调用了retain,就必须调用一次release

(3)总结:
有加就有减,曾经让对象的计数器+1,就必须在最后让对象的计数器-1

setter方法的内存管理
实现set方法内存管理有哪几步?
答:
(1)retain需要使用的对象
(2)release以前的对象
(3)仅仅有传入的对象和以前的不一样才需要release和retain

- (void)setRoom:(Room *)room
{
    // 仅仅有房间不一样才需用release和retain
    if (_room != room) {
    // 0ffe1 != 0ffe1
        // 2.将曾经的房间释放掉 -1
        [_room release];
        // retain不只仅会对引用计数器+1, 并且还会返回当前对象
        _room = [room retain];
    }
}

property修饰符
1.readonly: 仅仅会生成getter方法
readwrite: 既会生成getter也会生成setter, 默认什么都不写就是readwrite

2.getter: 可以给生成的getter方法起一个名称
setter: 可以给生成的setter方法起一个名称

3.retain: 就会本身主动帮咱们生成getter/setter方法内存管理的代码
assign: 不会帮咱们生成set方法内存管理的代码, 仅仅仅仅会生成普通的getter/setter方法, 默认什么都不写就是assign

4.多线程
atomic :性能低(默认)
nonatomic :性能高
在iOS开发中99.99%都是写nonatomic

property修饰符 有拿几点需要注意的问题?
答:
1.一样类型的property修饰符不能同一时候使用
2.不一样类型的property修饰符可以多个结合在一块儿使用, 多个之间用,号隔开
3.iOS开发中仅仅要写上property, 那么就立马写上nonatomic

什么是循环retain?


答:
假设A对用要拥有B对象, 而B相应又要拥有A对象, 此时会造成循环retain
解决循环retain的方法,一边用retain一边用assign

autorelease 本身主动释放池

  1. 什么是本身主动释放池?
    答:
    autorelease是一种支持引用计数的内存管理方式,仅仅要给对象发送一条autorelease消息,会将对象放到一个本身主动释放池中,当本身主动释放池被销毁时。会对池子里面的所有对象作一次release操做

  2. 本身主动释放池的长处是什么?
    答:
    不用再关心对象释放的时间
    不用再关心何时调用release

  3. 简述本身主动释放池的原理?
    答:
    autorelease实际上仅仅是把对release的调用延迟了,对于每个autorelease,系统仅仅是把该 Object放入了当前的autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。

  4. 本身主动释放池有哪些注意事项?


    答:
    (1)在本身主动释放池中建立了对象, 必定要调用autorelease,才会将对象放入本身主动释放池中
    (2)一个程序中可以建立N个本身主动释放池, 并且本身主动释放池还可以嵌套
    (3)不要再本身主动释放池中使用比較消耗内存的对象, 占用内存比較大的对象
    (4)尽可能不要再本身主动释放池中使用循环, 特别是循环的次数很是多, 并且还很是占用内存
    (5)千万不要写屡次autorelease
    (6)一个alloc/new相应一个autorelease或者release

  5. 本身主动释放池是以什么形式存储的?
    答: 假设存在多个本身主动释放池的时候, 本身主动释放池是以 “栈” 的形式存储在堆区
    栈的特色: 先进后出

ARC内存管理

  1. 问题1:ARC的原理是什么?
    答:当ARC开启时,编译器将本身主动在代码合适的地方插入retain, release和autorelease,而做为程序猿,全然不需要操心编译器会作错(除非开发人员本身错用ARC了)。

  2. ARC有什么长处?


    答:
    1.全然消除了手动管理内存的烦琐, 让程序猿更加专一于app的业务
    2.基本上可以避免内存泄露
    3.有时还能更加高速,因为编译器还可以执行某些优化

  3. ARC的原则是什么?什么是强指针?什么是弱指针?


    答:仅仅要另外一个强指针变量指向对象。对象就会保持在内存中
    (1)强指针
    默认所有指针变量都是强指针
    被__strong修饰的指针
    (2)弱指针
    被__weak修饰的指针

  4. ARC下@property修饰符有哪些?


    答:
    strong : 用于OC对象, 至关于MRC中的retain
    weak : 用于OC对象, 至关于MRC中的assign
    assign : 用于基本数据类型, 跟MRC中的assign同样

  5. ARC中是怎么对对象进行内存管理的?


    答:
    (1)ARC下单对象内存管理
    (2)ARC下,所有的指针都是强指针
    (3)ARC, A对象想拥有B对象, 那么就需要用一个强指针指向B对象
    (4)A对象不用B对象了, 什么都不需要作, 编译器会本身主动帮咱们作

  6. ARC怎么解决循环引用问题?
    答:
    ARC和MRC同样, 假设A拥有B, B也拥有A, 那么必须一方使用弱指针
    也就是说 一端用strong ,一端用weak

Category 分类

  1. 书写Category的格式?
    答:
    // 分类的声明
    @interface ClassName (CategoryName)
    NewMethod; //在类别中加入方法
    //不一样意在类别中加入变量
    @end

ClassName: 需要给哪一个类扩充方法
CategoryName: 分类的名称
NewMethod: 扩充的方法

// 分类的实现
@implementation ClassName(CategoryName)

NewMethod
… …
@end

ClassName: 需要给哪一个类扩充方法
CategoryName: 分类的名称
NewMethod: 扩充的方法

  1. Category的做用?
    答:
    (1)在不改变原来的类内容的基础上,为类添加一些方法。
    (2)一个庞大的类可以分模块开发,由多我的来编写,更有利于团队合做

  2. 分类,原来类或者父类中的方法调用的顺序?


    答:先调用分类中的方法(最后參与编译的分类优先),再调用原来类中的方法,最后掉用父类中的方法

Extension 匿名扩展

  1. 什么是类扩展?


    答:延展类别又称为扩展(Extension),Extension是Category的一个特例

  2. 类扩展格式?
    答:
    类扩展书写格式
    @interface 类名 ()
    @end

  3. 类扩展的做用是什么?
    答:写在.m文件里,可以为某个类扩充一些私有的成员变量和方法

Block

  1. 什么是Block?
    答:Block是iOS中一种比較特殊的数据类型,用来保存某一段代码

  2. Block的做用?
    答:Block用来保存某一段代码, 可以在恰当的时间再取出来调用
    功能类似于函数和方法

  3. Block的格式?
    答:Block的格式:
    返回值类型 (^block变量名)(形參列表) = ^(形參列表) {
    };

协议

  1. 什么是协议?
    答:其余语言有接口的概念,接口就是一堆方法的声明没有实现.
    OC中没有接口的概念,OC中的接口就是协议.
    协议Protocol是由一系列的方法声明组成的

  2. 书写协议的格式?
    答:
    格式:
    @protocol 协议名称
    // 方法声明列表
    @end

  3. 一个类怎么遵循协议?


    答:类遵照协议格式:
    @interface 类名 : 父类 <协议名称1, 协议名称2,…>
    @end

注意:
(1)一个类可以遵照1个或多个协议
(2)不论什么类仅仅要遵照了Protocol,就至关于拥有了Protocol的所有方法声明

4.协议和继承有什么差异?


答:
(1)继承以后默认就有实现, 而protocol仅仅有声明没有实现
(2)一样类型的类可以使用继承, 但是不一样类型的类仅仅能使用protocol
(3)protocol可以用于存储方法的声明, 可以将多个类中共同的方法抽取出来, 之后让这些类遵照协议就能够

  1. 什么是基协议?
    答:基协议:是基协议,是最根本最主要的协议。其中声明了很是多最主要的方法。
    注意:建议每个新的协议都要遵照NSObject协议

6.协议有哪些注意事项?
答:
(1)协议仅仅能声明方法, 不能声明属性
(2)父类遵照了某个协议, 那么子类也会本身主动遵照这个协议
(3)在OC中一个类可以遵照1个或多个协议
注意: OC中的类仅仅能有一个父类, 也就是说OC仅仅有单继承
(4)OC中的协议又可以遵照其余协议, 仅仅要一个协议遵照了其余协议, 那么这个协议中就会本身主动包括其余协议的声明

7.协议中控制方法的可否实现的关键字是什么?各有什么做用?


(1)注意: 假设没有使用不论什么关键字修饰协议中的方法, 那么该方法默认就是required的
(2)注意:@required和@optional仅仅使用程序猿之间交流, 并不能严格的控制某一个遵照该协议的类必需要实现该方法, 因为即使不是实现也不会报错, 仅仅会报一个警告
(3)
@required
假设协议中的方法是@required的, 要求遵照协议的类实现@required所修饰的方法,假设没有实现该方法, 那么会报一个警告
(4)
@optional
假设协议中的方法是@optional的, 遵照协议的类可选择实现@optional所修饰的方法,假设没有实现该方法, 那么不会报警告

类型限定

  1. 什么是类型限定?


    答:类型限定就是限定一个类必须遵照某个协议

  2. 类型限定的格式?


    答:数据类型<协议名称> 变量名
    @property (nonatomic, strong) Wife *wife;

  3. 类型限定有什么注意点?
    答:
    (1)类型限定是写在数据类型的右边的
    (2)尽管在接受某一个对象的时候, 对这个对象进行了类型限定(限定它必须实现某个协议),
    但是并不意味着这个对象就真正的实现了该方法. 因此每次在调用对象的协议方法时应该进行一次验证

if ([self.wife respondsToSelector:@selector(cooking)]) {
    [self.wife cooking];
}

代理设计模式

  1. 代理模式的应用场景?
    (1)当A对象想监听B对象的一些变化时, 可以使用代理设计模式
    (2)当B对象发生一些事情, 想通知A对象的时候, 可以使用代理设计模式
    (3)当对象A没法处理某些行为的时候,想让对象B帮忙处理(让对象B成为对象A的代理对象)

  2. 用什么类型来接收遵照协议的代理对象?
    答:使用id类型接收代理对象

  3. 简述一下协议的编写规范?
    答:
    (1)普通状况下, 当前协议属于谁, 咱们就将协议定义到谁的头文件里
    (2)协议的名称通常以它属于的那个类的类名开头, 后面跟上protocol或者delegate
    (3)协议中的方法名称通常以协议的名称protocol以前的做为开头
    (4)普通状况下协议中的方法会将触发该协议的对象传递出去

5.普通状况下一个类中的代理属于的名称叫作 delegate

6.当某一个类要成为另一个类的代理的时候,
普通状况下在.h中用@protocol 协议名称;告诉当前类 这是一个协议.
在.m中用#import真正的导入一个协议的声明

Foundation

  1. 什么是框架?
    答:
    众多功能\API的集合.
    框架是由不少类、方法、函数、文档依照必定的逻辑组织起来的集合,以便使研发程序变得更easy,在OS X下的Mac操做系统中大约有80个框架为所有程序开发奠基基础的框架称为Foundation 框架

  2. Foundation 框架有什么做用?


    答:
    1.Foundation框架是Mac\iOS中其余框架的基础
    2.Foundation框架包括了很是多开发中常用的数据类型:结构体,枚举, 类

  3. 什么是NSString?
    答:一个NSString对象就表明一个字符串(文字内容)
    通常称NSString为字符串类

  4. 怎样建立NSString对象?有几种方法建立一个NSString字符串?


    答:
    (1)经过@”“直接建立
    假设经过@”“建立字符串, 那么会将字符串放到常量区中
    假设是字符串常量, 那么仅仅要内容一样 , 不会反复建立

NSString *str1 = @"james";

(2)经过alloc或者类工厂方法建立
假设是经过alloc或者类工厂方法建立, 那么会将字符串放到堆区中

NSString *str2 = [[NSString alloc] initWithString:@"james"];
    NSString *str3 = [NSString stringWithFormat:@"jack"];
  1. 怎样将字符串写入到文件里?
NSString *str = @"iOS";
NSString *path2 = @"/Users/james/Desktop/abc.txt";
BOOL flag = [str writeToFile:path2 atomically:YES encoding:NSUTF8StringEncoding error:nil];
NSLog(@"flag = %i", flag);

6.什么是URL?
答:
(1)URL的全称是Uniform Resource Locator(统一资源定位符)
(2)URL是互联网上标准资源的地址
(3)互联网上的每个资源都有一个惟一的URL,它包括的信息指出资源的位置
(4)依据一个URL就能找到惟一的一个资源

7.写URL格式?
答: URL = 协议头://主机地址/路径

8.怎样建立URL
答:
(1)经过alloc 或者类工厂方法建立

NSURL *url = [NSURL URLWithString:@"file:///Users/james/Desktop/str.txt"];
NSURL *url = [[NSURL alloc] initWithString:@"file:///Users/james/Desktop/str.txt"];

(2)经过文件路径建立(默认就是file协议的)

NSURL *url = [NSURL fileURLWithPath:@"/Users/james/Desktop/str.txt"];

9.怎样获取本地路径的信息?获取本地路径信息的方法有什么注意点?
答:获取本地路径信息–fileURLWithPath
方法一:
(1)字符串保存路径

NSString *path = @"file://192.168.13.10/Users/james/Desktop/note/ja.txt";
    NSLog(@"url编码前: %@", path);

(2)将路径中中文转换为UTF-8编码格式

path = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"url编码后: %@", path);

方法二:
(1)字符串保存路径,假设訪问本机的文件, 可以省略主机地址
NSString *path = @”file:///Users/james/Desktop/note/ja.txt”;
NSLog(@”url编码前: %@”, path);

(2)将路径中中文转换为UTF-8编码格式
path = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@”url编码后: %@”, path);
NSURL *url = [NSURL URLWithString:path];

10.获取本地路径的信息

NSURL *url = [NSURL fileURLWithPath:@"/Users/james/Desktop/note/ja.txt"];
NSError *error = nil;
NSString *str = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
if (error == nil) {
NSLog(@"str = %@", str);
    }else{
        NSLog(@"error = %@", [error localizedDescription]);
    }

注意点:
URLWithString: 方法不支持中文,因此没法成功建立URL,必须先对路径字符串进行编码

fileURLWithPath: 方法支持中文,并且省略协议头,但是仅仅能获取本地方法

11.怎样获取网络路径的信息?
答:
获取网络路径的信息–URLWithString

NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
NSString *str = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSLog(@"str = %@", str);

12.怎样将信息写入到指定文件?
答:
方法一:

NSString *str = @"james";
NSString *path = @"file:///Users/james/Desktop/未命名目录/abc.txt";
path = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *url = [NSURL URLWithString:path];
 [str writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:nil];

方法二:

NSString *str = @"james";
NSString *path = @"/Users/james/Desktop/未命名目录/abc.txt";
NSURL *url = [NSURL fileURLWithPath:path];
[str writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:nil];

总结:
1.假设屡次往同一个文件里写入内容,那么后一次的会覆盖前一次的 \
2.方法名中没有file,路径中要加入上file协议头,假设方法名中有file,路径中就不需要file协议头

NSString

  1. 怎样比較两个字符串的”内容”是否一样?
    答:
    BOOL flag = [str1 isEqualToString:str2];
    NSLog(@”flag = %i”, flag);

  2. 怎样比較两个字符串的”地址”是否一样?
    flag = (str1 == str2);
    NSLog(@”flag = %i”, flag);

  3. 怎样比較字符串的大小?
    答:用法compare:
    NSOrderedAscending 前面的小于后面的
    NSOrderedSame, 两个字符串相等
    NSOrderedDescending 前面的大于后面的

  4. 怎样忽略大写和小写进行比較?
    [str1 caseInsensitiveCompare:str2];

  5. 怎样推断字符串是否以什么结尾的?

    本质是什么?
    答:
    本质就是从字符串的最后一个字符開始匹配, 仅仅要不匹配就返回NO

if ([str hasSuffix:@".gif"]) {
    NSLog(@"动态图片");
}else{
    NSLog(@"不是动态图片");
}

6.怎样获取指定范围内的字符串?
答:
(1)动态获取截取的起始位置
NSUInteger location = [str rangeOfString:@”>”].location + 1;
(2)动态获取截取的长度

NSUInteger length = [str rangeOfString:@"</"].location - location;
NSRange range = NSMakeRange(location, length);
NSString *newStr = [str substringWithRange:range];
NSLog(@"str = %@", str);
NSLog(@"newStr = %@", newStr);

7.怎样替换字符串中的部分字符?
答:
需求: 将&符号替换为/

NSString *str = @"http:&&www.weibo.iosjames.com&img&james.gif";
..OccurrencesOfString: 要替换谁
// withString: 用谁替换
NSString *newStr = [str stringByReplacingOccurrencesOfString:@"&" withString:@"/"];
NSLog(@"newStr = %@", newStr);

8.怎样对字符串首位进行处理?
答:

NSString *str = @"HTTP://www.baidu.com/img/james.GIF";
NSCharacterSet *set = [NSCharacterSet uppercaseLetterCharacterSet];
NSString *newStr = [str stringByTrimmingCharactersInSet:set];
NSLog(@"newStr = |%@|", newStr);

9.怎样给文件路径加入一个目录?


答:
本质就是在字符串的末尾加上一个/ 和指定的内容
注意: 假设路径后面已经有了/, 那么就不会加入了
假设路径后面有多个/, 那么会本身主动删除多余的/, 仅仅保留一个

NSString *newStr = [str stringByAppendingPathComponent:@"james"];
NSLog(@"%@", newStr);

10.怎样获取路径中文件的扩展名?


答:
本质就是从字符串的末尾開始查找., 截取第一个.后面的内容

NSString *newStr = [str pathExtension];
NSLog(@"%@", newStr);

11.怎样删除路径中文件的扩展名?
答:
本质就是从字符串的末尾開始查找.,删除第一个.和.后面的内容

NSString *newStr = [str stringByDeletingPathExtension];
NSLog(@"%@", newStr);

12.怎样给文件路径加入一个扩展名?


答:
本质就是在字符串的末尾加上一个.和指定的内容

NSString *newStr = [str stringByAppendingPathExtension:@"jpg"];
NSLog(@"%@", newStr);

13.怎样将将字符串转换为大写?
答:

NSString *newStr = [str uppercaseString];
NSLog(@"%@", newStr);

14.怎样将字符串转换为小写?


答:

NSString *newStr2 = [newStr lowercaseString];
NSLog(@"%@", newStr2);

15.怎样将字符串的首字符转换为大写
答:

NSString *newStr = [str capitalizedString];
NSLog(@"%@", newStr);

NSMutalbleString

  1. NSMutableString和NSString的差异?
    答:
    (1)NSString是不可变的, 里面的文字内容是不能进行改动的
    (2)NSMutableString是可变的, 里面的文字内容可以随时更改
    (3)NSMutableString能使用NSString的所有方法

  2. 什么是可变字符串?什么是不可变字符串?
    答:
    不可变字符串:指的是字符串在内存中占用的存储空间固定,并且存储的内容不能发生变化
    可变字符串:指的是字符串在内存中占用的存储空间可以不固定,并且存储的内容可以被改动

  3. 在字符串后面加入一段字符串?
    答:

[strM appendString:@"/image"];
NSLog(@"strM = %@", strM);

4.怎样删除字符串中的字符?
技巧: 在开发中, 咱们常常利用rangeOfString和deleteCharactersInRange方法配合起来删除指定的字符串

NSRange range = [strM rangeOfString:@"xx"];
[strM deleteCharactersInRange:range];
NSLog(@"strM = %@", strM);

5.怎样在某个字符前面插入love这个单词?
答:
insertString : 需要插入的字符串
atIndex: 从哪里開始插入

NSRange range = [strM rangeOfString:@"xx"];
[strM insertString:@"love" atIndex:range.location];
NSLog(@"strM = %@", strM);

NSArray

  1. 什么是NSArray?


    答:NSArray是OC中的数组类,开发中建议尽可能使用NSArray替代C语言中的数组

  2. NSArray有哪些使用注意?
    答:
    (1)仅仅能存放随意OC对象, 并且是有顺序的
    (2)不能存储非OC对象, 比方int\float\double\char\enum\struct等
    (3)它是不可变的,一旦初始化完成后,它里面的内容就永远是固定的, 不能删除里面的元素, 也不能再往里面加入元素
    (4)NSArray使用NSLog()打印,输出的是小括号的格式。


    (5)NSArray中不能存储nil,因为NSArray以为nil是数组的结束(nil是数组元素结束的标记)。nil就是0。0也是基本数据类型,不能存放到NSArray中。

  3. NSArray有哪些常常用法?
    答:

- (NSUInteger)count; 获取集合元素个数 - (id)objectAtIndex:(NSUInteger)index; 得到index位置的元素 
- (BOOL)containsObject:(id)anObject; 是否包括某一个元素 
- (id)lastObject; 返回最后一个元素 
- (id)firstObject; 返回最后一个元素 
- (NSUInteger)indexOfObject:(id)anObject; 查找anObject元素在数组中的位置(假设找不到,返回-1) 
- (NSUInteger)indexOfObject:(id)anObject inRange:(NSRange)range; 在range范围内查找anObject元素在数组中的位置

4.书写NSArray简写形式?
答:

NSArray *arr = [NSArray arrayWithObjects:@"ldda", @"james", @"jjj", nil];
NSArray *arr = @[@"james", @"jasc", @"jjj"];

获取数组元素的简写

NSLog(@"%@", [arr objectAtIndex:0]);
NSLog(@"%@", arr[0]);

5.怎样使用加强for循环,遍历NSArray数组?
答:
逐个取出arr中的元素, 将取出的元素赋值给obj
注意: obj的类型可以依据数组中元素的类型来写, 不必定要写NSObject
for (NSString *obj in arr) {
NSLog(@”obj = %@”, obj);
}

6.怎样使用OC数组的迭代器来遍历数组?


答:
每取出一个元素就会调用一次block
每次调用block都会将当前取出的元素和元素相应的索引传递给咱们
obj就是当前取出的元素, idx就是当前元素相应的索引
stop用于控制何时中止遍历

[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if (idx == 1) {
        *stop = YES;
    }
    NSLog(@"obj = %@, idx = %lu", obj, idx);
}];

7.怎样对数据进行排序?NSArray *arr = @[@10, @20, @5, @7, @15];
NSLog(@”排序前: %@”, arr);意:**
想使用compare方法对数组中的元素进行排序, 那么数组中的元素必须是Foundation框架中的对象, 也就是说不能是本身定义对象

NSArray *newArr = [arr sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"排序后: %@", newArr);

8.怎样将数组写入文件里?
答:

NSArray *arr = @[@"eee", @"aaa", @"jjj"];
BOOL flag = [arr writeToFile:@"/Users/james/Desktop/abc.plist" atomically:YES];
NSLog(@"flag = %i", flag);

9.将数组写入文件里,有什么注意事项?
答:
注意(1):
假设将一个数组写入到文件里以后, 本质是写入了一个XML文件
在iOS开发中普通状况下咱们会将XML文件的扩展名保存为plist

注意(2)
writeToFile仅仅能写入数组中保存的元素都是Foundation框架中的类建立的对象, 假设保存的是本身定义对象那么不能写入

10.怎样从文件里读取数据到NSArray中?
答:
从文件里读取一个数组,此方法在字典转模型中,经常用到

NSArray *newArray = [NSArray arrayWithContentsOfFile:@"/Users/james/Desktop/abc.plist"];
NSLog(@"%@", newArray);

NSMutableArray

1.什么是可变数组?

和NSArray有什么差异?
答:
(1)NSMutableArray是NSArray的子类
(2)NSArray是不可变的,一旦初始化完成后,它里面的内容就永远是固定的, 不能删除里面的元素, 也不能再往里面加入元素
(3)NSMutableArray是可变的,随时可以往里面加入\更改\删除元素

2.怎样建立一个空的数组?建立可变数组有什么注意点?

NSMutableArray *arrM = [NSMutableArray array];
NSMutableArray *arrM = [[NSMutableArray alloc] init];

注意:
不能经过@[]来建立一个可变数组, 因为@[]建立出来的是一个不可变的数组

3.怎样给可变数组添加内容?


答:
方法一:

[arrM addObject:@"james"];

方法二:
将指定数组中的元素都取出来, 放到arrM中 \
并不是将整个数组做为一个元素加入到arrM中

[arrM addObjectsFromArray:@[@"james", @"jjj"]];

注意:
下面是将整个数组做为一个元素加入

[arrM addObject:@[@"ss", @"jjj"]];
NSLog(@"%@", arrM);

4.怎样给可变数组插入内容?
答:

[arrM insertObject:@"xcq" atIndex:1];
NSRange range = NSMakeRange(2, 2);
NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:range];

插入一组数据, 指定数组需要插入的位置, 和插入多少个
[arrM insertObjects:@[@”A”, @”B”] atIndexes:set];

5.怎样删除可变数组中的内容?
答:

删除
[arrM removeObjectAtIndex:0]
删除数组中最后一个元素
[arrM removeLastObject];
删除index位置的元素
[arrM removeObject:@"A"];

6.怎样替换可变数组中的内容?


答:

[arrM replaceObjectAtIndex:1 withObject:@"M"];

//简写:

arrM[0] = @"ZS";
NSLog(@"%@", arrM);

7.怎样获取可变数组中的内容?


答:

NSLog(@"%@", [arrM objectAtIndex:0]);

NSDictionary

  1. 什么是字典?
    答:OC中的NSDictionary:依据key找到value,字典中存储的东西都是键值对

  2. 怎样建立字典?
    答:

方法一:

NSDictionary *dict = [NSDictionary dictionaryWithObject:@"james" forKey:@"name"];
NSString *name = [dict objectForKey:@"name"];
NSLog(@"name = %@", name);

方法二:
注意: key和value 是一一相应

NSDictionary *dict = [NSDictionary dictionaryWithObjects:@[@"james", @"22", @"1.75"] forKeys:@[@"name", @"age", @"height"]];
NSLog(@"%@ %@ %@", [dict objectForKey:@"name"], [dict objectForKey:@"age"], [dict objectForKey:@"height"]);

方法三:简写:

NSDictionary *dict = @{key:value};
NSDictionary *dict = @{@"name": @"james"};
NSLog(@"%@", dict[@"name"]);
NSDictionary *dict = @{@"name":@"james", @"age":@"30", @"height":@"1.75"};
NSLog(@"%@ %@ %@", dict[@"name"], dict[@"age"], dict[@"height"]);

3.怎样对字典进行遍历?
答:

NSDictionary *dict = @{@"name":@"james", @"age":@"22", @"height":@"1.75"};

//获取字典中key和value的个数, 在字典中key称之为键, value称之为值

NSLog(@"count = %lu", [dict count]);

方法一:老式for循环写法

for (int i = 0; i < dict.count; ++i) {
    // 获取字典中所有的key
    NSArray *keys = [dict allKeys];
    // 取出当前位置相应的key
    // NSLog(@"%@", keys[i]);
    NSString *key = keys[i];
    NSString *value = dict[key];
    NSLog(@"key = %@, value = %@", key, value);
}

方法二:加强for循环写法
怎样经过forin遍历字典, 会将所有的key赋值给前面的obj

for (NSString *key in dict) {
NSLog(@"%@", key);
NSString *value = dict[key];
NSLog(@"key = %@, value = %@", key, value);

}

方法三:OC字典的迭代器来遍历

[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
    NSLog(@"key = %@, value = %@", key, obj);
}];

4.怎样对字典文件进行读写?


答:
(1)将字典数据写入文件里

NSDictionary *dict = @{@"name":@"james", @"age":@"22", @"height":@"1.75"};

[dict writeToFile:@"/Users/james/Desktop/info.plist" atomically:YES];

(2)从文件里读取字典数据
注意: 字典和数组不一样, 字典中保存的数据是无序的

NSDictionary *newDict = [NSDictionary dictionaryWithContentsOfFile:@"/Users/james/Desktop/info.plist"];
NSLog(@"%@", newDict);
NSArray *arr = @[@10, @20, @30, @5];
[arr writeToFile:@"/Users/james/Desktop/abc.plist" atomically:YES];

NSMutableDictionary

  1. 怎样建立一个空的可变字典?
    答:
    NSMutableDictionary *dictM = [NSMutableDictionary dictionary];

  2. 怎样给可变字典加入键值对?
    答:

[dictM setObject:@"lnj" forKey:@"name"];

简写:

dictM[@"name"] = @"james";

会将传入字典中所有的键值对取出来加入到dictM中

[dictM setValuesForKeysWithDictionary:@{@"age":@"30", @"height":@"1.75"}];

3.怎样删除可变字典键值对?
答:

[dictM removeObjectForKey:@"name"];
[dictM removeObjectsForKeys:@[@"age", @"height"]];

4.怎样改动可变字典中的键值对?
答:利用setObject方法给同名的key赋值, 那么新值会覆盖旧值

[dictM setObject:@"88" forKey:@"age"];

简写:

dictM[@"age"] = @"88";

5.使用可变字典有什么注意事项?


答:
(1)不能使用@{}来建立一个可变的字典
NSMutableDictionary *dictM = @{@”name”:@”james”};//编译就会报错
[dictM setObject:@”30” forKey:@”age”];

(2)
假设是不可变字典, 那么key不能一样
假设是不可变字典出现了同名的key, 那么后面的key相应的值不会被保存
假设是在可变数组中, 后面的会覆盖前面的

NSDictionary *dict = @{@"name":@"lkl", @"name":@"lll"};
NSLog(@"dict = %@", dict);
NSMutableDictionary *dictM = [NSMutableDictionary dictionaryWithObjects:@[@"lkl", @"lll"] forKeys:@[@"name", @"name"]];
NSLog(@"dict = %@", dictM);

6.NSArray和NSDictionary的差异?
答:
NSArray是有序的,NSDictionary是无序的
NSArray是经过下标訪问元素,NSDictionary是经过key訪问元素

NSNumber

1.NSNumber的应用场景?
答:
NSNumber可以将基本数据类型包装成对象,这样就可以间接将基本数据类型存进NSArray\NSDictionary中

2.怎样将基本数据类型转换为对象类型?
答:

int age = 10;
double number= 5.1;
int value =  6;
NSNumber *ageN = [NSNumber numberWithInt:age];
NSNumber *numberN = [NSNumber numberWithDouble:number];
NSNumber *valueN = [NSNumber numberWithInt:value];
NSArray *arr = @[ageN, numberN, valueN];
NSLog(@"arr = %@", arr);

3.怎样将对象类型转换为基本数据类型?
答:

int temp = [ageN intValue];
double temp = [numberN doubleValue];

4.怎样将基本数据类型转换对象类型简写?有什么注意点?
答:
注意: 假设传入的是变量那么必须在@后面写上(), 假设传入的常量, 那么@后面的()可以省略

NSNumber *temp = @(number);
NSNumber *temp  =@10.10;
NSLog(@"%@", temp);

NSValue

1.NSValue的应用场景?
答:
(1)NSNumber是NSValue的子类, 但NSNumber仅仅能包装数字类型
(2)NSValue可以包装随意值
所以, 可以用NSValue将结构体包装后,加入NSArray\NSDictionary中

2.怎样利用NSValue包装常用的结构体?
答:

CGPoint point = NSMakePoint(10, 20);
NSValue *value = [NSValue valueWithPoint:point];
NSArray *arr = @[value];
NSLog(@"%@", arr);

3.怎样利用NSValue包装本身定义的结构体?


答:

typedef struct{
    int age;
    char *name;
    double height;
}Person;
Person p = {30, "lld", 1.75};

NSDate

1.NSDate的应用场景?


答:NSDate可以用来表示时间, 可以进行一些常见的日期\时间处理
[NSDate date]返回的就是当前0时区的时间

2.怎样获取当前时区的时间?


答:
(1) date方法建立的时间对象, 对象中就保存了当前的时间

NSDate *now = [NSDate date];

(2)获取当前所处的时区

NSTimeZone *zone = [NSTimeZone systemTimeZone];

(3)获取当前时区和指定时区时间的时间差

NSInteger seconds = [zone secondsFromGMTForDate:now];
//    NSLog(@"seconds = %lu", seconds);

(4)计算出当前时区的时间

NSDate *newDate = [now dateByAddingTimeInterval:seconds];
NSLog(@"newDate = %@", newDate);

3.怎样格式化时间?
答:
NSDate 转 NSString
(1)建立时间

NSDate *now = [NSDate date];

(2)建立时间格式化

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

(3)指定格式

formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";

(4)格式化时间

NSString *str = [formatter stringFromDate:now];
NSLog(@"%@", str);

NSString 转 NSDate
(1)获取时间

NSString *str = @"2015-08-20 07:05:26 +0000";

2.建立时间格式化

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

注意:
假设是从NSString格式化为NSDate, 那么dateFormat的格式, 必须和字符串中的时间格式一致, 不然可能转换失败
(3)指定格式

formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss Z";

4.格式化日期

NSDate *date = [formatter dateFromString:str];
NSLog(@"%@", date);

NSCalendar

1.怎样获取当前时间的年月日时分秒?


答:
(1)获取当前时间

NSDate *now = [NSDate date];
NSLog(@"now = %@", now);

得到NSCalendar 日历对象

NSCalendar *calendar1 = [NSCalendar currentCalendar];
// 利用日历类从当前时间对象中获取 年月日时分秒(单独获取出来)
// components: 參数的含义是, 问你需要获取什么?
// 普通状况下假设一个方法接收一个參数, 这个參数是是一个枚举 , 那么可以经过|符号, 链接多个枚举值
NSCalendarUnit type = NSCalendarUnitYear |
NSCalendarUnitMonth |
NSCalendarUnitDay |
NSCalendarUnitHour |
NSCalendarUnitMinute |
NSCalendarUnitSecond;
NSDateComponents *cmps = [calendar1 components:type fromDate:now];
NSLog(@"year = %ld", cmps.year);
NSLog(@"month = %ld", cmps.month);
NSLog(@"day = %ld", cmps.day);
NSLog(@"hour = %ld", cmps.hour);
NSLog(@"minute = %ld", cmps.minute);
NSLog(@"second = %ld", cmps.second);

2.怎样获取当前时间和指定时间的时间差?


答:

1.过去的一个时间
NSString *str = @"2015-06-29 07:05:26 +0000";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss Z";
NSDate *date = [formatter dateFromString:str];
2.当前的时间
NSDate *now = [NSDate date];

NSLog(@"date = %@", date);
NSLog(@"now = %@", now);

3.比較两个时间
NSCalendar *calendar = [NSCalendar currentCalendar];
NSCalendarUnit type = NSCalendarUnitYear |
NSCalendarUnitMonth |
NSCalendarUnitDay |
NSCalendarUnitHour |
NSCalendarUnitMinute |
NSCalendarUnitSecond;
NSDateComponents *cmps = [calendar components:type fromDate:date toDate:now options:0];
NSLog(@"%ld年%ld月%ld日%ld小时%ld分钟%ld秒钟", cmps.year, cmps.month, cmps.day, cmps.hour, cmps.minute, cmps.second);

NSFileManager

1.什么是NSFileManager?

怎样获取NSFileManager 对象?
答:
NSFileManager是用来管理文件系统的
它可以用来进行常见的文件\目录操做

NSFileManager *manager = [NSFileManager defaultManager];

2.怎样推断一个文件或者目录是否存在?
答:

BOOL flag = [manager fileExistsAtPath:@"/Users/james/Desktop/video/01-NSArray.text"];
NSLog(@"flag = %i", flag);

3.怎样获取文件或目录的属性?
答:

NSDictionary *info = [manager attributesOfItemAtPath:@"/Users/james/Desktop/video/acn.mp4" error:nil];
NSLog(@"info = %@", info);

4.怎样获取目录中所有的文件?


答:
注意:

NSArray *res = [manager contentsOfDirectoryAtPath:@"/Users/xiaomage/Desktop/video" error:nil];
NSLog(@"res = %@", res);

获取当前目录下所有的文件, 能获取子目录下面的文件

NSArray *res = [manager subpathsAtPath:@"/Users/james/Desktop/video"];
NSArray *res = [manager subpathsOfDirectoryAtPath:@"/Users/james/Desktop/video" error:nil];
NSLog(@"res = %@", res);

5.怎样建立目录?


答:
createDirectoryAtPath: 告诉系统目录需要建立到什么位置
withIntermediateDirectories: 假设指定的文件里有一些目录不存在, 是否本身主动建立不存在的目录
attributes: 指定建立出来的目录的属性
error: 是否建立成功, 假设失败会给传入的參数赋值
注意: 该方法仅仅能用于建立目录, 不能用于建立文件

BOOL flag = [manager createDirectoryAtPath:@"/Users/james/Desktop/abc/llq" withIntermediateDirectories:YES attributes:nil error:nil];
NSLog(@"%i", flag);

6.怎样建立文件?
createFileAtPath: 指定文件建立出来的位置
contents : 文件里的内容
attributes: 建立出来的文件的属性
NSData : 二进制数据
注意: 该方法仅仅能用于建立文件, 不能用于建立目录

Copy

1.使用copy功能的前提是什么?


答:
copy : 需要遵照NSCopying协议,实现copyWithZone:方法
使用mutableCopy的前提
需要遵照NSMutableCopying协议,实现mutableCopyWithZone:方法

2.怎样使用copy功能?


答:
一个对象可以调用copy或mutableCopy方法来建立一个副本对象
copy : 建立的是不可变副本(如NSString、NSArray、NSDictionary)
mutableCopy :建立的是可变副本(如NSMutableString、NSMutableArray、NSMutableDictionary)

3.copy基本原则?
答:
改动源对象的属性和行为。不会影响副本对象
改动副本对象的属性和行为,不会影响源对象

4.为何经过不可变对象调用了copy方法, 不会生成一个新的对象?
答:
因为原来的对象是不能改动的, 拷贝出来的对象也是不能改动的
既然两个都不能改动, 因此永远不能影响到另一个对象, 那么已经符合需求
因此: OC为了对内存进行优化, 就不会生成一个新的对象

copy内存管理

1.浅复制(浅拷贝。指针拷贝,shallow copy)
源对象和副本对象是同一个对象
源对象(副本对象)引用计数器+1,至关于作一次retain操做
本质是:没有产生新的对象

2.深复制(深拷贝,内容拷贝,deep copy)
源对象和副本对象是不一样的两个对象
源对象引用计数器不变,副本对象计数器为1(因为是新产生的)
本质是:产生了新的对象

copy和Property

1.@property中的copy的做用是什么?
答:
(1)防止外界改动内部的数据
(2)可以使用copy保存block, 这样可以保住block中使用的外界对象的命
block默认存储在栈中, 栈中的block訪问到了外界的对象, 不会对对象进行retain

2.@property内存管理原则?
答:
MRC
1> copy : 仅仅用于NSString\block
2> retain : 除NSString\block之外的OC对象
3> assign :基本数据类型、枚举、结构体(非OC对象),当2个对象相互引用,一端用retain,一端用assign

ARC
1> copy : 仅仅用于NSString\block
2> strong : 除NSString\block之外的OC对象
3> weak : 当2个对象相互引用,一端用strong,一端用weak
4> assgin : 基本数据类型、枚举、结构体(非OC对象)

3.怎样解决block中的循环引用?


答:假设对象中的block又用到了对象本身, 那么为了不内存泄露, 应该将对象修饰为__block

__block Person *p = [[Person alloc] init]; // 1
p.name = @"james";
NSLog(@"retainCount = %lu", [p retainCount]);
p.pBlock = ^{
    NSLog(@"name = %@", p.name); // 2
};
NSLog(@"retainCount = %lu", [p retainCount]);
p.pBlock();

本身定义类实现Copy

1.本身定义类怎样实现copy操做?
答:
(1)之后想让本身定义的对象可以被copy仅仅需要遵照NSCopying协议
(2)实现协议中的- (id)copyWithZone:(NSZone *)zone
(3)在- (id)copyWithZone:(NSZone *)zone方法中建立一个副本对象, 而后将当前对象的值赋值给副本对象就能够

- (id)copyWithZone:(NSZone *)zone
{
    // 1.建立一个新的对象
    Person *p = [[[self class] allocWithZone:zone] init];
    // 2.设置当前对象的内容给新的对象
    p.age = _age;
    p.name = _name;
    // 3.返回新的对象
    return p;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
    // 1.建立一个新的对象
    Person *p = [[[self class] allocWithZone:zone] init];
    // 2.设置当前对象的内容给新的对象
    p.age = _age;
    p.name = _name;
    // 3.返回新的对象
    return p;
}

单例ARC和MRC写法

1.什么是单例模式?
答:类的对象成为系统中惟一的实例,提供一个訪问点,供客户类 共享资源
单例就是无论怎么建立都仅仅能有一个实例对象

2.什么状况下使用单例?
答:
(1)类仅仅能有一个实例,并且必须从一个为人熟知的訪问点对其进行訪问,比方工厂方法。


(2)这个惟一的实例仅仅能经过子类化进行扩展,并且扩展的对象不会破坏client代码。

3.建立单例对象的方法通常以什么开头?


答:
(1)普通状况下建立一个单利对象都有一个与之相应的类方法
(2)普通状况下用于建立单利对象的方法名称都以share开头, 或者以default开头
单例在多线程的应用?
答:多线程中的单例

+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    // 下面代码在多线程中也能保证仅仅执行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[super allocWithZone:zone] init];
    });
    return _instance;
}

这里写图片描写叙述

相关文章
相关标签/搜索