美文网首页
iOS面试题

iOS面试题

作者: 阿凡提说AI | 来源:发表于2017-11-06 23:01 被阅读27次

1.MVC、MVP、MVVM的区别?
MVC:

View上面显示什么东西,取决于Model。
只要Model数据改了,View的显示状态也会跟着更改。
Controller负责初始化Model,并将Model传递给View去解析展示。

MVVM:

M:模型,负责数据的存储。
V:View和ViewController
VM:ViewModel,专门负责数据请求、业务逻辑等业务。

MVP:

M、V与上相同。
Presenter:作为model和view的中间人,从model层获取数据之后传给View,使得View和model有更强的复用性。

2.自动布局有哪些?
(1)Autolayout
1)约束和参照
2)代码实现
要先禁止autoresizing功能,设置view的下面属性为NO.

view.translatesAutoresizingMaskIntoConstraints = NO;
// 添加高度约束
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:buleView relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:40];

自动布局核心计算公式
obj1.property1 = (obj2.property2*multiplier)+constant value
3)VFL语言

H:[cancelButton(72)] - 12 - [acceptButton(50)]
H:[wideView(>=60@700)]
V:[redBox][yellowBox(==redBox)]

(2)Masonry:
约束的类型:
1.尺寸:width\height\size
2.边界:left\leading\right\trailing\top\bottom
3.中心点:center\centerX\centerY
4.边界:edges

[blueView mas_makeConstraints:^(MASConstarintMake *make){
      // 宽度约束
      make.width.equalTo(@100);
      // 宽度约束
      make.height.equalTo(@100);
      // 右边
      make.right.equalTo(self.view.mas_right).offset(-20);
      // 顶部
      make.top.equalTo(self.view.mas_top).offset(20);
}

// 这个方法会将以前的所有约束删除,添加新的约束
[blueView mas_remakeConstraints^(MASConstraintMaker *make){
        
}

// 这个方法将会覆盖以前的某些特定的约束
[blueView mas_updateConstraints^(MASConstraintMaker *make){
        
}

(3)SDAutolayout

_view.sd_layout.leftSpaceToView(self.view,10).topSpaceToView(self.view,80),heightIs(130).widthRatioToView(self.view,0.4);
_label.sd_layout.autoHeightRadio(0);

tableView高度自适应设置3步:
1)cell布局设置之后调用以下方法就可以实现高度自适应(注意:如果用高度自适应则不要再以cell的底边去参考布局其子view)

[cell setupAutoHeightWithBottomView:_view4 bottomMargin:10];

2)获取自动计算出cell的高度

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
      id model = self.modelsArray[indexPath.row];
      // 获取cell高度
      return [self.tableView cellHeightForIndexPath:indexPath model:model  keyPath:@"model"  cellClass:[DemoVC9Cell class] contentViewWidth:cellContentViewWidth];

}

3.切换分支

git checkout -b branch1 origin/branch1

4.递归函数
(1)必须有一个明确的结束标志
(2)自己调用自己

// 设置一个函数用来计算B的n次方

int myPow2(int base,int n)
{
      int result = 1;
      if(n<0){
            //结束标志
            return result;
      }else{
          return myPow2(base,n-1)*base;
     }

}

5.代码冲突解决方法
(1)代码文件冲突
当代码文件冲突时,是可以打开xcode的,然后逐个解决就行。

<<<<<<<<<<<<HEAD
================
>>>>>>>>>>>>masterDv

<<<<<<<<<<<<HEAD与================之间是本地的代码。
================与>>>>>>>>>>>>masterDv之间是对方的代码
根据情况来删除
(2)配置文件冲突
当配置文件冲突时,打不开xcode,这时需要进行项目文件夹xxx.xcodeproj打开project.pbxproj,然后逐个解决即可。
6.九宫格的思路
核心点就是算x,y。控制在第index/cols行,第index%cols列。(cols列数)。

// 每一列之间的间距
CGFloat colMargin = (self.shopView.frame.size.width - cols*shopW)/(cols - 1);
// 每一行的间距
CGFloat rowMargin = 10;
X值:NSUInterger col = index%cols;
CGFloat shopX = col*(shopW +colMargin);
Y值:NSUInteger row = index/cols;
CGFloat shopY = row*(shopH +rowHeight);

7.通知、代理、block
(1)发通知

// 发通知
NSDictionary *dic = [NSDictionary dictionaryWithObject:@"userInfo消息" forKey:@"param"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"noti3"  object:nil userInfo:dic];

// 监听
[[NSNotificationCenter defaultCenter] addObserver:self selector:(noti3:) name:@"noti3" object:nil];
// 调用方法
- (void)noti3:(NSNotification *)noti
{
        //使用userInfo处理消息
        NSDictionary *dic = [noti userInfo];
        NSString *info = [dic objectForKey:@"param"];
}

最后,记得在发送通知消息的页面,在dealloc方法里面移除观察者。

-(void)dealloc{
      [[NSNotificationCenter defaultCenter] removeObserver:self];
}

(2)代理设计模式的开发步骤
1)拟一份协议(协议名字的格式:控制名+Delegate),在协议里面生命一些代理方法。(一般代理方法都是@optional)
2)声明一个代理属性

@property(nonatomic,weak)id<代理协议>delegate;

3)在内部发生某种行为时,调用代理对应的代理方法,通知代理发生什么事。
4)设置代理:xxx.delegate = yyy;
5)yyy对象准守协议,实现代理方法。
(3)block逆向传值
A文件(用来保存block代码)

addVc.block = ^(Contact *contact){
          //1.联系人添加到数组
          [self.contacts addObject:contact];
          //2.刷新表格
          [self.tableView reloadData];
}

B文件:(逆传)
.h文件

typedef void(^AddViewControllerBlock)(Contact *contact);
@property(nonatomic,strong)AddViewControllerBlock block;

.m文件

//0.把文本框的值包装包装成模型人模型
Contact *c = [Contact contactWithName:_nameField.text phone:_phoneField.text];

// 1.把联系人添加到联系人控制器的数组,让联系人刷新表格
if(_block){
  _block(c);
}

// 2.回到联系人控制器
[self.navigationController popViewControllerAnimated:YES];

8.支付的过程
(1)首先从自己的服务器获取商品列表
(2)通过商品数据请求生成订单接口。
(3)根据生成订单接口返回的数据,调用ping++的api
(4) 在支付宝或微信进行支付
(5)API调用成功之后再通过服务器返回的数据判断交易状态。
9.瀑布流
XMGWaterflowLayout.h

#import <UIKit/UIKit.h>

@interface XMGWaterflowLayout : UICollectionViewLayout

@end

XMGWaterflowLayout.m

#import "XMGWaterflowLayout.h"

/** 默认的列数 */
static const NSInteger XMGDefaultColumnCount = 3;
/** 每一列之间的间距 */
static const CGFloat XMGDefaultColumnMargin = 10;
/** 每一行之间的间距 */
static const CGFloat XMGDefaultRowMargin = 10;
/** 边缘间距 */
static const UIEdgeInsets XMGDefaultEdgeInsets = {10, 10, 10, 10};

@interface XMGWaterflowLayout()
/** 存放所有cell的布局属性 */
@property (nonatomic, strong) NSMutableArray *attrsArray;
/** 存放所有列的当前高度 */
@property (nonatomic, strong) NSMutableArray *columnHeights;
@end

@implementation XMGWaterflowLayout

- (NSMutableArray *)columnHeights
{
    if (!_columnHeights) {
        _columnHeights = [NSMutableArray array];
    }
    return _columnHeights;
}

- (NSMutableArray *)attrsArray
{
    if (!_attrsArray) {
        _attrsArray = [NSMutableArray array];
    }
    return _attrsArray;
}

/**
 * 初始化
 */
- (void)prepareLayout
{
    [super prepareLayout];

    // 清除以前计算的所有高度
    [self.columnHeights removeAllObjects];
    for (NSInteger i = 0; i < XMGDefaultColumnCount; i++) {
        [self.columnHeights addObject:@(XMGDefaultEdgeInsets.top)];
    }

    // 清除之前所有的布局属性
    [self.attrsArray removeAllObjects];
    // 开始创建每一个cell对应的布局属性
    NSInteger count = [self.collectionView numberOfItemsInSection:0];
    for (NSInteger i = 0; i < count; i++) {
        // 创建位置
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
        // 获取indexPath位置cell对应的布局属性
        UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];
        [self.attrsArray addObject:attrs];
    }
}

/**
 * 决定cell的排布
 */
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    return self.attrsArray;
}

/**
 * 返回indexPath位置cell对应的布局属性
 */
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    // 创建布局属性
    UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

    // collectionView的宽度
    CGFloat collectionViewW = self.collectionView.frame.size.width;

    // 设置布局属性的frame
    CGFloat w = (collectionViewW - XMGDefaultEdgeInsets.left - XMGDefaultEdgeInsets.right - (XMGDefaultColumnCount - 1) * XMGDefaultColumnMargin) / XMGDefaultColumnCount;
    CGFloat h = 50 + arc4random_uniform(100);

    // 找出高度最短的那一列
//    __block NSInteger destColumn = 0;
//    __block CGFloat minColumnHeight = MAXFLOAT;
//    [self.columnHeights enumerateObjectsUsingBlock:^(NSNumber *columnHeightNumber, NSUInteger idx, BOOL *stop) {
//        CGFloat columnHeight = columnHeightNumber.doubleValue;
//        if (minColumnHeight > columnHeight) {
//            minColumnHeight = columnHeight;
//            destColumn = idx;
//        }
    //    }];

    // 找出高度最短的那一列
    NSInteger destColumn = 0;
    CGFloat minColumnHeight = [self.columnHeights[0] doubleValue];
    for (NSInteger i = 1; i < XMGDefaultColumnCount; i++) {
        // 取得第i列的高度
        CGFloat columnHeight = [self.columnHeights[i] doubleValue];

        if (minColumnHeight > columnHeight) {
            minColumnHeight = columnHeight;
            destColumn = i;
        }
    }

    CGFloat x = XMGDefaultEdgeInsets.left + destColumn * (w + XMGDefaultColumnMargin);
    CGFloat y = minColumnHeight;
    if (y != XMGDefaultEdgeInsets.top) {
        y += XMGDefaultRowMargin;
    }
    attrs.frame = CGRectMake(x, y, w, h);

    // 更新最短那列的高度
    self.columnHeights[destColumn] = @(CGRectGetMaxY(attrs.frame));

    return attrs;
}

- (CGSize)collectionViewContentSize
{
    CGFloat maxColumnHeight = [self.columnHeights[0] doubleValue];
    for (NSInteger i = 1; i < XMGDefaultColumnCount; i++) {
        // 取得第i列的高度
        CGFloat columnHeight = [self.columnHeights[i] doubleValue];

        if (maxColumnHeight < columnHeight) {
            maxColumnHeight = columnHeight;
        }
    }
    return CGSizeMake(0, maxColumnHeight + XMGDefaultEdgeInsets.bottom);
}

@end

ViewController.m

#import "ViewController.h"
#import "XMGWaterflowLayout.h"

@interface ViewController () <UICollectionViewDataSource>

@end

@implementation ViewController

static NSString * const XMGShopId = @"shop";

- (void)viewDidLoad {
    [super viewDidLoad];

    // 创建布局
    XMGWaterflowLayout *layout = [[XMGWaterflowLayout alloc] init];

    // 创建CollectionView
    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
    collectionView.dataSource = self;
    [self.view addSubview:collectionView];

    // 注册
    [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:XMGShopId];
}
#pragma mark - <UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 50;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:XMGShopId forIndexPath:indexPath];

    cell.backgroundColor = [UIColor orangeColor];

    NSInteger tag = 10;
    UILabel *label = (UILabel *)[cell.contentView viewWithTag:tag];
    if (label == nil) {
        label = [[UILabel alloc] init];
        label.tag = tag;
        [cell.contentView addSubview:label];
    }

    label.text = [NSString stringWithFormat:@"%zd", indexPath.item];
    [label sizeToFit];

    return cell;
}
@end

10.oc与js的交互
(1)在oc中执行js代码:
webViewDidFinishLoad方法中

[webView stringByEvaluatingJavaScriptFromString:str1];

(2)在网页中执行OC的方法

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    NSString *str = request.URL.absoluteString;
    NSRange range = [str rangeOfString:@"xmg://"];
    if (range.location != NSNotFound) {
        NSString *method = [str substringFromIndex:range.location + range.length];
        NSLog(@"%@", method);
       SEL sel = NSSelectorFromString(method);
       [self performSelector:sel];
    }
    return YES;
}

11.本地化存储
(1)属性列表
(2)偏好设置
(3)归档

遵循NSCoding协议
- (void)encodeWithCoder:(NSCoder *)encode{
      [encode encodeObject:self.name forKey:@"name"];
}

-  (id)initWithCoder:(NSCoder*)decode{
    self.name = [decode decoderObjectForkey];
}

(4)FMDB

1)  获取数据库对象
2)打开数据库,如果不存在,则创建并且打开。
3)创建表
4)插入数据
5)查询数据

12.性能优化
(1)首页启动速度

1)启动过程中做的事情越少越好
2)不在UI线程做耗时的操作

(2)页面浏览速度

1)数据的分页
2)   内容缓存
3)延时加载tab(比如app有5个tab,可以先加载第一个显示的tab,其他的在显示时候加载)
4)算法的优化(联系人姓名用汉语拼音的首字母排序)

相关文章

网友评论

      本文标题:iOS面试题

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