2018-12-22

2018-12-22  本文已影响9人  零度_不结冰

iOS面试题总结

https://www.jianshu.com/p/1798ba01e9ef

1、iOS 应用导航模式有哪些?

平铺模式,一般由scrollView和pageControl组合而成的展示方式。手机自带的天气比较典型。

标签模式,tabBar的展示方式,这个比较常见。

树状模式,tableView的多态展示方式,常见的9宫格、系统自带的邮箱等展现方式。

2、iOS 中持久化方式有哪些?

属性列表文件-- NSUserDefaults的存储,实际是本地生成一个plist文件,将所需属性存储在plist文件中

对象归档 -- 本地创建文件并写入数据,文件类型不限

SQLite 数据库 -- 本地创建数据库文件,进行数据处理

CoreData -- 同数据库处理思想相同,但实现方式不同

iOS单元测试框架有哪些

OCUnit是OC官方测试框架,现在被XCTest所取代。

XCTest是与Foundation框架平行的测试框架。

GHUnit是第三方的测试框架。github地址

OCMock都是第三方的测试框架。github地址

ios7 层协议,tcp四层协议及如何对应的?

5、iOS 你在项目中用过 runtime 吗?举个例子

Objective-C 语言是一门动态语言,编译器不需要关心接受消息的对象是何种类型,接收消息的对象问题也要在运行时处理。

pragramming层面的runtime主要体现在以下几个方面:

关联对象Associated Objects 

消息发送Messaging 

消息转发Message Forwarding 

方法调配Method Swizzling 

“类对象”NSProxyFoundation | Apple Developer Documentation 

KVC、KVOAbout Key-Value Coding 

补充一个大家经常用的、但是很容易忽视的 runtime 应用吧:

动态获取 class slector

NSClassFromString(@"MyClass");

NSSelectorFromString(@"showShareActionSheet");

给分类添加属性和KVC/KVO了。

大多数情况下,我们是不会直接用 runtime 写业务代码的,所以,大部分时候,我们只会在一些平时用起来很方便的框架里面,看到有用到 runtime 的黑魔法(当然你也可以自己造轮子)。runtime 用起来的最大感受就是,底层写一堆 runtime,外面用起来超清爽!对于那些“代码艺术家”来说,简直是爽到爆。

我在项目中使用runtime比较少:

1.在category中添加属性

2.

修改系统方法,如重写objectAtIndex方法阻止数组越界崩溃。

大概说说一下自己在开发中用到的一些基于 runtime 的开源框架吧,具体应用自己可以去看看源码:

1.Aspects(AOP必备,“取缔”baseVC,无侵入埋点)

2.MJExtension(JSON转model,一行代码实现NSCoding协议的自动归档和解档)

3.JSPatch(动态下发JS进行热修复)

4.NullSafe(防止因发unrecognised messages给NSNull导致的崩溃)

5.UITableView-FDTemplateLayoutCell(自动计算并缓存table view的cell高度)

6.UINavigationController+FDFullscreenPopGesture(全屏滑动返回)

runtime 的原理和用法可以看看官方文档:

Objective-C Runtime Programming GuideInteracting with the Runtime

Objective-C Runtime Reference

About Key-Value Coding

Introduction to Key-Value Observing Programming Guide

20180212更新

在引导页上使用了runtime

.h代码如下:

#import <UIKit/UIKit.h>

@interface UIViewController(KSGuid)

//*实现引导页的控制器,外部不用调用即可实现GuidView,可以修改下面的图片*/

@end

/*这里是要展示的图片,修改即可,当然不止三个  1242 * 2208的分辨率最佳,如果在小屏手机上显示不全,最好要求UI重新设计图片*/

#define ImageArray @[@"guid01",@"guid02",@"guid03",@"guid04"]

/** pageIndicatorTintColor*/

#define pageTintColor[[UIColor whiteColor]colorWithAlphaComponent:0.5];

/** currentPageIndicatorTintColor*/

#define currentTintColor[UIColor whiteColor];

/*

如果要修改立即体验按钮的样式

重新-(UIButton*)removeBtn方法即可

*/

.m代码如下

#import "UIViewController+KSGuid.h"

#import <objc/runtime.h>

#define CollectionView_Tag 15

#define RemoveBtn_tag 16

#define Control_tag 17

#define FIRST_IN_KEY @"FIRST_IN_KEY"

@interface KSGuidViewCell : UICollectionViewCell

@property(nonatomic,copy)NSString* imageName;

@property(nonatomic,strong)UIImageView* imageView;

@end

@implementation KSGuidViewCell

-(instancetype)initWithFrame:(CGRect)frame

{

    self =[super initWithFrame:frame];

    if(self){

        _imageView =[[UIImageView alloc]initWithFrame:self.bounds];

        _imageView.contentMode = UIViewContentModeScaleAspectFill;

        _imageView.userInteractionEnabled = YES;

        [self.contentView addSubview:_imageView];

    }

    return self;

}

-(void)setImageName:(NSString *)imageName{

    if(_imageName != imageName){

        _imageName =[imageName copy];

    }

    _imageView.image =[UIImage imageNamed:imageName];

}

@end

/************************以上是KSGuidViewCell,以下才是UIViewController+KSGuid******************************/

@implementation UIViewController(KSGuid)

#pragma mark- 

#pragma mark这里是退出的按钮

-(UIButton*)removeBtn{

    //移除按钮样式

    UIButton* removeBtn =[UIButton buttonWithType:UIButtonTypeCustom];

    [removeBtn addTarget:self action:@selector(removeGuidView)forControlEvents:UIControlEventTouchUpInside];

    removeBtn.hidden =(self.imageArray.count != 1);

    removeBtn.tag = RemoveBtn_tag;      //注意这里的tag

    //***********************这里面可以自定义*******************************//

    CGFloat btnW = 128;

    CGFloat btnH = 35;

    CGFloat btnX = CGRectGetMidX(self.view.frame)- btnW / 2;

    CGFloat btnY = CGRectGetMaxY(self.view.frame)* 0.83;

    removeBtn.frame = CGRectMake(btnX,btnY,btnW,btnH);

    removeBtn.layer.cornerRadius = 4;

    removeBtn.layer.borderColor =[UIColor whiteColor].CGColor;

    removeBtn.layer.borderWidth = 1.;

    [removeBtn setTitle:@"进入婚匠" forState:UIControlStateNormal];

    [removeBtn setTitleColor:[UIColor whiteColor]forState:UIControlStateNormal];

    removeBtn.titleLabel.font =[UIFont systemFontOfSize:18.];

     //********************自定义结束**********************************//

    return removeBtn;

}

#pragma mark-

#pragma mark这里填充图片的名称

-(NSArray*)imageArray{

    return ImageArray;

}

+(void)load{

    NSString* versoin =[[[NSBundle mainBundle]infoDictionary]objectForKey:@"CFBundleShortVersionString"];

    NSString* versionCache =[[NSUserDefaults standardUserDefaults]objectForKey:FIRST_IN_KEY];

    //启动时候首先判断是不是第一次

    if([versoin isEqualToString:versionCache]){

        return;

    }

    //以下代码只在程序安装初次运行时候执行

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken,^{

        Method method1 = class_getInstanceMethod(self.class,@selector(viewDidLoad));

        Method method2 = class_getInstanceMethod(self.class,@selector(guidViewDidLoad));

        BOOL didAddMethod =

        class_addMethod(self.class,

                        @selector(viewDidLoad),

                        method_getImplementation(method2),

                        method_getTypeEncoding(method2));

        if(didAddMethod){

            class_replaceMethod(self.class,

                                @selector(guidViewDidLoad),

                                method_getImplementation(method1),

                                method_getTypeEncoding(method1));

        } else {

            method_exchangeImplementations(method1,method2);

        }

    });

}

-(void)guidViewDidLoad{

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken,^{

        //这里的代码只在程序安装初次打开,并且在第一个控制器里面执行

        //初始化视图

        [self setupSubViews];

    });

    //这是调用工程里面的viewDidLoad

    [self guidViewDidLoad];

}

#pragma mark- 

#pragma mark初始化视图

-(void)setupSubViews{

    //界面样式

    UICollectionViewFlowLayout* flowLayout =[[UICollectionViewFlowLayout alloc]init];

    flowLayout.itemSize =[UIScreen mainScreen].bounds.size;

    flowLayout.minimumLineSpacing = 0;

    flowLayout.minimumInteritemSpacing = 0;

    flowLayout.sectionInset = UIEdgeInsetsZero;

    flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;

    UICollectionView* collectionView =[[UICollectionView alloc]

                      initWithFrame:self.view.bounds

                      collectionViewLayout:flowLayout];

    collectionView.dataSource = self;

    collectionView.delegate = self;

    collectionView.pagingEnabled = YES;

    collectionView.showsVerticalScrollIndicator = NO;

    collectionView.showsHorizontalScrollIndicator = NO;

    collectionView.backgroundColor =[UIColor whiteColor];

    [collectionView registerClass:[KSGuidViewCell class]forCellWithReuseIdentifier:@"KSGuidViewCell"];

    collectionView.tag = CollectionView_Tag;

    [self.view addSubview:collectionView];

    [self.view addSubview:self.removeBtn];

    UIPageControl* control =[[UIPageControl alloc]init];

    CGFloat controlW = 170;

    CGFloat controlH = 20;

    CGFloat controlX = CGRectGetMidX(self.view.frame)- controlW / 2;

    CGFloat controlY = CGRectGetMaxY(self.view.frame)- 38;

    control.frame = CGRectMake(controlX,controlY,controlW,controlH);

    control.numberOfPages = ImageArray.count;

    control.pageIndicatorTintColor = pageTintColor;

    control.currentPageIndicatorTintColor = currentTintColor;

    control.tag = Control_tag;

    [self.view addSubview:control];

}

#pragma mark-

#pragma mark UICollectionViewDataSource

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{

    return self.imageArray.count;

}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

    KSGuidViewCell* cell =[collectionView dequeueReusableCellWithReuseIdentifier:@"KSGuidViewCell" forIndexPath:indexPath];

    cell.imageName = self.imageArray[indexPath.row];

    return cell;

}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{

    NSUInteger index = scrollView.contentOffset.x / CGRectGetWidth(self.view.frame);

    [self.view viewWithTag:RemoveBtn_tag].hidden =(index != self.imageArray.count - 1);

    UIPageControl* control =[self.view viewWithTag:Control_tag];

    control.currentPage = index;

}

-(void)removeGuidView{

    NSString* versoin =[[[NSBundle mainBundle]infoDictionary]objectForKey:@"CFBundleShortVersionString"];

    [[NSUserDefaults standardUserDefaults]setObject:versoin forKey:FIRST_IN_KEY];

    [[NSUserDefaults standardUserDefaults]synchronize];

    [[self.view viewWithTag:Control_tag]removeFromSuperview];

    [[self.view viewWithTag:RemoveBtn_tag]removeFromSuperview];

    [[self.view viewWithTag:CollectionView_Tag]removeFromSuperview];

}

@end

6、iOS 什么是ARC?

7、iOS 说明并比较关键词:atomatic, nonatomic

上一篇下一篇

猜你喜欢

热点阅读