尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

网易iOS校招笔试复盘:Runtime、内存管理与多线程核心考点解析

网易iOS校招笔试复盘:Runtime、内存管理与多线程核心考点解析 我帮好几个师弟师妹复盘过网易2018校招iOS开发工程师笔试卷说实话这份卷子在当年的大厂校招里算是比较有代表性的。它不考偏题怪题而是把iOS开发工程师日常最常碰到的语言特性、内存管理、runtime机制、并发模型、UI渲染链路和工程化认知全部串联起来。几年后再看iOS面试题的核心框架其实没有太多变化只是技术在演进考察角度更细了。这篇文章不打算把原题一张张抄出来当题库念而是基于这份卷子的考察逻辑把iOS校招笔试和后续面试里真正重要的考点拆开讲清楚并附上我当时帮人复盘时积累的实操经验和避坑记录。如果你正准备参加大厂iOS岗校招或者工作一两年想跳槽想系统梳理一遍iOS开发的核心知识这篇文章应该能给你一条比较清晰的备考主线。1. 笔试卷的整体布局与考察逻辑1.1 基础语法与语言特性不是背概念而是考“能不能写稳”网易这份2018年的笔试卷选择题和填空题部分覆盖了大量Objective-C的语言细节。比如分类Category与扩展Extension的区别、属性关键字在不同场景下的语义差异、block对变量的捕获规则、字符串和集合类在可变与不可变之间的底层差异。很多人觉得这些是“基础题”应该拿满分但实际失分率很高。原因在于校招笔试题很少直接问“什么是分类”而是会给你一段看似正常的代码问最终输出是什么或者会不会崩溃。比如在一个分类里声明了一个和主类同名的方法调用时走的是哪一个比如用copy修饰NSMutableArray属性后往里添加元素会不会崩溃。这类题考察的不是记忆力而是你对Objective-C运行时查找方法、属性修饰符底层实现的理解程度。我当时给师弟的建议是不要靠刷题背答案而是把每一个知识点在工程里的真实行为验证一遍。比如分类和主类同名方法为什么分类会“覆盖”主类实现因为在runtime的方法列表插入逻辑里分类的方法会被插入到类方法列表的前面而运行时消息查找是顺着方法列表依次查找的先找到谁就调用谁。你如果只用“分类优先级更高”这种话术去答题换一个场景就懵了。只有真正理解方法列表的插入机制才能应对考官换着花样出题。1.2 从整体难度阶梯看大厂筛选逻辑网易2018校招iOS笔试卷的整体难度呈现明显的阶梯式上升。前面60%左右是“会者不难”的基础题考察候选人的日常积累中间30%是runtime、内存管理、多线程、Autorelease机制等进阶题考察的是候选人是否真正理解iOS底层运行原理最后10%是结合工程场景的开放题比如“如何优化UITableView的滑动流畅度”“App启动时间过长怎么排查”这类题没有标准答案但能直接筛选出有真实项目经验、有性能调优意识的人。这种难度设计其实反映了大厂校招的核心逻辑基础决定下限底层原理决定上限。你不能指望一个完全没接触过iOS的人通过刷两周题就能通过但也不需要你已经是资深架构师。关键看你有没有形成“遇到问题愿意往底层多挖一层”的习惯。所以这份卷子给备考者的启示是复习时不要只盯着高频题更要建立完整的知识链路把语言、运行时、系统框架串起来理解。1.3 2018年时间点与技术背景2018年这个时间点iOS生态正处于一个重要过渡期。iPhone X带来了刘海屏和Safe Area概念iOS 11引入了大标题导航栏、File Provider、Drag and Drop等新特性iOS 12则在性能优化上下了很大功夫。网易这份笔试卷里也明显带上了这些时代印记比如会考察Safe Area与Auto Layout的配合、iPhone X底部Home Indicator的适配、以及64位架构下的一些兼容性问题。如果你现在才看到这份题会觉得有些考点已经“过时”了比如iOS 11的适配细节现在基本不用单独处理。但考察背后的能力模型并不过时快速学习新系统特性、从系统变更中找到对现有工程的影响范围、在兼容与创新之间做取舍。这也是为什么我建议校招同学不要只刷最新面经老牌大厂的历年题同样值得做一遍因为它能帮你建立iOS开发的纵向历史观。2. 内存管理校招笔试里的送分题与连环坑2.1 ARC不是自动垃圾回收笔试卷里关于内存管理的题目几乎每年都有网易这份也不例外。但很多候选人有一个根深蒂固的误解觉得ARC等于Java里的垃圾回收写代码时完全不用关心内存。这个误解在笔试里会吃大亏。ARC是编译期的内存管理优化它在编译阶段帮你在合适的位置插入retain、release、autorelease调用但它的前提是编译器能正确分析对象的生命周期。一旦出现编译器无法确定的情况比如block对self的强引用、delegate用strong修饰、NSTimer对target的持有ARC是帮不了你的循环引用该发生还是会发生。我印象比较深的一道题是在一个视图控制器里用[NSTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:]创建了一个重复定时器并且在dealloc里invalidate问这个控制器会不会正常释放。很多人答“会”因为dealloc里做了清理。但实际答案是不会。因为scheduledTimerWithTimeInterval方法会将timer添加到当前RunLoop的common mode中而RunLoop会对timer强引用timer又会强引用target也就是控制器形成一个self - timer - self的循环dealloc根本不会被调用。正确的做法是在viewWillAppear里创建timer在viewWillDisappear里invalidate或者使用iOS 10之后提供的block版本timer在block里使用__weak修饰self打破循环。2.2 循环引用所有大厂面试必问的连环坑循环引用这一块笔试卷通常会从三个角度去考代理属性、block、NSTimer。代理属性考的是weak和assign的区别。很多人知道delegate要用weak但不知道为什么。如果delegate用strong那么两个对象会互相持有谁都没法释放。那为什么不能用assign因为assign在对象释放后不会自动置nil再向这个野指针发消息会直接崩溃。而weak在对象释放时由runtime自动把指针置为nil消息发送时就变成了向nil发消息不会崩溃。这个“自动置nil”的机制很多人只是在概念上知道笔试里一旦问到底层怎么实现的就卡住了。其实weak表是一张哈希表以对象地址为keyvalue是weak指针地址的数组。对象释放时会根据对象地址找到所有weak指针逐个置为nil。block的循环引用更隐蔽。常考的场景是在block里直接使用self的属性或者调用self的方法。如果你不假思索地写self.name xxxblock就会强引用self如果self又通过属性持有这个block就形成了循环。笔试卷里经常给出一段代码让你指出哪里有问题并改错。标准答案是使用__weak typeof(self) weakSelf self;在block内部再用__strong typeof(self) strongSelf weakSelf;。很多初学者只写了weakSelf其实在block执行期间如果self已经被释放weakSelf就变成nil了block里后续的self操作都不会执行。用strongSelf可以保证在block执行期间self不会被释放同时不产生循环引用。这个“先weak后strong”的技巧笔试和面试都极爱考。2.3 从笔试题延伸引用计数与autorelease的底层细节Objective-C的引用计数原理也是网易这类笔试卷的常客。核心问题是retain增加引用计数、release减少引用计数、当引用计数降为0时调用dealloc。但ARC下你不需要手动调用这些方法编译器会在合适的位置插入。比较进阶的考点是autorelease。比如autoreleasepool的作用范围、什么时候释放、一个对象的autorelease是在什么时候真正release的。很多人只知道“autoreleasepool包裹的代码在作用域结束时释放”但RunLoop与autoreleasepool的关系才是大厂真正想考的。每个RunLoop周期里系统会创建一个autoreleasepool在RunLoop休眠前或退出时drain。这就是为什么在循环里大量创建临时对象时需要手动加一个autoreleasepool来及时释放内存而不是等整个RunLoop周期结束。2018年笔试那会儿还有一道关于dealloc的题也很有区分度问在dealloc里能不能用self访问属性、能不能调用self的方法、能不能用weakSelf。答案是在dealloc期间对象正在被释放不应该使用self访问属性或调用方法因为相关对象可能已经释放会造成野指针。正确做法是直接使用成员变量来清理资源。这个知识点很多工作一两年的开发者也未必注意得到。3. Runtime与动态特性iOS开发的核心灵魂3.1 消息发送与消息转发从“方法调用”说起Objective-C的消息机制是runtime最核心的内容也是网易笔试卷区分度最高的考点之一。基本问题通常是[obj doSomething]这行代码在运行时发生了什么。答案是编译器会将其转换为objc_msgSend(obj, selector(doSomething))然后runtime根据obj的isa指针找到对应的类在类的方法列表包括父类链中查找对应的IMP找到后调用找不到则进入消息转发流程。消息转发流程是笔试和面试都很爱深入追问的部分分为三个阶段第一阶段动态方法解析。runtime会调用resolveInstanceMethod:你可以在这里用class_addMethod动态添加一个实现。第二阶段快速转发。如果动态解析不处理runtime会调用-forwardingTargetForSelector:你可以把消息转发给另一个对象。这个机制常被用来实现“多继承”效果比如让一个对象代理另一个对象的方法。第三阶段完整转发。如果前两步都不处理runtime会调用-methodSignatureForSelector:获取方法签名然后调用-forwardInvocation:你可以把方法调用包装成NSInvocation做统一处理或转发给多个对象。如果这一步也不处理最终会抛出unrecognized selector sent to instance异常。我当时给师弟讲这一段的时候让他把消息转发想成一个“层层上报的流程”先问自己能不能动态补一个实现不能再问有没有备用对象能处理还不行就把完整方法调用包装起来做统一处理最后实在不行就崩溃。这样记不仅笔试能写出流程图式的回答面试时也不会被追问卡住。3.2 Method Swizzling看起来简单坑却不少Method Swizzling在runtime类题目里出现频率很高网易2018年这道题我印象很深给一个黑盒类添加日志统计功能要求不改变原有类的实现写出实现思路。标准答案是使用Method Swizzling交换两个方法的IMP。交换方法的核心代码很简单 (void)load { static dispatch_once_t onceToken; dispatch_once(onceToken, ^{ Class class [self class]; SEL originalSelector selector(viewDidLoad); SEL swizzledSelector selector(swizzled_viewDidLoad); Method originalMethod class_getInstanceMethod(class, originalSelector); Method swizzledMethod class_getInstanceMethod(class, swizzledSelector); BOOL didAddMethod class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if (didAddMethod) { class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } }); }但真正决定你能不能拿高分的是你能不能说出这段代码里几个关键细节。第一Swizzling要在load里做因为load是类加载时调用能保证交换只发生一次第二要用dispatch_once保证线程安全第三为什么不直接method_exchangeImplementations而要先用class_addMethod判断因为如果原类本身没有实现“被交换的方法”而是从父类继承来的直接交换会把父类的方法实现也换掉影响范围过大。先用class_addMethod给当前类添加一个原selector的实现就可以把影响控制在这个类内部。这些细节在笔试里很难想到但你一旦在项目里真正做过Swizzling比如无侵入统计页面停留时长、处理iOS系统版本兼容问题就会理解这段代码为什么必须这么写。这也是为什么我反复跟校招同学讲遇到runtime相关题目不要只背最终代码一定要理解每一步在防御什么。3.3 KVO的实现原理为什么说它是“用runtime拼出来的”KVO也是网易这类笔试卷的常客而且经常和KVC一起考。基础题是什么是KVO、什么是KVC、两者有什么区别。进阶题是KVO的底层实现是什么手动触发KVO怎么做KVO的优缺点是什么。KVO的底层机制大概是当你对一个对象添加KVO监听时runtime会动态生成一个该类的子类NSKVONotifying_原类名并将对象的isa指针指向这个子类。子类重写了被观察属性的setter方法在setter里先调用willChangeValueForKey:再调用父类的setter最后调用didChangeValueForKey:。手动触发KVO就是要自己调用这两个方法。这道题的考察深度往往在于为什么KVO能监听到属性变化但监听数组变化却经常失效。因为直接对NSMutableArray调用addObject:是不会触发KVO的必须通过KVC的可变数组代理方法mutableArrayValueForKey:获取代理对象再通过代理对象操作数组KVO才会生效。很多做惯了业务开发的人在这上面踩过坑搞不清楚为什么数据明明变了UI却没有刷新。另外有一个多年后被问烂了的问题如果父类和子类都监听同一个属性KVO会触发几次。答案是子类监听触发一次、父类监听触发一次总共两次。这在嵌套KVO场景里很容易惹出问题笔试卷偶尔也会拿这个做文章。3.4 associated object与分类添加属性分类里不能直接添加成员变量这是Objective-C语言层面的限制。但业务中经常需要在分类里“添加属性”怎么办用associated object。网易笔试里有道题就是给UIView添加一个分类要求可以让任意UIView绑定一个字符串写出实现。实现不难static const char kAssociatedKey kAssociatedKey; implementation UIView (Associated) - (void)setCustomTagInfo:(NSString *)customTagInfo { objc_setAssociatedObject(self, kAssociatedKey, customTagInfo, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (NSString *)customTagInfo { return objc_getAssociatedObject(self, kAssociatedKey); } end但面试时通常会追问OBJC_ASSOCIATION_COPY_NONATOMIC是如何影响内存管理的、什么时候会触发release。答案在于associated object的释放时机是对象自身dealloc时runtime会统一调用_object_remove_assocations来释放所有关联对象。如果关联策略是retain或copy会先release旧值再设置新值。这个机制在日常开发中用来给系统类扩展轻量级状态非常顺手但要注意不能滥用尤其是用strong策略关联一个持有大量资源的对象时要谨慎管理生命周期。4. 并发与Runloop笔试里最容易失分的两个模块4.1 GCD的队列层级与“死锁”问题GCD相关题目在网易2018校招笔试卷里分量很重而且多数是以代码分析的形式出现。最经典的考察点是在主线程执行以下代码会发生什么。dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(hello); });答案是死锁。原因很清晰主线程同步派发一个任务到主队列任务需要主线程执行但主线程正在等待同步任务执行完毕互相等待谁也不让谁。这个例子几乎出现在每一家公司的iOS笔试题里但每年还是有很多人答错或者只知道“会死锁”却说不清原因。备考时一定要把队列、线程、同步/异步派发的关系彻底理清。再进阶一点的题目是在自定义串行队列里执行同步任务到自身队列会不会死锁。答案也是会。因为同步派发会阻塞当前线程并等待任务完成而任务又被派发到同一个串行队列需要等待队列里前一个任务当前任务完成形成循环等待。同理dispatch_sync到并行队列则不会死锁因为并行队列不需要等待前面的任务完成系统会直接开新的线程执行任务。这里建议你把GCD的核心概念整理成一张对照表来记忆串行队列 同步派发 大概率死锁同队列串行队列 异步派发 按顺序执行但不阻塞并行队列 同步派发 在新线程执行不阻塞当前线程并行队列 异步派发 常见方式不阻塞当前线程并发执行。笔试之外面试官还可能追问dispatch_group怎么实现等所有任务完成后再统一刷新UIdispatch_semaphore怎么控制并发数。这些属于iOS多线程开发的高频工具建议每个都写个小demo跑一遍光看概念印象不深。4.2 线程安全与原子性atomic不等于线程安全线程安全相关的题网易笔试主要考两类一类是NSMutableArray、NSMutableDictionary在多线程环境下读写崩溃问题另一类是atomic属性是否保证线程安全。先说前者。多线程并发操作NSMutableArray最常见的崩溃日志是“index out of bounds”或者“malloc: *** error for object ... pointer being freed was not allocated”。原因是数组在扩容、插入、删除时如果另一个线程同时读取可能读到中间状态。解决方案有几种加锁NSLock、synchronized、os_unfair_lock、用并行队列包裹写操作、或者用更底层的pthread_rwlock做读写分离。笔试卷一般会让你选择最合适的方案这时候不要只看答案要能说出每种方案的优缺点。比如synchronized简单但性能一般它底层是递归锁适合轻量级保护os_unfair_lock性能更好但不支持递归读写锁适合读多写少的场景。再说atomic。atomic的作用是保证属性的setter和getter原子性也就是多线程同时set不会让属性处于未定义状态。但它并不保证“业务逻辑”的线程安全。举个例子如果两个线程同时执行self.count 1即使count声明为atomic最终结果也未必是2。因为实际是“读取旧值、计算新值、写入新值”三步原子性只能保证单步读写安全不能保证三步作为一个整体不被插队。这个考点非常经典也经常在面试中被追问出一个反问那怎么才能做到线程安全答案是加锁或者使用专门的原子操作。4.3 Runloop与事件循环为什么App能“一直活着”Runloop是iOS开发里出了名的“不见得每天直接用但面试总要考”的知识点。网易2018年笔试卷也涵盖了Runloop的常见模式包括Runloop有哪几种运行模式Default、Common、Tracking、Initialization等、Timer在滑动时为什么会被暂停、如何让NSTimer在UIScrollView滑动时依然工作。Timer在滑动时被暂停的根本原因是UIScrollView滑动时主线程Runloop会切换到UITrackingRunLoopMode而NSTimer默认添加到了NSDefaultRunLoopMode在Tracking模式下不会被处理。解决办法有两个把timer添加到NSRunLoopCommonModes或者放到子线程的Runloop里。这个知识点非常实用因为很多人在做轮播图时遇到过图片轮播在滑动时停顿的问题原因就在这里。进阶点在于Source0和Source1的区别。Source0是用户主动触发的事件比如点击屏幕Source1是系统内核事件比如基于Port的通信。笔试卷一般不会让你抠这种细节但面试官如果顺着Runloop往下问你最好能答出来。再往下就是Autoreleasepool与Runloop的关系、Runloop在AFNetworking常驻线程中的应用。当时我在给师弟梳理时让他把Runloop想象成一个“大管家”没有事件就睡觉有事件就分发给对应的人处理这个类比在理解层面帮助很大。5. UI与渲染从Auto Layout适配到离屏渲染5.1 Auto Layout、Safe Area与UIStackView的适配2018年的iOS笔试如果完全避开Auto Layout和iPhone X适配反而奇怪。网易那份卷子里就有关于Safe Area的题目比如“在iPhone X上如何让内容避开底部Home Indicator区域”。这在iOS 11之后有成熟的API直接使用view.safeAreaLayoutGuide即可Adaptive Layout中还有additionalSafeAreaInsets可以额外扩展安全区域。同时UIStackView也是当时比较新的考点。UIStackView并不是一个真正意义上的布局控件而是一个容器它帮你去管理内部子视图的约束关系。它解决的核心痛点是当多个视图水平或垂直排列间距和尺寸需要动态变化时手写约束会非常繁琐。用UIStackView可以极大减少约束代码而且配合分布对齐选项Fill、FillEqually、FillProportionally、EqualSpacing、EqualCentering可以实现很多复杂布局。笔试里可能会给你一段描述问用什么控件实现最合适这时候如果你只会Auto Layout不会UIStackView就会失分。但也要提醒一句UIStackView在嵌套复杂布局时性能未必好它本质上是将多个约束组合起来管理层级嵌套过深会带来约束计算量上升。所以我在实际项目中的经验是简单的等分、自适应排列优先用UIStackView复杂的交错布局还是要回到Auto Layout甚至手动frame。5.2 离屏渲染iOS性能优化里绕不开的坎离屏渲染在网易2018年笔试中出现过一道很经典的题设置UIView的圆角效果什么时候会触发离屏渲染什么时候不会。很多人只知道“设置圆角会触发离屏渲染”但实际是否触发取决于实现方式。如果你用view.layer.cornerRadius配合view.layer.masksToBounds YES并且在view上还有内容包括背景图片、子视图、背景色那么iOS会触发离屏渲染。因为系统需要先把view的内容渲染到一个离屏的缓冲区再通过圆角路径裁切后合成到屏幕。如果你只是给UIImageView设置圆角且不设置masksToBounds系统可以直接在渲染阶段处理不一定会产生离屏渲染。离屏渲染为什么需要关注因为它在GPU渲染管线里是额外的一步尤其是tableview滚动时如果有大量页面同时触发离屏渲染会发现滑动帧率明显下降出现掉帧。优化手段常见的有几种用UIBezierPath做圆角裁剪、把圆角提前合成到图片上、用CAShapeLayer配合mask、或者只对最上层视图设置圆角并配合图层透明度处理。笔试如果考到性能优化不从离屏渲染的角度答就少了一个关键得分点。5.3 UITableView滚动流畅度与卡顿排查UITableView的性能优化是iOS笔试和面试最高频的开放题之一。网易2018年笔试卷有一道“如何保证UITableView滑动流畅”虽然不要求写代码但需要你给出系统性的优化方案。常规答案分几个层面第一层是cell复用这个是最基础的必须答到但光答这个不够。第二层是高度计算。如果cell高度是动态的不要每次都调用heightForRowAtIndexPath去实时计算最好缓存高度使用Auto Layout时要注意约束完整性减少约束冲突。iOS 11之后可以使用UITableViewAutomaticDimension但要注意预估行高estimatedRowHeight的设置设置得当可以显著提升首次加载速度。第三层是渲染压力。减少离屏渲染、减少复杂图层层级、避免在cellForRowAtIndexPath里做大量耗时操作比如图片解码、字符串计算。尤其是图片如果用UIImage imageNamed:加载大图每次滚动都可能触发图片解码造成卡顿。比较成熟的方案是使用异步解码、提前裁剪、按需加载。第四层是数据源与UI更新。不要在后台线程直接操作UI不要在主线程做大量计算。如果数据是分页加载的要注意批量更新和差量刷新避免reloadData拖慢滚动。答这种题时如果能把“CPU耗时点”和“GPU耗时点”分开讲面试官会认为你有实际的iOS开发性能调优经验而不只是背答案。6. 网络与工程化进阶笔试里最容易拉开差距的部分6.1 HTTP、HTTPS与TCP三次握手的基础知识网易2018校招iOS笔试卷的网络题难度不低。常见考点包括HTTP和HTTPS的区别、TLS握手过程、TCP和UDP的区别、TCP三次握手和四次挥手、HTTP的请求头与响应头常见字段、GET与POST的区别。这些知识在大学课程里都学过但校招笔试会结合iOS开发场景出题比如“ATSApp Transport Security是什么为什么要用HTTPS”。ATS是iOS 9之后引入的网络传输安全机制默认要求所有网络请求都使用HTTPS。如果你的App因为某些原因需要兼容HTTP接口必须在Info.plist里配置NSAppTransportSecurity的例外字段。这个考点我在实际项目里遇到过很多次特别是接手旧项目时发现一堆HTTP接口上线时配置不规范审核时容易被拒。所以笔试里如果考到ATS最好能说明配置的细节和潜在风险。6.2 Charles抓包与接口调试的实操技巧网络调试是iOS开发日常离不开的能力网易笔试卷里的网络题也会间接考察类似思路比如“线上有用户反馈接口返回异常但你本地复现不了如何排查”。这种开放题最稳妥的思路就是先用Charles抓包看看线上接口的完整请求和响应确认是入参、出参还是网络链路问题。Charles抓包本身不复杂但要抓HTTPS的明文字段需要在手机上安装并信任Charles的SSL证书。这里有一个经常踩到的坑安装了证书后如果App开启了证书校验SSL Pinning依然抓不到包。遇到这种情况需要暂时禁用证书校验或使用支持SSL Pinning绕过的方式。不过这部分内容在面试中最好谨慎展开重点应该放在你的排查思路和工具使用是否熟练。还有一个实用技巧用Charles做接口的断点调试Breakpoints与本地映射Map Local可以快速mock后端返回数据很多UI联调场景用这个方式特别高效。但这里要提醒一点工程里不要为了测试方便把mock数据写死在代码里我曾经见过一个App上线后还在读取本地mock数据界面一片假数据这种问题在Code Review时要重点防范。6.3 证书管理、签名机制与上架流程iOS开发者的App证书管理、描述文件Provisioning Profile、上架流程是大厂iOS笔试卷里比较偏实践的考点尤其对于有上架经验的候选人这类题几乎是送分题。网易2018年也有类似题目比如“描述文件过期会导致什么问题”、“Xcode里的证书和描述文件之间的关系是什么”。简单梳理一下开发者证书Certificate用来签名你的App确保App的开发者身份合法描述文件Provisioning Profile是把开发者证书、App ID和测试设备捆绑在一起的配置文件。真机调试、发布TestFlight、上架App Store都需要对应的描述文件。如果描述文件过期最直接的表现是App无法装在真机上或者提交到App Store时校验失败。很多同学第一次接触时会被一堆证书和过期时间搞懵其实只要掌握一个核心流程用Apple ID登录开发者中心生成证书打开Xcode的Signing Capabilities自动管理签名真机调试时确保设备被加进描述文件。上架流程通常是在App Store Connect创建应用信息 - 构建版本用Xcode Archive上传 - 选择构建版本 - 填写审核资料 - 提交审核。2018年的上架流程和现在差别不大只是审核材料要求越来越细像隐私政策、收集数据的说明现在都必须写得很清楚。6.4 混合开发与架构选型2018年的热与冷混合开发方案在2018年非常热网易笔试卷里也有关于Hybrid App和跨端框架的开放题。那时React Native已经火了两三年Flutter刚起步Weex在国内也有不少落地案例。笔试卷可能会问你如何看待原生开发与跨端框架的选型在什么场景下选择React Native什么场景下继续使用原生。我当时给师弟准备的答题框架是永远不要脱离业务形态来谈技术选型。如果你的团队以iOS和Android双端为主、业务需求变化快、UI复杂度不高跨端方案可以明显提升并行效率。如果业务追求极致体验重度依赖系统硬件能力比如地图导航、音视频处理、AR那么原生依然是更稳的方案。近两年Flutter和RN各有起落国内大厂也有不少团队转回原生或自研方案这个趋势本身就是很好的谈资。架构题也是笔试的压轴常客。MVC、MVVM、MVP的区别和适用场景组件化方案如何设计Router如何解耦页面跳转。网易2018年笔试卷我记得后面有一道开放题是“如何设计一个App的架构来支持多人协作开发和多功能模块扩展”这题没有标准答案但最容易踩的坑是答得过于宏大、抽象没有落到具体工程细节。比较好的答法是先用一句话说明架构目标然后从工程分层、模块划分、通信机制、依赖管理、持续集成几个维度展开每个维度给出一个具体例子。比如工程分层上可以把“基础层网络、存储、工具- 业务层页面、组件- 应用层启动、路由”分开。通信机制上可以用协议接口约束模块间的调用避免相互直接依赖。这样一来即使面试官追问你也有足够的细节支撑。7. 常见问题与避坑实录7.1 笔试常见易错点速查我在帮人复盘网易2018年题时把历届同学最容易出错的点整理成了一个快速自查表。考点易错点正确理解delegate用strong或assign修饰用weakweak在对象释放后自动置nilblock变量捕获与循环引用需要__weak打破循环block执行期再__strongcopy修饰NSMutableArray/NSMutableStringcopy会变成不可变对象后续会崩溃NSTimerdealloc里invalidate无法解决RunLoop强引用需要提前invalidateKVO监听数组变化需要mutableArrayValueForKey的代理对象GCDdispatch_sync到主队列死锁互相等待属性atomic保证线程安全只保证单步安全不保证逻辑安全离屏渲染圆角一定会离屏渲染只有配合masksToBounds且内容需要裁剪时才是架构一上来谈大道理结合具体工程分层、模块、通信、依赖、CI这张表可以直接拿来当考前最后一天的速查记忆卡比翻厚重的笔记高效得多。7.2 面试追问时最容易暴露问题的地方笔试过关后面试官喜欢顺着笔试里的错题或薄弱点往下追问。我见过最多的翻车场景是笔试里写了__weak typeof(self) weakSelf self;但面试官问“为什么用weak而不是assign”时答不上来笔试题里写了dispatch_async但问“并行队列和串行队列在性能上差多少”时就说不出所以然知道KVO可以监听属性变化但问“KVO会不会导致循环引用”时完全没有思路。所以准备面试时不要只准备“正确答案”还要为每个答案准备至少两个“为什么”和两个“如果”。比如你知道delegate要用weak那还要知道weak底层是怎么自动置nil的你知道block里用了weakSelf那还要能说清楚什么时候需要strongSelf你知道GCD并行队列并发执行那还要能说明并发任务多了以后线程爆炸的风险以及DispatchSemaphore怎么控制最大并发数。7.3 备考策略与资料整理建议关于怎么准备这类大厂笔试卷我给身边人推荐的方式一直是“三遍法”。第一遍限定时间独立做一遍把不会的题目标记出来重点收集做错的题。注意一定要独立完成不要一边看答案一边写否则根本看不出自己的知识盲区。第二遍一道题一道题去溯源。做错的每一道题都要找到对应的官方文档或权威博客把背后的机制搞清楚。比如block捕获变量去看clang转换后的C代码KVO底层看runtime源码里NSObject的响应方法GCD死锁用Playground写个demo复现一下。这个阶段最耗时但收获最大。第三遍合上题目按知识域复述整个答题思路。不需要背原题而是把每个知识点的来龙去脉讲给自己听。能讲得清楚面试就不会太慌。我自己在iOS开发里摸爬滚打这些年最大的体会是大厂校招笔试不像很多人想的那样只是“筛选简历的工具”它更像是给候选人一面镜子让你看到自己在整个iOS知识体系里还有哪些盲区。网易2018这份卷子虽然已经过去几年但它的题目质量和考察思路放到今天依然很有参考价值。你把它当成一块磨刀石磨的不仅是答案本身更是你拆解问题、钻到底层原理的能力。最后再分享一个小技巧做笔试卷时遇到不会的题先别忙着查资料拿一张纸把自己“猜”的答案和理由写下来哪怕写的是“我不确定但我认为……”。这个动作很关键因为它逼你把隐性的直觉转成显性的逻辑链。答完之后再对照解析你会发现自己真正的思考断点在哪里。iOS开发是一个需要持续自省的领域笔试只是第一关后面还有更长的路。祝你顺利拿下offer。
返回列表