面试题总结

属性关键字的理解以及在MRC和ARC下的写法的不同,对其要有深刻的理解和认识。

assign和weak的区别?

weak在对象被释放的时候回自动销毁赋值为nil,而assign(会造成野指针),只是对应的引用计数为0,并没有把对象指向nil,所以会造成野指针的问题。

assign主要用来修饰基本的数据类型,分配在栈上,有系统去自动管理分配和释放工作。assign也是可以用来修饰对象的,但是有一个严重的问题:就是在对象释放的时候,assign修饰的对象并不会安全释放,会造成野指针的问题

category的原理

在load之前也就是在runtime初始化的时候回进行合并。

方法定义在分类里面,怎么去执行

方法合并,程序运行的时候动态的将类的方法合并??

在底层生成对应的struct _category_t结构体变量不一样

分类添加的方法列表对应的方法有指定的方法指针地址,原来的数据结构不变,原来的类的方法列表放到最后面,会优先加载对应的分类的方法(这就是优先调用分类的方法)

MethodExchange的原理?什么时候去交换方法,交换的原理是什么?

实际是交换对应的方法的地址,但是外部的函数名还是没有变化,这就是为什么在自定义的函数里面再次去调取同样的函数名不会造成循环。改变了对应的函数地址。

如果是写在+load方法里面会在编译的时候就交换了对应的方法指针,+initialize是在类第一次用到的时候去交换。

谁管理autoreleasePool?

系统。

多线程

子线程创建和runloop的关系。

iOS性能的优化

  • 对象的创建

    • 当使用到的对象涉及到CALayer的时候,会到主线程去操作,如果不涉及到UI相应事件的话,最好用CALayer
  • 对象的调整

    • 涉及到frame ,bounds, center等的属性调整的时候都会消耗CPU去计算
  • 对象的销毁

对象的销毁最好放到后台去销毁

iOS设备定位服务

首先用户需要同意允许定位到对应的服务信息;

会通过蜂窝网络,Wi-Fi,GPS,蓝牙来判断大致的位置信息

NSRunloop的mode

创建的线程是自带的不允许自己创建,创建并保活你的runloop

NSDefaultRunLoopMode UITrackingRunLoopMode UITInitializationRunLoopMode GSEventReceiveRunLoopMode

NSRunLoopCommonModes(NSDefaultRunLoopMode|UITrackingRunLoopMode)

GCD源码

https://opensource.apple.com/tarballs/libdispatch/

Foundation框架可以参考GNUStep,学习下思路。

下载地址http://www.gnustep.org/resources/downloads.php

FB661284-F36F-40D3-83F8-129C2227711B.png

runtime本身是开源的

https://opensource.apple.com/source/objc4/

开发总结和学习

Interview

clang

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc [对应的文件路径]

clang -emit-llvm -S [对应的文件名字]

bt 函数调用栈调试

p 打印地址信息

p/x 打印地址

x 查看对应的地址信息里面保存的值

C++代码只是参考

step oc的单步调试

stepi(si) 汇编的单步调试

next oc的单步调试

nexti(ni) 汇编的单步调试

gnusetp反写了oc代码,可以跟踪oc代码的实现(cocoa框架的代码)

NSObject 需要多大的内存

默认是16个字节,不够也会返回16个,字节对齐。
class_getInstanceSize 得到的是对应的这个类需要的内存的大小

malloc_size 是操作系统的分配的内存大小(在这个里面需要遵循对应的字节对齐和操作系统对应的一些规范)

NSObject 实际分配多大的内存

sizeOf编译的时候就决定了对应的大小

isa和superClass调用流程

13315615-1255b59d53589f51.png

OC三种对象形式: 实例对象(instance),类对象(class),元类对象(meta_class)

实例对象:存着这个对象的一些信息

类对象:存储着isa、superClass属性、对象方法、协议、成员变量…...

元类对象:isa、superClass、类方法…...

对象的isa指向哪里?

interface对象的isa指向类对象;

class对象的isa指向meta-class对象;

meta-class的isa指向根类的isa(oc里面是NSObject)

对象的类对象里面存放着什么?

存储着isa、superClass属性、对象方法、协议、成员变量…...

KVO原理内部机制

添加不同的对象去监听对应的值得变化;

发送消息的时候的isa指针是不一样的

动态生成的一个NSKVONotifying_xxx的类,这个类是对应的xxx类的子类,(???在这里带着两个问题去思考,就是新的类的isa指针指向哪里,还有就是对应的添加的观察者set方法的内部实现原理)

//例子 ARC
- (void)setAge:(int)age {
 _age = age;
}
​
//创建后的setter方法
//添加了KVO的观察者的内部实现是利用runtime动态的创建了一个此类的子类NSKVONotifying_xxx
- (void)setAge:(int)age {
 _NSSetIntValueAndNotify();
}
//调用的是Foundation框架的这个c函数
//在这个方法里面会调用
//伪代码
void _NSSetIntValueAndNotify{
 [self willChangeValueForKey:key];
 [super setAge:age];
 [self didChangeValueForKey:key];  //然后再在didChangeValueForKey里面观察者去执行对应的监听
}
- (void)didChangeValueForKey:(NSString *)key {
 [observer observeValueForKeyPath:@"age" ofObject:self change:change context:context]; 
}
  • 利用runtime的动态特性,动态的生成一个子类,并且将原来的isa指针指向这个子类对象;

  • 当修改instance的属性时,会调用Foundation的_NSSetxxxValueAndNotify函数

    • willChangeValueForKey

    • 父类原来的setter

    • didChangeValueForKey

    内部会触发监听器(Observer)的监听方法observerValueForKeyPath:Object:change

手动触发KVO

调用willChangeValueForKey和didChangeValueForKey

KVC

kvc设置会不会触发KVO呢???

,首先寻找setter方法,允许访问实例变量也会触发对应的KVO。

@property (nonatomic ,assign) int age;
//设置会首先查询 _age , _isAge, age ,isAge
//取值 getAge ,age ,isAge, _age

Category

oc是消息发送机制,类对象里面查询对应的方法;但是category里面的方法存储在哪里呢

都会存储到对应的类方法里面,isa指针,在里面会对方法重新进行排序

  • 编译之后的底层结构是结构体;里面存储着分类的对象方法,类方法属性,协议

  • 在程序运行的时候,runtime会将Category的数据,合并到类信息中(类对象,元类对象中)是怎么合并的呢??分类中有相同的方法怎么去加载执行

分类是有顺序的,根据加载的顺序。分类是先执行的,会先执行分类的方法

Category和Extension的区别

  • Class Extension在编译的时候,它的数据已经包含在类信息中

  • Category是在运行时,才会将数据合并到类信息中

分类中有load方法吗?load方法什么时候调用?load方法能继承吗?

有load方法; 类加载进内存的时候会被调用;load方法没有被覆盖 为什么分类的load方法会被调用 普通的调用都是通过isa指针找到类去实现对应的方法,如果没有则通过superClass去调用,而load方法则不一样,它是直接取出来method的地址,直接调用。

  1. load方法的调用是从父类开始的。

  2. 分类则是根据编译顺序加载的。load都会调用。

initialize

  • 类第一次接收到消息的时候会被调用;

  • 会先调用父类的initialize(消息发送机制);

  • 被加载过之后就不会再去加载了;(Objc)msgSend也是根据isa指针去寻找superClass)

load和initialize的区别

load是直接找到函数指针去执行,initialize消息发送机制(如果分类实现对应的initizlize实现则调用父类的initialize)父类的initizlize会被会被多次

  1. 调用方式,load根据函数地址直接调用,initizlize是通过objc_msgSend调用的

  2. 调用时刻: load是runtime加载类,分类的时候调用(只会调用一次);initizlize是第一次被调用的时候出现,每个类只会被调用一次(父类的initizlize可能会被调用多次)

    • load 先调用自己的load,调用子类的load,会先调用父类的load; 分类的load方法是先编译先调用

    • initizlize先初始化父类,再初始化子类

Category能否添加成员变量?怎么添加?

struct object_IMPL {

Class isa;

int _age;

}

分类可以添加属性,只生成了对应的函数的声明;

不能直接添加成员变量,但是可以间接添加;

关联对象runtime ,全局变量的问题;

//时刻记住对应的调用图和调用顺序,还有对应的各个结构

block面试题

block本质上是一个对象,也有isa指针

封装了函数调用的地址和调用环境的OC对象

捕获变量

能够访问外部的变量;

默认的是(auto)值传递
auto int a = 10; //自动变量 
static int height = 20;  //地址传递

上述两个在block的时候auto是值传递,static是获取到对应的地址

局部变量会被捕获,全局变量不会被捕获

oc里面self是隐式参数,属于局部静态参数(捕获地址)


屏幕快照 2018-10-21 上午9.04.56.png

问题 函数调用栈???

copy

栈copy到堆上,堆上的代码由程序员自己释放,在ARC下编译器自动帮助转换成了NSMallocBlock,MRC下需要自己手动释放;

对象类型的auto变量

auto 自动捕获进block代码块

如果block是在栈上的,不管外面的是strong还是weak引用都不会产生引用;

如果block是在堆上的根据外部的修饰符

__block修饰符,用来修饰auto,不能用来修饰static,编译器会将__block包装成一个对象

__block的内存管理

  • 捕获变量NSObject *obj在内部会释放copy和dispose对象;

  • __weak修饰

runtime

消息转发机制

isa(64位下为共用体union)

位运算:& || !读取规则

掩码:一般是用来做位与运算的

结构体:位域的运算 New

在Arm64位下用共用体其中33位用来存储isa指针(优化过的内存)

struct method_t {

SEL name;

const char *types;

IMP imp;

}

不同类中同一个SEL是相同的;imp就是函数的指针;

消息机制 给方法调用者发送消息

三个阶段

  1. 消息发送 源码汇编


    屏幕快照 2018-10-24 上午10.51.54.png
  1. 动态方法解析 resolveInstanceMethod | resolveClassMethod

  2. 消息转发

    forwardingTargetForSelector返回一个对象,给这个对象发送消息重复进入上述的流程

方法签名:返回值类型、参数类型

@dynamic 自己手动去生成对应的setter和getter的实现,也不会自动生成实例变量

@synthesize age = _age 属性age生成 _age实例变量,并生成对应的setter和getter

-(Class)class { return objc_getClass(self); } ????

消息接受者仍然是子类对象,只是查找方法的时候失去父类开始寻找的。

runtime API

class_coptIvarlist

oc是一门动态性比较强的编程语言;runtime是一套c语言的API; 是在程序运行的时候才去执行的代码。

平时项目中怎么使用runtime

  1. 利用关联对象给分类添加属性

  2. 遍历类的所有成员变量(修改UitextFIeld的站位文字的颜色,字典转模型,自动归档)

  3. 交换方法(交换系统的方法)

  4. 防止程序崩溃(消息发送机制)

监听所有按钮的事件 hook UIControl的sendActionTargetEvent

method_exchangeImplementation //类簇 NSString NSArray NSDictionary 真实类型是其他类型

runloop

source0,source1,timer,port,observer在每一种模式下,每一个runloop至少有一种mode

runloop在实际开发中的应用

控制线程的生命周期(AFNetworking);线程保活

解决NSTimer在滑动时停止工作的问题;//runloop不同的Mode模式下运行对应的diamante

监控应用卡顿;//加载大量的图片,导致滑动卡顿现象

性能优化;//

NSRunloop的run方法是无法停止的,它专门用于开启一个永不销毁的线程。 (生成与销毁)

注意:当发生坏内存访问出现的错误

线程的封装

自定义一个线程方法:封装的时候考虑到是否包含暴露对应的接口信息

子线程全新的runloop需要添加对应的source0,source1或者tiemr,observer,port

屏幕快照 2018-10-30 上午11.24.26.png

GCD等多线程技术

数据安全问题怎么去防止???

加锁:

sync和sync决定着在哪一个线程执行;决定这是否开启新的线程。

???OSSpinLock自旋锁 忙等状态一直耗费CPU资源

  • 目前不安全,优先级反转问题;

线程的调度:时间片段轮转算法(线程、进程)

OSUnfairLock

Pthread_mutex互斥锁

  • NSLock

  • NSRerusiveLock

  • NSCondition

  • NSConditionLock : NSCondition

Dispatch_queue

Dispatch_semaphore

@synchronized([self class]) {每个类对象都是一个,对象可能有多个,所以在加锁的时候需要注意一下}

在子线程中,串行队列,顺序执行代码相当于有了依赖。

ios性能问题加锁

屏幕快照 2018-10-31 上午11.24.06.png

queue决定着怎么样去执行


屏幕快照 2018-10-30 下午12.05.34.png

队列的特点:FIFO

  • sync往当前串行队列中添加任务才会造成死锁

PerformSelector:withObject:afterDelay:

在runloop中,用到了定时器,添加到runloop中去,beforWaiting

atomic/nonatomic

atomic:原子性操作setter和getter,但是不是线程安全的可以在其它的线程中释放掉该资源

IO安全操作

多读单写操作

pthread_rwlock 会进入休眠

dispatch_async_barrier 异步栅栏

CADisplayLink和NSTimer循环引用和不准时的问题

定时器的内存管理:

  • 利用Block的弱引用;

  • 创建一个中间的弱指针引用,当ViewController销毁的时候引用链会断裂;(消息转发机制)

消息转发机制: NSProxy(转么用来消息转发)和NSObject

  1. 消息发送

  2. 动态解析

  3. 消息转发

NSObject和NSProxy做代理的区别

NSProxy主要用于消息转发

定时器的准确性

NSTimer和CADisplayLink依赖runloop,runloop本身可能会有耗时的操作

GCD依靠内核去执行时间,不依赖runloop,所以不存在线程阻塞的问题,导致定时器运行不准确;

程序空间

  • 代码段

  • 数据段

  • 内核区

Tagged Pointer

从64bit开始引入的技术NSNumber,NSDate,NSString等小对象的存储。

耗电操作

  • CPU

  • 网络请求

  • 定位

  • 图像

优化:

  • 尽可能降低CPU,GPU

  • 少用定时器

  • 优化I/O操作

    • 尽量不要频繁写入小数据,最好批量一次性写入

    • 读写大量重要数据时,考虑用dispatch_io,提供了基于GCD的异步操作文件I/O的API,用dispatch_io系统会优化磁盘访问

    • 数据量比较大的,建议用数据库(SQLite,CoreData)

  • 网络优化

    • 减少,压缩网络数据

    • 缓存数据(多次请求相同的)

    • 试用断点续传

  • 网络不可用时,不要尝试执行网络请求

  • 让用户可以取消长时间运行或者速度很慢的网络操作,设置合适的超时时间

  • 定位

    • 尽量使用少的定位,不要多次去尝试定位信息;

APP启动优化

冷启动

  1. dyld dynamic link editor,apple动态链接库,mac-omac-o,装载APP的可执行文件,同时会递归加载所有依赖的动态库,当dyld把可执行文件、动态库装载完毕后会同志runtime进行下一步的处理

    优化:合并一些动态库,尽量不要使用C++虚函数,objc的+load方法,可以使用+ininitialize和dispatch_once

  2. runtime: 调用map_iamges进行可执行文件进行解析

  3. main

热启动

安装包瘦身

屏幕快照 2018-11-01 下午3.41.35.png
屏幕快照 2018-11-01 下午3.45.01.png

多线程

pthread

NSThread

GCD

设计模式与架构

多做项目:多接触

MVP

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,034评论 1 32
  • 把网上的一些结合自己面试时遇到的面试题总结了一下,以后有新的还会再加进来。 1. OC 的理解与特性 OC 作为一...
    AlaricMurray阅读 2,471评论 0 20
  • iOS 面试题总结(一) 101. 修改下面的代码: typedef enum{ UserSex_Man,User...
    AlaricMurray阅读 1,607评论 0 6
  • 花絮:从上一篇文章的发表到这篇文章的发表已经有很长一段时间了,一直在摸索适合自己的学习方式,到现在还是没有找到适合...
    七秒记忆的鱼儿阅读 129,771评论 123 804
  • 1.UIView 与CALayer的关系 每个UIView内部都有一个CALayer在背后提供内容的绘制和显示,并...
    夜之海澜阅读 218评论 0 0