iOS上机题(附个人见解)
机试题目如下
用命令行创建一个以CocoaPods管理的项目【Test-你的姓名拼音】,新建3个ViewController,完成以下题目
- 将下面的问题在一个UITabView里面列出所有问题,单击每一行进入一个新的页面,里面是问题和答案。
- 1.1 什么是VFL,请说出“H:[_aImageView(==50)]-10-[_aButton]”代表的意思?
- 1.2 NSPersistentStoreCoordinator\NSManagedObjectContext和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.新建以CocoaPods管理的项目
- 在命令行窗口输入以下命令
pod init
pod install
- 等待Updating完毕以后文件夹的样式
- 打开
test-cyx.xcworkspace
文件
PS:下面只写思路,由于有点强迫症,想把题目做的完整一点,时间又不允许,就只把思路写写就好了
2.第一题(创建一个TableViewController)
1.我们假定问题和答案分别是字典的Key和Value,把十道题目分别存放到一个.plist文件中,使之能从.plist文件中读取
2.根据MVC思想,我们面向模型开发,而不是面向字典开发,因此,我们从plist文件中读出的字典数组需要转化为模型数组
- (1)(M)我们需要定义模型
test
类,里面有两个属性: @property (nonatomic, copy) NSString *testName;
题目@property (nonatomic, copy) NSString *testContext;
答案- (2)(V)创建一个用于展示问题和答案的
PageViewController
类,.h头文件里向外暴露了@property (nonatomic, strong) YXTest * text;
属性 - (3)(C)通过
TableViewController
类里面使用KVC把字典数据转为模型数据,再在以下方法把模型数据传递给PageViewController
用于展示。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
PageViewController *page = [[PageViewController alloc]init];
page.text = self.text;
[self.navigationController pushViewController:page animated:YES];
}
- (1)(M)我们需要定义模型
上面的Demo骨架已经搭完了,下面是解析一下问题的答案(当然,这些问题都可以从网上直接找到答案,这里只是简单说说我个人的理解,如有纰漏,欢迎指正)
什么是VFL,请说出“H:[_aImageView(==50)]-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属性(UI控件除外)时,一般使用Strong;UI控件一般使用weak,因为在UI控件通常被父控件的subViews数组强引用着。
- 首先,循环引用的意思是两个对象互相强引用着(或者多个对象引用循环),造成互相都无法释放,效果类似与‘死锁’。避免循环引用的方式是将其中一个对象设置为weak。我印象比较深的在使用block时造成的循环引用,例如使用AFN的时候
// 在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);
}];
将一个MRC的项目转换为ARC的项目,应该遵循什么规则?
- (我也不太确定,猜的)规则难道是,需要转换为ARC文件的就转换,,不需要转换的就不转换?过滤掉无需转换的文件(不支持ARC的文件)。无需转换的文件应添加
-fno-objc-arc
标记
- (我也不太确定,猜的)规则难道是,需要转换为ARC文件的就转换,,不需要转换的就不转换?过滤掉无需转换的文件(不支持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的特点以及解决了哪些问题
- M(Model)V(View)VM(ViewModel),是一种View层的架构模式,衍生自MVC。
- 特点:把数据加工的任务从Controller中移到了ViewModel,使得Controller只需要专注于数据调配的工作,ViewModel则去负责数据加工并通过通知机制让View响应ViewModel的改变。
- 目标:为MVC中的Controller减负
请使用UIScrollerView控件实现图片的循环切换
- 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:(CGRect)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;
}
- (void)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];
}
- (void)setImages:(NSArray *)images
{
_images = images;
// 设置页码
self.pageControl.numberOfPages = images.count;
self.pageControl.currentPage = 0;
// 设置内容
[self updateContent];
}
#pragma mark - <UIScrollViewDelegate>
- (void)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;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self updateContent];
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[self updateContent];
}
#pragma mark - 内容更新
- (void)updateContent
{
// 设置图片
for (int i = 0; i<self.scrollView.subviews.count; i++) {
UIImageView *imageView = self.scrollView.subviews[i];
NSInteger index = self.pageControl.currentPage;
if (i == 0) {
index--;
} else if (i == 2) {
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);
}
}
请使用UICollectionView控件实现图片数据绑定,要求每行两列
#import "CYXCollectionViewController.h"
@interface CYXCollectionViewController ()
@end
@implementation CYXCollectionViewController
static NSString * const CYXCell = @"cell";
- (instancetype)init
{
// 流水布局
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(150, 150);
layout.minimumLineSpacing = 0;
layout.minimumInteritemSpacing = 20;
layout.sectionInset = UIEdgeInsetsMake(20, 0, 0, 0);
return [self initWithCollectionViewLayout:layout];
}
- (void)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上机题(附个人见解)的更多相关文章
- 详解 iOS 上机题!附个人见解
庸者的救赎2015-11-20 02:30:23 AFN那个使用的时候不需要弱引用的,因为从你的封装方式来看,那个block并不会被当前视图控制器持有,而是被manager持有了,所以不需要__wea ...
- Java上机题(封装)(编写student类)
今天帮大一的童鞋写Java上机题 题目虽然很简单,但是刚拿到题目的时候愣了一下,然后就疯狂get set QuQ 其实这是一个特别基本的封装的题目(之前实验室面试大二的时候竟然还有蛮多人不知道封装的概 ...
- Python语言上机题实现方法(持续更新...)
Python语言上机题实现方法(持续更新...) 1.[字符串循环左移]给定一个字符串S,要求把S的前k个字符移动到S的尾部,如把字符串"abcdef"前面的2个字符'a'.'b' ...
- Java 哈希表(google 公司的上机题)
1 哈希表(散列)-Google 上机题 1) 看一个实际需求,google 公司的一个上机题: 2) 有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址..),当输入该 ...
- 关键路径 p3 清华复试上机题
关键路径 p3 清华复试上机题 题目描述 小H为了完成一篇论文,一共要完成n个实验.其中第i个实验需要a[i]的时问去完成.小H可以同时进行若干实验,但存在一些实验,只有当它的若干前置实验完成时,才能 ...
- 华为上机题汇总----java
以下华为上机题目都是网上整理得到的,代码都是自己调试过的,由于网上java答案较少,欢迎大家批评指正,也希望对准备华为上机的童鞋们有一点点帮助.在练习的过程中成长,加油!~~ 第1题:输入字 ...
- 浙江大学PAT上机题解析之1014. 福尔摩斯的约会 (20)
1014. 福尔摩斯的约会 (20) 时间限制 50 ms 内存限制 32000 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Y ...
- 浙江大学PAT上机题解析之1015. 德才论 (25)
宋代史学家司马光在<资治通鉴>中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人.凡取人之术,苟不得圣人,君子而与之,与其得小人,不若得愚人 ...
- 浙江大学PAT上机题解析之3-05. 求链式线性表的倒数第K项
给定一系列正整数,请设计一个尽可能高效的算法,查找倒数第K个位置上的数字. 输入格式说明: 输入首先给出一个正整数K,随后是若干正整数,最后以一个负整数表示结尾(该负数不算在序列内,不要处理). 输出 ...
随机推荐
- Redis中的数据对象
redis对象 redis中有五种常用对象 我们所说的对象的类型大多是值的类型,键的类型大多是字符串对象,值得类型大概有以下几种,但是无论哪种都是基于redisObject实现的 redisObjec ...
- Vue 项目实战系列 (三)
我们继续前两节的开发.本节教程实现的效果如下: 效果很简单,但是实现起来却要用到Vue的很多知识,下面我们将一步一步的实现这个效果. 首先这些城市的信息都是从后台的server里面获取的,所以我们需要 ...
- sublime 设置字体
通过菜单Preferences/Settings - User,添加下面这行配置就可以修改字体: "font_face": "Courier New", &qu ...
- php 多维数组简化(递归)
<?php $a=[ 'a'=>['d'=>['aa'=>1,'bb'=>2,'cc'=>3]], 'b'=>['f'=>['dd'=>4,'ee ...
- 【Android Developers Training】 0. 序言:构建你的第一个应用
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- Maven pom.xml配置详解
POM的全称是“ProjectObjectModel(项目对象模型)”. 声明规范 <projectxmlns="http://maven.apache.org/POM/4.0.0&q ...
- .net入门 - Get Started with .NET
阅读原文 有很多种方式去开始使用.net.因为.net是一个巨大的平台,在这个文档里面有很多文章,告诉你如何从不同的角度去开始使用.net. 使用.NET的语言入门 C#入门文章和C#教程提供了以C# ...
- Unity3D中使用BMFont制作图片字体 (NGUI版)
[旧博客转移 - 发布于2015年9月10日 16:07] 有时美术会出这种图片格式的文字,NGUI提供了UIFont来支持BMFont导出的图片字体 BMFont原理其实很简单,首先会把文字小图拼成 ...
- Struts框架之 执行流程 struts.xml 配置详细
1.执行流程 服务器启动: 1. 加载项目web.xml 2. 创建Struts核心过滤器对象, 执行filter → init() struts-default.xml, 核心功能的初 ...
- SQL Server Alwayson配置两个节点加共享文件夹仲裁见证
标签:MSSQL/节点和共享文件夹多数 概述 之前讲过多数节点的仲裁配置,多数节点一般3个节点以上的奇数个节点:常见的是使用3个节点节点多了也是浪费因为Alwayson的只读路由只能利用到一个只读副本 ...