您的位置:时时app平台注册网站 > 编程知识 > 【面试】阿里 iOS 开发实习电话面试记录(二)时

【面试】阿里 iOS 开发实习电话面试记录(二)时

2019-09-15 00:59

这次的面试官,一听他说话,年纪就不小了,感觉差不多也是个全栈。他问的 iOS 相关的问题我 90% 都答上来了,提到操作系统、计算机网络、算法之类的,我直说因为长期不投入实用,都忘了,他就说那就不问这方面的了,最后还劝告说,这些更多是方法论的东西,建议我学好,下面是他问了的 iOS 相关的问题:

ARC下,是Xcode编译器自动判断是否有强指针引用着对象,从而自动帮我们在恰当的位置加上引用计数加一或减一的代码<retain/release/autorelease>。使用Strong就表明这个OC对象是被使用强指针引用的。
因此,我们自己定义的需要使用的OC属性(UI控件除外)时,一般使用Strong;UI控件一般使用weak,因为在UI控件通常被父控件的subViews数组强引用着。
首先,循环引用的意思是两个对象互相强引用着(或者多个对象引用循环),造成互相都无法释放,效果类似与‘死锁’。避免循环引用的方式是将其中一个对象设置为weak。我印象比较深的在使用block时造成的循环引用,例如使用AFN的时候

2.第一题(创建一个TableViewController)

  • 1.我们假定问题和答案分别是字典的Key和Value,把十道题目分别存放到一个.plist文件中,使之能从.plist文件中读取

  • 2.根据MVC思想,我们面向模型开发,而不是面向字典开发,因此,我们从plist文件中读出的字典数组需要转化为模型数组

    • 我们需要定义模型test类,里面有两个属性:
    • @property (nonatomic, copy) NSString *testName;题目
    • @property (nonatomic, copy) NSString *testContext;答案
    • 创建一个用于展示问题和答案的PageViewController类,.h头文件里向外暴露了@property (nonatomic, strong) YXTest * text;属性
    • 通过TableViewController类里面使用KVC把字典数据转为模型数据,再在以下方法把模型数据传递给PageViewController用于展示。
     - tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ PageViewController *page = [[PageViewController alloc]init]; page.text = self.text; [self.navigationController pushViewController:page animated:YES]; }
    
  • 什么是VFL,请说出“H:[_aImageView]-10-[_aButton]”代表的意思?

    • VFL:苹果为了简化手写Autolayout代码发明出来的,好像叫可视化格式语言(表示真的很久没用过啊!自从发现了Masonry),那行代码的意思应该是设置水平方向的约束。
    • 手写Autolayout代码我一般使用第三方框架:Masonry。用Masonry写出来的代码的可读性非常好。
  • NSPersistentStoreCoordinator\\NSManagedObjectContext和NSManagedObject三者什么关系

    • CoreData里面的属性,NSPersistentStoreCoordinator:持久性数据协调器;NSManagedObjectModel:管理数据模型;NSManagedObjectContext:管理数据内容。三者的关系:CoreData根据NSManagedObjectModel对象确定如何将底层的持久化文件中的数据映射为NSManagedObject对象。
    • 对于数据持久化的操作,我使用比较多的是通过FMDB框架操作SQLite,因为CoreData是基于OC封装了SQLite,性能并没有SQLite好。例如GCD性能比NSOperation好。
  • ARC下什么时候使用Strong,什么时候使用Weak,如何避免循环引用?

    • ARC下,是Xcode编译器自动判断是否有强指针引用着对象,从而自动帮我们在恰当的位置加上引用计数加一或减一的代码<retain/release/autorelease>。使用Strong就表明这个OC对象是被使用强指针引用的。
    • 因此,我们自己定义的需要使用的OC属性时,一般使用Strong;UI控件一般使用weak,因为在UI控件通常被父控件的subViews数组强引用着。
    • 首先,循环引用的意思是两个对象互相强引用着(或者多个对象引用循环),造成互相都无法释放,效果类似与‘死锁’。避免循环引用的方式是将其中一个对象设置为weak。我印象比较深的在使用block时造成的循环引用,例如使用AFN的时候
     // 在AFN的block内使用,防止造成循环引用 __weak typeof weakSelf = self; [[AFHTTPSessionManager manager] GET:CYXRequestURL parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) { NSLog; // 利用MJExtension框架进行字典转模型 weakSelf.menus = [CYXMenu objectArrayWithKeyValuesArray:responseObject[@"result"]]; // 刷新数据(若不刷新数据会显示不出) [weakSelf.tableView reloadData]; } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) { NSLog(@"请求失败 原因:%@",error); }];
    
  • 将一个MRC的项目转换为ARC的项目,应该遵循什么规则?

    • (我也不太确定,猜的)规则难道是,需要转换为ARC文件的就转换,,不需要转换的就不转换?过滤掉无需转换的文件(不支持ARC的文件)。无需转换的文件应添加-fno-objc-arc标记
  • Objective-C如何对内存管理的,有哪些情况会导致崩溃,说说你的看法和解决方法?

    • (...上面已经问过ARC了,这题我猜是问iOS系统的内存管理原则了吧?)
    • 当App收到三次内存警告还不做处理时,会造成闪退。
    • 处理方法:在didReceiveMemoryWarning内释放不必要的资源。
  • 简述GCD是如何简化线程编程的?

    • GCD相对于pthread/NSThread,通过自动管理线程的生命周期,从而简化了线程编程。
  • Extensions有哪些类型,每种类型可以完成的功能有哪些?

    • (那时候有几个忘了....)六种类型:Today、Share、Action、Photo Editing、Storage Provider、Custom keyboard
    • 完成的功能可以顾名思义
  • 如何衡量ViewController的规模?-(这个真的不太清楚。。求大神指导)是代码量?业务逻辑的复杂程度?还是ViewController做了过多数据加工的事情,造成ViewController的规模变大?

  • MVVM是什么,请简述MVVM的特点以及解决了哪些问题

    • MVVM(ViewModel),是一种View层的架构模式,衍生自MVC。
    • 特点:把数据加工的任务从Controller中移到了ViewModel,使得Controller只需要专注于数据调配的工作,ViewModel则去负责数据加工并通过通知机制让View响应ViewModel的改变。
    • 目标:为MVC中的Controller减负

- CYXInfiniteScrollView.h文件

#import <UIKit/UIKit.h>@interface CYXInfiniteScrollView : UIView@property (strong, nonatomic) NSArray *images;@property (weak, nonatomic, readonly) UIPageControl *pageControl;@property (assign, nonatomic, getter=isScrollDirectionPortrait) BOOL scrollDirectionPortrait;@end

- CYXInfiniteScrollView.m文件

#import "CYXInfiniteScrollView.h"static int const ImageViewCount = 3;@interface CYXInfiniteScrollView() <UIScrollViewDelegate>@property (weak, nonatomic) UIScrollView *scrollView;@end@implementation CYXInfiniteScrollView- (instancetype)initWithFrame:frame{ if (self = [super initWithFrame:frame]) { // 滚动视图 UIScrollView *scrollView = [[UIScrollView alloc] init]; scrollView.showsHorizontalScrollIndicator = NO; scrollView.showsVerticalScrollIndicator = NO; scrollView.pagingEnabled = YES; scrollView.bounces = NO; scrollView.delegate = self; [self addSubview:scrollView]; self.scrollView = scrollView; // 图片控件 for (int i = 0; i<ImageViewCount; i  ) { UIImageView *imageView = [[UIImageView alloc] init]; [scrollView addSubview:imageView]; } // 页码视图 UIPageControl *pageControl = [[UIPageControl alloc] init]; [self addSubview:pageControl]; _pageControl = pageControl; } return self;}- layoutSubviews{ [super layoutSubviews]; self.scrollView.frame = self.bounds; if (self.isScrollDirectionPortrait) { self.scrollView.contentSize = CGSizeMake(0, ImageViewCount * self.bounds.size.height); } else { self.scrollView.contentSize = CGSizeMake(ImageViewCount * self.bounds.size.width, 0); } for (int i = 0; i<ImageViewCount; i  ) { UIImageView *imageView = self.scrollView.subviews[i]; if (self.isScrollDirectionPortrait) { imageView.frame = CGRectMake(0, i * self.scrollView.frame.size.height, self.scrollView.frame.size.width, self.scrollView.frame.size.height); } else { imageView.frame = CGRectMake(i * self.scrollView.frame.size.width, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height); } } CGFloat pageW = 100; CGFloat pageH = 100; CGFloat pageX = self.scrollView.frame.size.width - pageW; CGFloat pageY = self.scrollView.frame.size.height - pageH; self.pageControl.frame = CGRectMake(pageX, pageY, pageW, pageH); [self updateContent];}- setImages:(NSArray *)images{ _images = images; // 设置页码 self.pageControl.numberOfPages = images.count; self.pageControl.currentPage = 0; // 设置内容 [self updateContent];}#pragma mark - <UIScrollViewDelegate>- scrollViewDidScroll:(UIScrollView *)scrollView{ // 找出最中间的那个图片控件 NSInteger page = 0; CGFloat minDistance = MAXFLOAT; for (int i = 0; i<self.scrollView.subviews.count; i  ) { UIImageView *imageView = self.scrollView.subviews[i]; CGFloat distance = 0; if (self.isScrollDirectionPortrait) { distance = ABS(imageView.frame.origin.y - scrollView.contentOffset.y); } else { distance = ABS(imageView.frame.origin.x - scrollView.contentOffset.x); } if (distance < minDistance) { minDistance = distance; page = imageView.tag; } } self.pageControl.currentPage = page;}- scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ [self updateContent];}- scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{ [self updateContent];}#pragma mark - 内容更新- updateContent{ // 设置图片 for (int i = 0; i<self.scrollView.subviews.count; i  ) { UIImageView *imageView = self.scrollView.subviews[i]; NSInteger index = self.pageControl.currentPage; if  { index--; } else if  { index  ; } if (index < 0) { index = self.pageControl.numberOfPages - 1; } else if (index >= self.pageControl.numberOfPages) { index = 0; } imageView.tag = index; imageView.image = self.images[index]; } // 设置偏移量在中间 if (self.isScrollDirectionPortrait) { self.scrollView.contentOffset = CGPointMake(0, self.scrollView.frame.size.height); } else { self.scrollView.contentOffset = CGPointMake(self.scrollView.frame.size.width, 0); }}

#import "CYXCollectionViewController.h"@interface CYXCollectionViewController ()@end@implementation CYXCollectionViewControllerstatic NSString * const CYXCell = @"cell";- (instancetype)init{ // 流水布局 UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; layout.itemSize = CGSizeMake; layout.minimumLineSpacing = 0; layout.minimumInteritemSpacing = 20; layout.sectionInset = UIEdgeInsetsMake(20, 0, 0, 0); return [self initWithCollectionViewLayout:layout];}- viewDidLoad { [super viewDidLoad]; self.collectionView.backgroundColor = [UIColor whiteColor]; // 注册cell [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier: CYXCell];}#pragma mark - <UICollectionViewDataSource>- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return 30;}- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier: CYXCell forIndexPath:indexPath]; UIImageView *view = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"xxx"]]; cell.backgroundView = view; return cell;}@end

iOS 客户端开发的三面。

(...上面已经问过ARC了,这题我猜是问iOS系统的内存管理原则了吧?)
当App收到三次内存警告还不做处理时,会造成闪退。
处理方法:在didReceiveMemoryWarning内释放不必要的资源。

用命令行创建一个以CocoaPods管理的项目【Test-你的姓名拼音】,新建3个ViewController,完成以下题目
    1. 将下面的问题在一个UITabView里面列出所有问题,单击每一行进入一个新的页面,里面是问题和答案。
    • 1.1 什么是VFL,请说出“H:[_aImageView]-10-[_aButton]”代表的意思?
    • 1.2 NSPersistentStoreCoordinatorNSManagedObjectContext和NSManagedObject三者什么关系
    • 1.3 ARC下什么时候使用Strong,什么时候使用Weak,如何避免循环引用?
    • 1.4 将一个MRC的项目转换为ARC的项目,应该遵循什么规则?
    • 1.5 Objective-C如何对内存管理的,有哪些情况会导致崩溃,说说你的看法和解决方法?
    • 1.6 简述GCD是如何简化线程编程的?
    • 1.7 Extensions有哪些类型,每种类型可以完成的功能有哪些?
    • 1.8 如何衡量ViewController的规模?
    • 1.9 MVVM是什么,请简述MVVM的特点以及解决了哪些问题?
  • 2.请使用UIScrollerView控件实现图片的循环切换

  • 3.请使用UICollectionView控件实现图片数据绑定,要求每行两列
  1. (我在简历上写自己独立开发了几个 App)说一下你自己做的那个 App

  2. (我大概阐述了产品方向之后,他问我技术上最难的是什么,然后随口提到了要保存图片到相册)

  3. 关于 iOS 系统相册,有哪些相关方案可以获取?

  4. 以前的 AssetsLibrary 和现在的 Photos 框架都知道吗?(我说了关于现在引入 Photos 和 PhotosUI 之后可以获取 LivePhoto 的问题)

  5. 都熟悉哪些框架,有没有特别了解的?(我说我熟悉 WebKit,然后他就问了我 GCD = =)

  6. (发现我会用 GCD 之后)能不能说一下底层?

  7. (我说我知道点 ARC 相关的底层实现,就说了一通,他很满意,这里要强烈推荐下面这本书)

    时时app平台注册网站 1Objective-C 高级编程

    同类型的问题还有 assign、weak 的区别,ARC 如何实现,编译时、运行时区别,weak 属性的对象在废弃后 指针是如何指向 nil 的……

  8. 平时了解一些架构吗?(我说我知道 MVC、MVVM。其他的光知道没用过,不敢拿出来装B)

  9. 说一下 MVVM(泪奔,难得在面试的时候能碰上自己很熟悉的,推荐不熟悉的看看最近挺火的文章《面向协议的 MVVM 架构介绍》)

  10. 知道 KVO、KVC 吗?(虽然这个东西大家都在用,但是查一下还是能查出来一些自己不知道的,心里没底的,建议现在就去 Google 一下)

  11. 你平时做 App 之后,有什么推广途径?(其中我提到了一些推广平台,国内的有 36Kr 的 NEXT、爱范儿的 MindStore 和 AppSo,国外的有 ProductHunt,好像他在听的时候还在一边拿笔记,人家也还在学习啊~)

8.什么是VFL,请说出“H:[_aImageView(==50)]-10-[_aButton]”代表的意思?

时时app平台注册网站 2随机配图

VFL:苹果为了简化手写Autolayout代码发明出来的,好像叫可视化格式语言(表示真的很久没用过啊!自从发现了Masonry),那行代码的意思应该是设置水平方向的约束。
手写Autolayout代码我一般使用第三方框架:Masonry。用Masonry写出来的代码的可读性非常好。

机试题目如下

CoreData里面的属性,NSPersistentStoreCoordinator:持久性数据协调器;NSManagedObjectModel:管理数据模型;NSManagedObjectContext:管理数据内容。三者的关系:CoreData根据NSManagedObjectModel对象确定如何将底层的持久化文件中的数据映射为NSManagedObject对象。
对于数据持久化的操作,我使用比较多的是通过FMDB框架操作SQLite,因为CoreData是基于OC封装了SQLite,性能并没有SQLite好。例如GCD性能比NSOperation好。

1.新建以CocoaPods管理的项目

  • 在命令行窗口输入以下命令
  • pod init
  • pod install
  • 等待Updating完毕以后文件夹的样式

    时时app平台注册网站 3文件夹样式

  • 打开test-cyx.xcworkspace文件

PS:下面只写思路,由于有点强迫症,想把题目做的完整一点,时间又不允许,就只把思路写写就好了

GCD相对于pthread/NSThread,通过自动管理线程的生命周期,从而简化了线程编程。

4.简述GCD是如何简化线程编程的?

2.将一个MRC的项目转换为ARC的项目,应该遵循什么规则?

3.Objective-C如何对内存管理的,有哪些情况会导致崩溃,说说你的看法和解决方法?

(那时候有几个忘了....)六种类型:Today、Share、Action、Photo Editing、Storage Provider、Custom keyboard
完成的功能可以顾名思义

(我也不太确定,猜的)规则难道是,需要转换为ARC文件的就转换,,不需要转换的就不转换?过滤掉无需转换的文件(不支持ARC的文件)。无需转换的文件应添加-fno-objc-arc标记

7.NSPersistentStoreCoordinator\NSManagedObjectContext和NSManagedObject三者什么关系

6.MVVM是什么,请简述MVVM的特点以及解决了哪些问题

5.Extensions有哪些类型,每种类型可以完成的功能有哪些?

面试题集合:http://www.cnblogs.com/markstray/p/5615040.html
1.ARC下什么时候使用Strong,什么时候使用Weak,如何避免循环引用?

M(Model)V(View)VM(ViewModel),是一种View层的架构模式,衍生自MVC。
特点:把数据加工的任务从Controller中移到了ViewModel,使得Controller只需要专注于数据调配的工作,ViewModel则去负责数据加工并通过通知机制让View响应ViewModel的改变。
目标:为MVC中的Controller减负

// 在AFN的block内使用,防止造成循环引用
 __weak typeof(self) weakSelf = self;
 [[AFHTTPSessionManager manager] GET:CYXRequestURL parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) { NSLog(@"请求成功"); 
// 利用MJExtension框架进行字典转模型 
weakSelf.menus = [CYXMenu objectArrayWithKeyValuesArray:responseObject[@"result"]]; 
// 刷新数据(若不刷新数据会显示不出)
 [weakSelf.tableView reloadData];
 } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) { NSLog(@"请求失败 原因:%@",error); }];

本文由时时app平台注册网站发布于编程知识,转载请注明出处:【面试】阿里 iOS 开发实习电话面试记录(二)时

关键词: