IOS知识基础篇

category 和 extension 的区别

分类有名字,类扩展没有分类名字,是一种特殊的分类

分类只能扩展方法(属性仅仅是声明,并没真正实现),类扩展可以扩展属性、成员变量和方法

categor是不允许添加实例变量,注意是不能添加实例变量,而不是属性成员(具体参见类别不是应该只能添加方法吗?类别现在能直接添加属性了?。因为category是运行期决定的,所以当你添加实例变量的话,那么这个类的内存空间就要变了,而类的内存空间是在编译期就确定了。这里你可以添加属性成员,但是得自己实现getter和setter方法。

define 和 const常量有什么区别?

define在预处理阶段进行替换,const常量在编译阶段使用

宏不做类型检查,仅仅进行替换,const常量有数据类型,会执行类型检查

define不能调试,const常量可以调试

define可以定义一些简单的函数,const不可以

__block和__weak修饰符的区别?

__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,也可以修饰基本数据类型

__weak只能在ARC模式下使用,只能修饰对象(NSString),不能修饰基本数据类型

__block修饰的对象可以在block中被重新赋值,__weak修饰的对象不可以

static关键字的作用

函数(方法)体内 static 变量的作用范围为该函数体,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;

在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;

在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明 它的模块内;

在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;

在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量堆和栈的区别

从管理方式来讲

对于栈来讲,是由编译器自动管理,无需我们手工控制;

对于堆来说,释放工作由程序员控制,容易产生内存泄露(memory leak)

从申请大小大小方面讲

栈空间比较小

堆控件比较大

从数据存储方面来讲

栈空间中一般存储基本类型,对象的地址

堆空间一般存放对象本身,block的copy等

风格纠错题


修改后的代码

typedef NS_ENUM(NSInteger, CYLSex)

{

    CYLSexMan,CYLSexWoman

};

@interface CYLUser : NSObject@property (nonatomic, copy, readonly) NSString *name;

@property (nonatomic, assign, readonly) NSUInteger age;

@property (nonatomic, assign, readwrite) CYLSex sex;

- (instancetype)initWithName:(NSString *)name age:(NSUInteger)age sex:(CYLSex)sex;

- (instancetype)initWithName:(NSString *)name age:(NSUInteger)age;

+ (instancetype)userWithName:(NSString *)name age:(NSUInteger)age sex:(CYLSex)sex;

@end

Objective-C使用什么机制管理对象内存?

MRC 手动引用计数

ARC 自动引用计数,现在通常ARC

通过 retainCount 的机制来决定对象是否需要释放。 每次 runloop 的时候,都会检查对象的 retainCount,如果retainCount 为 0,说明该对象没有地方需要继续使用了,可以释放掉了

ARC通过什么方式帮助开发者管理内存?

通过编译器在编译的时候,插入类似内存管理的代码

ARC是为了解决什么问题诞生的?

首先解释ARC: automatic reference counting自动引用计数

了解MRC的缺点

在MRC时代当我们要释放一个堆内存时,首先要确定指向这个堆空间的指针都被release了

释放指针指向的堆空间,首先要确定哪些指针指向同一个堆,这些指针只能释放一次(MRC下即谁创建,谁释放,避免重复释放)

模块化操作时,对象可能被多个模块创建和使用,不能确定最后由谁去释放

多线程操作时,不确定哪个线程最后使用完毕

综上所述,MRC有诸多缺点,很容易造成内存泄露和坏内存的问题,这时苹果为尽量解决这个问题,从而诞生了ARC

ARC下还会存在内存泄露吗?

循环引用会导致内存泄露

Objective-C对象与CoreFoundation对象进行桥接的时候如果管理不当也会造成内存泄露

CoreFoundation中的对象不受ARC管理,需要开发者手动释放

什么情况使用weak关键字,相比assign有什么不同?

首先明白什么情况使用weak关键字?

在ARC中,在有可能出现循环引用的时候,往往要通过让其中一端使用weak来解决,比如:delegate代理属性,代理属性也可使用assign

自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用weak,自定义IBOutlet控件属性一般也使用weak;当然,也可以使用strong,但是建议使用weak

weak 和 assign的不同点

weak策略在属性所指的对象遭到摧毁时,系统会将weak修饰的属性对象的指针指向nil,在OC给nil发消息是不会有什么问题的;如果使用assign策略在属性所指的对象遭到摧毁时,属性对象指针还指向原来的对象,由于对象已经被销毁,这时候就产生了野指针,如果这时候在给此对象发送消息,很容造成程序奔溃

assigin 可以用于修饰非OC对象,而weak必须用于OC对象

@property 的本质是什么?

@property其实就是在编译阶段由编译器自动帮我们生成ivar成员变量,getter方法,setter方法

ivar、getter、setter是如何生成并添加到这个类中的?

使用“自动合成”( autosynthesis)

这个过程由编译器在编译阶段执行自动合成,所以编辑器里看不到这些“合成方法”(synthesized method)的源代码

除了生成getter、setter方法之外,编译器还要自动向类中添加成员变量(在属性名前面加下划线,以此作为实例变量的名字)

为了搞清属性是怎么实现的,反编译相关的代码,他大致生成了五个东西

// 该属性的“偏移量” (offset),这个偏移量是“硬编码” (hardcode),表示该变量距离存放对象的内存区域的起始地址有多远

OBJC_IVAR_$类名$属性名称

// 方法对应的实现函数

setter与getter

// 成员变量列表

ivar_list

// 方法列表

method_list

// 属性列表

prop_list

每次增加一个属性,系统都会在ivar_list中添加一个成员变量的描述

在method_list中增加setter与getter方法的描述

在prop_list中增加一个属性的描述

计算该属性在对象中的偏移量

然后给出setter与getter方法对应的实现,在setter方法中从偏移量的位置开始赋值,在getter方法中从偏移量开始取值,为了能够读取正确字节数,系统对象偏移量的指针类型进行了类型强转

@protocol 和 category 中如何使用 @property

在protocol中使用property只会生成setter和getter方法声明,我们使用属性的目的,是希望遵守我协议的对象能实现该属性

category 使用 @property也是只会生成setter和getter方法声明,如果我们真的需要给category增加属性的实现,需要借助于运行时的两个函数

objc_setAssociatedObject

objc_getAssociatedObject

NSOprationQueue 与 GCD

1、GCD是底层的C语言构成的API,而 NSOprationQueue 及相关对象是 Objc 的对象。在GCD中 队列中执行的是有 block 构成的任务,这是一个轻量级的数据结构、而 Operation 给我们提供了更多的选择。

2、在NSOperationQueue中,我们可以随时取消已经设定要准备执行的任务(未开始的任务),而GCD已经加入 block 的 不容易取消。

3、NSOperation 可以设定依赖关系,可以设置 一个Operation 在另一个 Operation 执行结束之后 在执行,可以设置 先后执行的顺序。还可以 通过 KVO 去监听 Operation是否完成或取消。GCD则不可以被监听。

4、Operation queue 提供了更多你在编写多线程程序时需要的功能,并隐藏了许多线程调度,线程取消与线程优先级的复杂代码,为我们提供简单的API入口。从编程原则来说,一般我们需要尽可能的使用高等级、封装完美的API,在必须时才使用底层API。但是我认为当我们的需求能够以更简单的底层代码完成的时候,简洁的GCD或许是个更好的选择,而Operation queue 为我们提供能更多的选择。

 IOS应用文件的目录都是什么?缓存文件存在哪个文件里?他的上一层是什么?

    .plist 文件

    Documents 【数据是永久性的存储,出发时卸载APP,存储的是备份】

    Library 【Cache 和 Preferences 文件目录】【存储的是缓存数据 , 系统在内容不足时 对cache 文件的清除】

        Preferences : [NSUserDefaults standardUserDefaults]

        Cache : EGO

    tmp 【系统会自动对这个文件的清除 】中转站

TCP和UDP的区别?

TCP 有连接的 数据可靠 数据不边界, 长连接 socket,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达

UDP 无连接 数据不可靠 数据有边界,UDP尽最大努力交付,即不保  证可靠交付

1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接

2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保  证可靠交付

3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的

  UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

5、TCP首部开销20字节;UDP的首部开销小,只有8个字节

6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

Https 介绍

https = http + ssl

HTTP下加入SSL层,来保证数据传输的安全,

http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

劣势

对数据进行加解密决定了它比http慢

需要进行非对称的加解密,且需要三次握手。

首次连接比较慢点,当然现在也有很多的优化。

AFNetworking 的内部结构

网络请求分为两部分  请求 响应  发送

请求处理文件

响应处理文件

发送管理文件(管理 NSURLSession) NSURLConnection

在AFNetworking 3.0之前,底层是通过封装NSURLConnection来实现的。

在AFNetworking 3.0之后,也就是在iOS 9.0 之后,NSURLConnection被弃用,苹果推荐使用NSURLSession来管理网络请求,所以AFNetworking 3.0之后,底层是通过封装NSURLSession来实现的。

从AFNetworking 3.0中之后,下面三个方法被弃用了。

    AFURLConnectionOperation

    AFHTTPRequestOperation

    AFHTTPRequestOperationManager

依次被下面三个类代替了,同时请求方法也跟着改变了,所以AFNetworking 3.0以后发生了很大的变化。

    AFURLSessionManager

    AFHTTPSessionManager

    AFNetworkReachabilityManager

SDWebImage 图片处理的原理

SDWebImage底层实现有沙盒缓存机制,主要有三块组成

1、内存图片缓存

2、内存操作缓存

3、磁盘沙盒缓存

首先从内存中查找是否有图片缓存,如果有就直接显示,如果没有

就生成 NSInvocation 添加到 队列中从硬盘中查找图片是否有缓存,有就将图片 添加到内存缓存中。如果都没有有

就生成一个下载器 SDWebImageDownloader 开始下载图片。下载完成的图片 同时添加到内存缓存和硬盘缓存中,

写入 硬盘单独 用NSinvocationOperation 完成,避免拖慢主线程。

CALayer与UIView的区别是什么?

两者最大的区别就是:涂层不会直接渲染到屏幕上;

UIView是IOS界面元素的基础,所有界面元素都是继承于它,他的本身全是由 CoreAnimation 来实现的;

真正的绘图部分,是有 CALayer 类来管理的;

一个UIView上可以有n个CALayer,每个layer来显示一种东西,增强UIView的展现能力。

TCP和UDP

TCP:(传输控制协议),提供面向连接的、可靠地点对点的通信;

UDP:(用户数据报协议),提供非连接的不可靠的点对多点的通信;

实际运用中,看程序注重的是哪一方面,是可靠还是快速;

TCP的三次握手

第一次握手:客户端发送syn(syn=j)包到服务器,并进入syn_send状态,等待服务器进行确认;

第二次握手:服务器收到客户端的syn包,必须确认客户的SYN(ack = j + 1),同时自己也发送一个SYN包(syn = k),即SYN + ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户收到服务器发送的SYN+ACK包之后,向服务器发送确认包(ACK = k + 1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成第三次握手。

使用系统的某些block api(如UIView的block版本写动画时),是否也考虑引用循环问题?

    UIView animate 动画

    NSOperationQueue

    NSNotification

    不需要考虑 循环引用

    但如果你使用一些参数中可能含有 ivar 的系统 api ,如 GCD 、NSNotificationCenter就要小心一点:比如GCD 内部如果引用了 self,而且 GCD 的其他参数是 ivar,则要考虑到循环引用:

GCD的队列(dispatch_queue_t)分哪两种类型?

串行队列Serial Dispatch Queue

并行队列Concurrent Dispatch Queue

苹果为什么要废弃dispatch_get_current_queue?

dispatch_get_current_queue容易造成死锁

dispatch_barrier_async函数的作用

【 https://www.cnblogs.com/denz/p/5277666.html 】

1、实现高效率的数据库访问和文件访问

2、避免数据竞争

lldb(gdb)常用的调试命令

1> po:打印对象,会调用对象 description 方法。是 print-object 的简写

2> expr:可以在调试时动态执行指定表达式,并将结果打印出来,很有用的命令

3> print:也是打印命令,需要指定类型

4> bt:打印调用堆栈,是 thread backtrace 的简写,加 all 可打印所有thread 的堆栈

5> br l:是 breakpoint list 的简写

6> n:是换行

7> p:是打印这个对象所属的类,即其父类


字典的排序

NSArray *sortedKeys = [self.keyCntDickeysSortedByValueUsingComparator:^NSComparisonResult(id obj1, idobj2) {

 if ([obj1 integerValue] > [obj2 integerValue]) {

 return (NSComparisonResult)NSOrderedAscending;

        }

 if ([obj1 integerValue] < [obj2 integerValue]) {

 return (NSComparisonResult)NSOrderedDescending;

        }

 return (NSComparisonResult)NSOrderedSame;

    }];

bundle(沙盒)

bundle(沙盒):一个应用只能在自己的沙盒中读取或存储文件,而不能操作其他沙盒中的文件。好处:保护应用的隐私不受侵犯,保护系统文件的安排,应用删除后相关文件也能被全部清除。

    每个应用都有自己的沙盒,沙盒的根目录的获取方法是NSHomeDirectory()。

    根目录下的内容:

         -.app文件,实际上是一个文件夹,包含了可执行文件、Nib文件、图片资源、plist等。XCode中能看到的资源,及编译后的可执行文件,都封装在app中。

        -Documents文件夹,用于存放你的应用所产生的数据,该文件夹可通过iTunes备份,可以存储游戏进度等。

        -Library文件夹,用于存放用户偏好和临时文件。

        -tmp文件夹是系统的中转站。


文件管理器

    NSFileManager,defaultManager()返回一个文件管理器的单例(多线程下不安全)。init(),在多线程编程中应尽量使用init()。

    代理方法:-fileManager:shouldRemoveItemAtPath和-fileManager:shouldRemoveItemAtURL在移除操作之前被调用。

    -removeItemAtPath:error:删除位于指定路径的文件、连接、目录(及其所有子目录、文件)。

    -removeItemAtURL:error:同上。

    -contentOfDirectoryAtPath:查找所有位于给定路径的子路径和文件。返回值为一个数组,其中包含了NSString对象。查找只在当前目录进行,不会进入下一层目录。

    -subpathsAtPath:查找给定路径下的所有子路径。深度查找,不限于当前层,也会查找package的内容。

    -fileExistsAtPath:判断文件是否位于一个路径下面。

    -isReadableFileAtPath:查询文件的可读性

    -isWritableFileAtPath:可写性

    -isExecutableFileAtPath:查询文件的可执行性

    -isDeletableFileAtPath:可删除性


NSString的路径功能

    -pathWithComponent:参数是一堆components构成的数组,返回的路径是由这些components连接而成的路径字符串,相邻components之间用/隔开。

    -pathComponents:返回一个数组,包含路径中的components。

    -fileSystemRepresentation:返回C字符串

    -isAbsolutePath:判断是否为绝对路径

    -pathExtension:返回文件的扩展名,没有的就返回空字符串

    -stringByAppendingPathComponents :向现有路径添加一个component。斜杠/会被自动加上

    -stringByAppendingPathExtension:向现有路径加上文件的扩展名

    -stringByDeletingLastPathComponent:移除最后一个路径component

    -stringByDeletingPathExtension:删除路径扩展名

    -stringByAppendingPaths:参数为一个数组,此方法将数组中的字符串对象作为路径一次添加到源字符串后面。

你可能感兴趣的:(IOS知识基础篇)