前言
投的第一份简历,第一次面试
首先说一下印象吧:一家创业公司,HR姐姐很nice,公司环境很不错,位置也好就在南京路步行街附近,交通方便。
至于面试题,不了解的后端、动画、Autolayout和CALayer一带而过。了解的就问得很简单基础,不过毕竟第一次面试,感觉答得。。。呵呵!所以在这里重新整理为自己总结一下吧!
面试问题如下
1.对MVC的理解
答:M代表Model(模型数据);V代表View(视图/界面);C代表Controller(控制器)
Controller从Model中取到数据控制View的内容显示,所以Controller可以访问Model和View。但是Model为了重用而不能访问Controller和View,View不能直接到Model中取数据,他需要设置Controller中的数据源方法,让Controller帮它到Model中取数据。
额......是不是有点乱,上图:
MVC图解.png
注:图中的标注“1”处,并不是代表View拥有Controller属性,而是访问Controller的dataSource方法
另:用文章MVC模式下通过xib自定义cell中的MVC模式为例大体总结一下MVC之间的工作(对MVC不了解的建议先看这篇文章)
1.模型Borrow中,写一个构造方法解析字典属性,写一个类方法 通过调用构造方法返回解析的数据。
2.自定义的BorrowCell继承自UITableViewCell,拥有cell中控件的属性,写一个类方法返回这个自定义的cell。同行BorrowCell拥有模型Borrow属性,并重写其setter方法,在setter方法中为BorrowCell中的控件绑定模型数据
3.BorrowViewController里添加UITableView,并使用自定义的BorrowCell。在Controller里加载plist文件,通过Model里的类方法解析后数据传给BorrowCell的Borrow属性
说到在UITableView里使用自定义的Cell,面试时的一件极惭愧的事:面试官看到我的代码在cellForRow方法中有这么一段:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
DetailCell *cell = [[DetailCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[DetailCell ID]];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
说:你的cell没有采用重用机制吗?毕竟第一次面试,当时竟然懵了。想怎么会没有重用机制呢,所有的TableViewCell最基本的嘛。当时没答出来,回来之后才发现只有这里忘写了而已,改为:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
DetailCell *cell = [tableView dequeueReusableCellWithIdentifier:[DetailCell ID]];
if (cell == nil) {
cell = [[DetailCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[DetailCell ID]];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
面试官以为我不知道 dequeueReusableCellWithIdentifier
方法呢
由此引发下一个面试题
2.UITableViewCell的重用机制
答:UITableView刚出现时只会创建视图上看得见cell,向下滚动UITableView,即将出现新的cell时,它会去缓存池中取带有自定标识reuseIdentifier的cell(这个缓存池是UITableView自带的)缓存池中有这样的cell就取出重用,没有就创建。对于上方消失的cell会带着重用标记reuseIdentifier放到缓存池中去。
3.在你的作品中Cell是怎么计算行高的
答:以文章MVC模式下代码自定义cell(自计算行高)为例:
UITableView在代理方法cellForRowAtIndexPath
里展示cell的时候,对于cell的创建是采用重用的机制,但是对于代理方法heightForRowAtIndexPath
里是统一将所有的cell高度全部计算出来的。
为证明我的说法,在cellForRowAtIndexPath
里添加如下打印语句:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 打印语句
NSLog(@"cellForRow--%ld", (long)indexPath.row);
在heightForRowAtIndexPath
里添加如下打印语句:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"heightForRow--%ld", (long)indexPath.row);
打印结果如下:
看到打印我就懵了,和以前不一样了......
总共有6个cell,高度全部计算出来了。在界面能显示出来的两个cell中先执行
cellForRowAtIndexPath
,再执行heightForRowAtIndexPath
。具体哪个版本目前还不清楚,但至少在Xcode6.3以前
heightForRowAtIndexPath
方法将所有的cell高度全部计算出之后就不再执行此方法了,但目前来看显然不是。好吧,先按照之前的情况来吧,目前这种自计算行高的方法仍然适用(如果看过文章MVC模式下代码自定义cell(自计算行高)会发现肯定适用啊)其实就是把cell的高度提前全都计算出来
这里以文章MVC模式下代码自定义cell(自计算行高)为例大体总结一下:
1.模型Query中,写一个构造方法解析字典属性,写一个类方法 通过调用构造方法返回解析的数据。
2.在继承自UIView的QueryFrame中,拥有cell中控件的属性,同行拥有模型Query属性和一个cellHeight属性,并重写其setter方法,在setter方法中计算cell中控件的frame和cell的高度
3.自定义的QueryCell继承自UITableViewCell,重写- (instancetype)initWithStyle
方法,添加cell子控件。拥有QueryFrame属性,并重写其setter方法,在setter方法中为QueryCell中的控件绑定模型数据和计算子控件frame
4.QueryViewController里添加UITableView,并使用自定义的QueryCell。在Controller里加载plist文件,通过Model里的类方法解析后数据传给QueryCell的Borrow属性
5.在代理方法heightForRowAtIndexPath
里调用QueryCell的QueryFrame属性的cellHeight来返回cell高度
4.代理模式是怎么使用的,自己写过吗?
答:自己写一个代理,用一个最简单经典的买票的例子吧。Person拥有一个买票的代理来查询票价和剩余票数
首先新建协议,声明代理中拥有的方法:
#import <Foundation/Foundation.h>
@protocol TicketDelegate <NSObject>
- (int)leftTicket;
- (double)ticketPrice;
@end
Person拥有一个代理和买票方法:
#import <Foundation/Foundation.h>
#import "TicketDelegate.h"
@interface Person : NSObject
@property (nonatomic, retain)id<TicketDelegate> ticketDelegate;
- (void)buyTicket;
@end
在代理对象中遵守代理协议:
#import <Foundation/Foundation.h>
#import "TicketDelegate.h"
@interface Delegate : NSObject <TicketDelegate>
@end
并实现代理的方法:
#import "Delegate.h"
@implementation Delegate
- (int)leftTicket {
return 10;
}
- (double)ticketPrice {
return 45.5;
}
@end
这样一来,就可以设置Person的代理为TicketDelegate,并调用代理的方法了:
Person *p = [[Person alloc] init];
Delegate *d = [[Delegate alloc] init];
p.ticketDelegate = d;
[p buyTicket];
同样的,要想让Person拥有其他的代理也是这样。
而想让另一个对象改变代理的具体行为,只需要让这个对象遵守TicketDelegate的协议并实现其声明的方法即可。当然这只是最简单基础的例子啦!
5.frame与bounds的区别
答:
- frame: 视图基于父视图坐标系统的位置和大小(参照点是父视图的坐标系统)
- bounds:视图基于本地坐标系统的位置和大小(参照点是自己的坐标系统,以0,0点为起点)
6.关于CALayer
答:关于CALayer只是设置控件圆角的时候用过控件的layer属性
详细的就附几篇文章来看吧:
iOS开发UI篇—CALayer简介--系列
iOS 面试大全从简单到复杂(简单篇)
详解CALayer 和 UIView的区别和联系
7.关于GCD
答:这个......怎么答呢,因为开头就没有答好,所以面试官也没有往下问。
先看这篇博客吧iOS开发多线程篇—GCD介绍
组织好语言再来补充......
8.如何自定义UITabBarController和ViewController
答:没答出来。附一个连接,共同学习其开源代码吧https://github.com/ChenYilong/CYLTabBarController
有心得再来补充......
9.是否了解动画、Autolayout和后端
答:不了解所以就一带而过了。学到了再写Blog吧,迫不及待的学习......
以下是一些个人问题:
10.英语怎么样,阅读文档呢?
11.什么时候开始自学的,如何自学的?
12.来上海的原因
13.职业规划
就记得这么多了。
体会
- 果然小白,要学的东西还有太多,感觉自己现在最缺的就是时间和实践!
- 第一次面试,单对答题状态。。。唯有呵呵二字!
后记
小白出手,请多指教。
如言有误,还望斧正!
再次感谢我的iOS启蒙老师MJ大大,遥祝小码哥越来越茁壮!----MJ万千桃李之一
- 转载请保留原文地址:http://www.jianshu.com/p/572104511644
- 有兴趣的读者欢迎关注我的微博:与佳期
网友评论