美文网首页
2018-12-22

2018-12-22

作者: 零度_不结冰 | 来源:发表于2018-12-22 15:12 被阅读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

    相关文章

      网友评论

          本文标题:2018-12-22

          本文链接:https://www.haomeiwen.com/subject/ztiikqtx.html