美文网首页
面试题集锦2(更新)

面试题集锦2(更新)

作者: 彼岸的黑色曼陀罗 | 来源:发表于2016-09-18 22:00 被阅读0次

    1.xcode5和xcode7区别

    • 1.xcode7没有Frameworks文件夹,xcode7内部会自动帮你导入一些常见的框架.
    • 2.xcode7多了LaunchScreen.xib,LaunchScreen.xib设置启动界面,而且可以确定模拟器或者真机的真实尺寸,如果没有设置,默认4s的尺寸(320,480)
    • 3.xcode7没有pch文件
    • 4.xcode5当中也有info.plist,只不过它的名字很长.是工程的名称.

    2.pch文件原理

    • 会把pch里面的所有内容导入到每个文件中去

    3.UIApplication常见功能

    • 1.设置应用提醒数字
    • 2.设置连网状态
    • 3.设置状态栏
    • 4.跳转网页

    4.程序完整启动流程

    • 1.执行Main
    • 2.执行UIApplicationMain函数.
    • 3.创建UIApplication对象,并设置UIApplicationMain对象的代理.
      UIApplication的第三个参数就是UIApplication的名称,如果指定为nil,它会默认为UIApplication.
      UIApplication的第四个参数为UIApplication的代理.
    • 4.开启一个主运行循环.保证应用程序不退出.
    • 5.加载info.plist.加载配置文件.判断一下info.plist文件当中有没有Main storyboard file base name
      里面有没有指定storyboard文件,如果有就去加载info.plist文件,如果没有,那么应用程序加载完毕.

    5.UIWindow是什么?

    • UIWindow是一种特殊的UIView,通常在一个app中至少有一个UIWindow
    • iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,
    • 最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了
    • 一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow

    6.手动创建窗口的步骤

    • 1.创建窗口,要有窗口显示,必须要有强引用.窗口也是控件,要想展示出来.必须得要有尺寸.
    • 2.创建控制器
    • 3.设置控制器为窗口的根控制器
    • 4.显示窗口

    7.makeKeyAndVisable做了哪些事情?

    • 1.让窗口成为显示状态.
    • 2.把根控制器的View添加到窗口上面.
    • 3.把当前窗口设置成应用程序的主窗口

    8.如何从storyboard中加载控制器?

    • 1.加载指定的storyBoard
    • 2.加载箭头所指向的控制器.
    • 3.加载指定标识的控制器.

    9.initWithNibName的加载过程?

    • 1.如果没有指定名称.指定为nil,那么它就会去先加载跟它相同名称的Xib.
    • 2.如果没有跟它相同名称的Xib,那么它就会再去加载跟它相同名称去点Controller的名字的Xib.
    • 3.控制器的init方法会调用initWithNibName:方法.

    10.LoadView作用以及LoadView的注意点?

    • 控制器调用loadView方法创建控制器的view.
      它的默认做法是:
      • 1.先去判断当前控制器是不是从StoryBoard当中加载的,如果是,那么它就会从StoryBoard当中加载控制器的View.
      • 2.如果不是从StoryBoard当中加载的, 那么它还会判断是不是从Xib当中创建的控制器.
        如果是,那么它就会从xib加载控制器的View.
      • 3.如果也不是从Xib加载的控制器.那么它就会创建一个空的UIView.设为当前控制器的View.
    • 注意点:
      • 1.一旦重写了loadView,表示需要自己创建控制器的View.
      • 2.如果控制器的View还没有赋值,就不能调用控制器View的get方法.会造成死循环.
      • 因为控制器View的get方法底层会调用loadView方法

    11.UIPickerView是什么控件?基本用法是怎样的?

    • UIPickerView是选择控件,用来供用户选择一些城市等,他的基本用法与tableView基本相似,需要设置数据源和代理,让其展示数据

    12.KVC底层实现?

    • 拿字符串与当前类的属性进行匹配,如果匹配到,就给该属性赋值
    • [item setValue:forKeyPath:key]
    • 1.会找有没有跟key值相同名称的set方法,就会调用set方法,把obj传入
    • 2.如果说没有set方法,那么它会去找有没有相同名称,并且带有下划线的成员属性,如果有就会给该属性赋值
    • 3.如果也没有带下划线的成员属性,就看有没有跟它相同名称的成员属性,如果有就会给该属性赋值
    • 4.如果还没有跟它相同名称的成员属性,就会调用setVale:forUndefineKey:
    • 5.如果没有实现setValue:forUndefinedKey:就会直接报错

    13.导航控制器的view的结构是怎样的?

    • 导航条,导航条的高度为44,y为20
    • 专门存放栈顶控制器view的view

    14.导航控制器push做了哪些事情?

    • 当调用push方法的时候,会把要push的控制器从栈里面移除
    • 把之前导航控制器中栈顶控制器的view给移除,把当前栈顶控制器的view添加上去

    15.导航控制器pop做了哪些事情?

    • 当调用pop方法时, 会把要pop的控制器从栈里移除
    • 把之前导航控制器中栈顶控制器View给移除,把当前栈顶控制器添加上去.
    • popViewController:把当前控制器从栈中移除
    • popToRootViewControllerAnimated:把除了根控制器以外的控制器,全部从栈中移除
    • popToViewController:要返回的控制器必须要在导航控制器的子控制器当中

    16.如何设置导航条的内容?

    • 导航条的内容由导航控制器的栈顶控制器的navigationItem决定
    • 设置标题:.title
    • 设置标题视图:.titleView
    • 设置左侧样式:.leftBarButtonItem
    • 自定义view:initWithCustomView
    • 设置图片:initWithImage:

    17.导航控制器pop操作有哪些?

    • 返回到上一级
    • 返回到根控制器
    • 返回到指定的控制器

    18.文本框如何拦截用户输入?

    • 给指定的文本框,设置代理,遵守协议,实现代理方法,包括是否允许开始编辑,是否允许结束编辑,是否允许改变字符等。

    19.如何自定义键盘?

    • 继承自系统的UITextField,自定义一个键盘,设置文本框的inputView属性,把键盘定义成自己想要的view

    20.导航控制器的作用?

    • 导航控制器可以通过push/pop操作,实现控制器之间的跳转

    21.如何通过storyboard进行控制器之间的跳转?

    • 在storyBoard当中,选中一个视图, 按住Ctrol,拖一根线到指定的控制器,就可以跳转到指定的控制器

    22.控制器view的生命周期

    • loadView:加载view的时候调用
    • viewDidLoad:当控制器View加载完毕时调用
    • viewWillAppear:当控制器View即将显示时调用
    • viewWillLayoutSubviews:当控制器View即将布局子控件时调用
    • viewDidLayoutSubviews:当控制器View布局子控件完毕时调用
    • viewDidAppear:当控制器View显示完毕时调用
    • viewWillDisappear:当控制器View既将消失时调用
    • viewDidDisappear:当控制器View消失完毕时调用
    • viewDidUnload:当控制器View卸载的时候调用

    23.segue自动跳转和手动跳转有什么区别?

    • 自动跳转是通过控件拖到下一个控制器.只要一点击该控件,就会跳转,
      • 一般跳转之不需要做任何事时, 用此跳转方法
    • 手动跳转是通过控制器拖线的方式,跳转到下一个控制器.要给segue绑定标识
      • 需要手动执行方法才能跳转.

    24.UIAlertController使用步骤

    • 第一步:创建控制器:UIAlertController
    • 第二步:创建按钮:UIAlertAction
    • 第三步:添加按钮:[alertVC addAction:action];
    • 第四步:显示弹框.(相当于show操作)presentViewController:alertVC

    25.数据顺传的步骤

    • 1.要在数据接收控制器当中定义属性
    • 2.获取数据接收控制器
    • 3.给对应的属性进行赋值.

    26.代理传递的过程

    • 当一个对象发生某一件事时,想要把自己的东西传给别人.或是通知别人做某事使用代理.
    • 使用场景 上下级之间,通常是它的上一级成为它的代理.
      1.定义协议,在协议方法中,把要传的数据,写成参数
      2.定义代理属性
      3.调用代理方法
      4.设置代理
      5.遵守协议
      6.实现协议方法.

    27.如何取消tableView多余的线

    • tableView的footView为一个空白的View.

    28.在跳转之前会执行什么方法?

    • prepareForSegue方法
      在执行segue跳转之前会调用,(不论是自动型跳转, 还是手动跳转都会来到这个方法)

    29.performSegueWithIdentifier:做了哪些事情?

    • 1.会根据标识到Storyboard当中查找有没有这个标识的segue
    • 2.如果有的话,就会创建一个UIStoryboardSegue对象,
    • 3.把当前的控制器赋值给UIStoryboardSegue对象sourceViewController segue.sourceViewController = self
    • 4.创建UIStoryboardSegue箭头指向的控制器.创建完毕后.把创建的控制器给UIStoryboardSegue对象destinationViewController赋值
    • 5.调用当前控制器的prepareForSegue方法,告诉你线的准备工作已经完成.问你有没有要传递数据给目标控制器.
    • 6.等prepareForSegue执行完毕后,才去做真正的跳转 UIStoryboardSegue对象perform
      [segue perform];
      [segue.sourceViewController.navigationController pushViewController:segue.destinationViewController animated:YES];

    30.延迟执行代码方法?

    • GCD的dispatch_after方法

    31.ios当中的存储方式有哪些?

    • plist存储

    • preference偏好设置

    • NSKeyedArchive归档

    • SQLLite存储

    • CoreData存储

    32.简述ios应用沙盒的概念?

    • 每个ios应用都有自己的应用沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离

    • 应用必须待在自己的沙盒里,其他应用不能访问该沙盒

    33.沙盒目录结构

    • Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备的时候会备份该目录

    • tmp:保存应用运行时所需要的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。

    • Library

      • Caches:保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录

      • Preference:保存应用的所有偏好设置,ios的setting设置应用会在该目录中查找应用的设置信息

    34.如何获取沙盒目录?

    • NSDocumentDirectory:查找哪一个文件夹
    • NSUserDomainMask:在什么范围下查找
    • expandTilde:是否展开路径
    • NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)[0]

    35.NSUserDefaults的实现是什么存储?一般用来存什么?

    • NSUserDefaults不需要考虑文件名称跟文件的路径
    • NSUserDefaults本质就是plist存储(NSDictionary)
    • 在NSUserDefaults中,key值不能为nil
    • 在NSUserDefaults也不能存放自定义的对象
    • 一般用来存用户的一些偏好,如版本号,密码,账号等

    36.归档一般用来保存什么?使用时有哪些注意点?

    • 归档一般用来保存自定义的对象,使用归档的时候,要告诉保存的对象
    • encodeWithCoder:保存该对象的哪些属性
    • initWithCoder:询问你要读取该对象的哪些属性

    37.initWithCoder,什么时候调用?与awakeFromNib的区别?

    • initWithCoder:当开始解析一个文件的时候调用,如果一个view是从xib当中加载,当开始解析xib时会调用这个方法,在调用这个方法的时候,里面的子控件都还没有创建
    • awakeFromNib:当前对象从nib文件当中加载完结时调用,awakeFromNib调用时,说明xib加载完结了,view的大小和里面子控件的尺寸都已经知道了

    38.使用导航控制器有哪些注意点?

    • 凡是在导航控制器下的scrollView都会自动设置一个内边距64
    • 可以使用automaticallyAdjustsScrollViewInsets属性取消内边距
    • 导航条以及导航条里面的控件设置透明度是没有效果的
    • 如果不设置背景图片,会默认设置一张透明的图片
    • 只要是想要设置背景图片,必须得要使用UIBarMetricsDefault样式
    • 同一个导航控制器下,导航条只有一个

    39.UITabBarController的基本使用

    • 初始化UITabBarController控制器
    • 设置为窗口的根控制器为UITabBarController
    • 创建对应的子控制器
    • 调用UITabBarController的addChildViewController添加子控制器
    • 默认选中的是第一个添加的子控制器
    • 可以通过tabBar.selectedIndex的属性更改选中的控制器
    • 内部有多少个子控制器,底部tabBar条上就有多少个按钮
    • 每一个子控制器的view都是懒加载

    40.如何设置TabBar的内容?

    • UITabBarButton里面显示什么内容,由对应子控制器的tabBarItem属性决定
    • 设置标题
    • vc1.tabBarItem.title = @"标题1";
    • 设置提醒数字
    • vc1.tabBarItem.badgeValue = @"10";
    • 添加子控制器.
    • [tabBar addChildViewController:vc1];

    41.事件的传递过程?(掌握)

    • 当发生一个触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中
    • UIApplication会从事件队列中取出最前面的事件,交给主窗口
    • 主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件
    • 触摸事件的传递是从父控件传递到子控件
    • 如果一个父控件不能接收事件,那么它里面的子控件也不能够接收事件

    42.一个控件什么情况下不接收事件?

    • 不接收用户交互时不能够处理事件
      • userInteractionEnabled NO
    • 当一个控件隐藏的时候不能够接收事件
      • hidden YES
    • 当一个控件为透明的时候,也不能够接收事件
    • 注意:UIImageView的userInteractionEnabled默认就是NO,因此UIImageView已经它的子控件默认是不能够接收触摸事件的

    43.如何寻找最适合的view?

    • 先判断自己是否能够接收触摸事件,如果能再继续往下判断
    • 再判断触摸的当前点在不在自己身上
    • 如果在自己身上,它会从后往前遍历子控件,遍历出每一个子控件后,重复前面的两个步骤
    • 如果没有符合条件的子控件,那么他自己就是最适合的view

    44.事件的响应过程

    • 用户点击屏幕后产生的一个触摸事件,经过一系列的传递过程后,会找到最合适的视图控件来处理这个事件
    • 找到最适合的视图控件后,会调用控件的touches方法来做具体的事件处理
    • 这些touches的默认做法是将事件顺着响应者链条向上传递,将事件交给上一个响应者进行处理

    45.如何寻找上一个响应者

    • 如果当前view是控制器的view,那么控制器就是上一个响应者
    • 如果当前的view不是控制器的view,那么他的父控件就是上一个响应者
    • 在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或者消息传递给window对象进行处理
    • 如果window对象也不处理,则其将事件或消息传递给UIApplication对象
    • 如果UIApplication也不能处理该事件或消息,则将其丢弃

    46.transform带Make与不带Make的区别?

    • 带Make:是相对于最原始的形变,使用情况为只做一次形变操作
    • 不带Make:是相对于上一次的形变,使用情况为多次形变操作

    47.如何添加手势

    • 创建手势
    • 添加手势
    • 实现手势方法

    48.如何同时支持多个手势

    • 想要同时支持多个手势,要通过代理的方法
    • 设置代理,在实现是否支持允许多个手势的代理方法中,返回YES

    49.hitTest:方法的作用以及什么时候调用

    • 作用:寻找最适合的view
    • 参数:当前手指所在的点,产生的事件
    • 返回值:返回谁,谁就是最适合的view
    • 什么时候调用,只要一个事件,传递给一个控件的时候,就会调用这个控件的hitTest方法

    50.pointInSide方法的作用以及有什么注意点?

    • 作用:判断point在不在方法调用者上
    • point:必须是方法调用者的坐标系
    • 什么时候调用:hitTest方法底层会调用这个方法,判断点在不在控件上

    51.什么是图形上下文?

    • 图形上下文是用来保存用户绘制的内容状态,并决定绘制到哪个地方的.
    • 用户把绘制好的内容先保存到图形上下文,
    • 然后根据选择的图形上下文的不同,绘制的内容显示到地方也不相同,即输出目标也不相同.

    52.如何自定义UIView,步骤是什么?

    • 首先得要有上下文,有了上下文才能决定把绘制的东西显示到哪个地方去.
    • 其次就是这个上下文必须得和View相关联.才能将内容绘制到View上面.
    • 步骤:
      • 1.要先自定定UIView
      • 2.实现DrawRect方法
      • 3.在DrawRect方法中取得跟View相关联的上下文.
      • 4.绘制路径(描述路径长什么样).
      • 5.把描述好的路径保存到上下文(即:添加路径到上下文)
      • 6.把上下文的内容渲染到View

    53.DrawRect方法作用?什么时候调用?

    • DrawRect作用:专用在这个方法当中绘图的.只有在这个方法当中才能取得跟View相关联的上下文.
    • DrawRect是系统自己调用的, 它是当View显示的时候自动调用.

    54.setNeedsDisplay方法的作用

    • 当每次调用setNeedsDisplay这个方法,系统就会自动调用drawRect
    • 当我们手动调用drawRect:方法时, 它并不会给我们创建跟VIEW相关联的上下文.
    • 只有系统自动调用drawRect方法的时候才会创建跟View相关联的上下文.
    • setNeedsDisplay底层会调用DrawRect方法重绘.
    • 但是它不是立马就进行重绘.它仅仅是设置了一个重绘标志,等到下一次屏幕刷新的时候才会调用DrawRect方法.

    55.如何画文字?

    • 先创建好要画的文字
    • 使用UIKit提供的方法进行绘制.
    • 方法说明:
      • drawAtPoint:要画到哪个位置
      • withAttributes:文本的样式.
      • [str drawAtPoint:CGPointZero withAttributes:nil];

    56.如果画图片?

    • 绘制图片同样开始要先把图片素材导入.
    • AtPoint:参数说明图片要绘制到哪个位置.
    • 通过调用UIKit的方法drawAtPoint:CGPointZero方法进行绘制;
      • drawAtPoint:绘制出来的图图片跟图片的实际尺寸一样大
      • drawInRect:使用这个方法绘制出来的图片尺寸会和传入的rect区域一样大.
    • 平铺图片
      • [image drawAsPatternInRect:rect];

    57.如何使用CADisplayLink添加定时器

    • Target:哪个对象要监听方法.
    • selector:监听的方法名称.
    • CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)];
    • 想要让CADisplayLink工作,必须得要把它添加到主运行循环.
    • 只要添加到主运行循环, 跟模式没有关系
      • [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

    58.什么是上下文状态栈?

    • 上下文状态栈为内存中的一块区域,用来保存上下文当前的状态
    • 我们获取的图层上下文当中其实有两块区域:一个是存放添加的路径,一个是用来保存用户设置的状态
    • 这些状态包括线条的颜色、线宽等
    • 当我们把上下文的内容渲染到view上面的时候
    • 它会自动将设置的所有上下文状态运行到保存的路径上面显示到view上面

    59.如何保存和恢复上下文状态

    • 保存
      • CGContextSaveGState(context)
    • 恢复
      • CGContextRestoreGState(context)

    60.上下文矩阵操作有哪些?

    • 上下文的矩阵操作,就是上下文当中的路径可以进行一些形变操作

    • 平移CGContextTranslateCTM()

    • 旋转CGContextScaleCTM()

    • 缩放CGContextRotate()

    • 注意相比操作要在添加路径之前进行

    61.如何生成一张图片?

    • 开启一个图片上下文.
    • 上下文的大小和原始图片保持一样.以免图片被拉伸缩放.
    • 在上下文的上面添加一个圆形裁剪区域.圆形裁剪区域的半径大小和图片的宽度一样大.
    • 把要裁剪的图片绘制到图片上下文当中.
    • 从上下文当中取出图片.
    • 关闭上下文.

    62.如何把图片转成二进制流?

    • 把生成的图片写到桌面上.
    • 桌面都是以流的形式传递数据,所以我们要把图片转成二进流.
      • image:要转的图片
      • compressionQuality:压缩质量,1代表质量最高
      • NSData *data = UIImageJPEGRepresentation(newImage, 1);
      • 原始质量的png图片.
      • NSData *data = UIImagePNGRepresentation(newImage);
      • 把二进流写到桌面.
      • [data writeToFile:@"/Users/gaoxinqiang/Desktop/newImage.png" atomically:YES];

    63.如何把一个路径设置为裁剪区域?

    • 利用UIBezierPath设置一个矩形的裁剪区域.
    • 然后把这个路径设置为裁剪区域.
    • 把路径设为裁剪区域的方法为:
      • [path addClip];

    64.如何擦除上下文当中的某一个区域?

    获取当前的上下文.
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        把UIImageV上的图片渲染到上下文当中. 
        [self.imageV.layer renderInContext: ctx];
        设置擦除区域 
        CGContextClearRect(ctx, rect);
    

    65.如何判断点在不在某个区域当中

    判断手指当前点在不在按钮上.
            if (CGRectContainsPoint(btn.frame, point)) { 
                在按钮上.返回当前按钮 
                return btn;
            } 
    

    66.如何把图片保存到系统相册?

    • 调用方法:
    • 参数说明:
      • 第一个参数:要写入到相册的图片.
      • 第二个参数:哪个对象坚听写入完成时的状态.
      • 第三个参数:图片保存完成时调用的方法
    UIImageWriteToSavedPhotosAlbum(newImage,self,@selector(image:didFinishSavingWithError: contextInfo:),nil);
    注意:图片保存完成时调用的方法必须得是image:didFinishSavingWithError: contextInfo:
    

    67.如何从系统相册当中选择一张照片?

    弹出系统相册
        UIImagePickerController *vc = [[UIImagePickerController alloc] init];
        设置照片的来源 
        vc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
        vc.delegate = self;
        Modal出来系统相册
        [self presentViewController:vc animated:YES completion:nil];
    调用代理方法:-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
    

    68.如何办到一个图片长按的时候闪一下?

    • 先通过一个动画,把图片的alpha值改为0.
    • 在动画完成时, 立马再通过一个动画设置为1.

    69.抽取方法的思路?

    • 抽取一个方法时,要做到方法的功能单一性, 不要一个方法里面写过多的业务逻辑, 要方便适合更多场合
    • 相同的代码,写到一个方法当中 ,不同的地方当做参数传入.

    70.什么情况下自定义类?

    • 当发现系统的类没有办法瞒足自己要求时, 可以继续系统的类, 在子类当中添加属性自己的类属性.

    71.什么是CALayer?

    • CALayer我们又称它叫做层.
    • 在每个UIView内部都有一个layer这样一个属性.
    • UIView之所以能够显示,就是因为它里面有这个一个层,才具有显示的功能.
    • 我们通过操作CALayer对象,可以很方便地调整UIView的一些外观属性.
    • 可以给UIView设置阴影,圆角,边框等等…

    72.如何自定义Layer?

    • 自定义CALayer的方式创建UIView的方式非常相似.
    CALayer *layer = [CALayer layer];
    layer.frame = CGRectMake(50, 50, 100, 100);
    layer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:layer];
    

    73.UIView和CALayer都能够显示东西,该怎么选择?

    • 对比CALayer,UIView多了一个事件处理的功能。也就是说,CALayer不能处理用户的触摸事件,而UIView可以
    • 如果显示出来的东西需要跟用户进行交互的话,用UIView;
    • 如果不需要跟用户进行交互,用UIView或者CALayer都可以
    • CALayer的性能会高一些,因为它少了事件处理的功能,更加轻量级

    74.layer的CATransform3D属性是干什么用的?

    旋转
    x,y,z 分别代表x,y,z轴.
    CATransform3DMakeRotation(M_PI, 1, 0, 0);
    平移
    CATransform3DMakeTranslation(x,y,z)
    缩放
    CATransform3DMakeScale(x,y,z);
    可以通过KVC的方式进行设置属性.
    但是CATransform3DMakeRotation它的值,是一个结构体, 所以要把结构转成对象.
    NSValue *value = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 1, 0, 0)];
    [_imageView.layer setValue:value forKeyPath:@"transform.scale"];
    

    75.position和anchorPoint是CALayer的两个属性,作用?

    • 我们以前修改一个控件的位置都是能过Frame的方式进行修改.
    • 现在利用CALayer的position和anchorPoint属性也能够修改控件的位置.
    • 这两个属性是配合使用的.
      • position:它是用来设置当前的layer在父控件当中的位置的.所以它的坐标原点.以父控件的左上角为(0.0)点.
    • 两者结合使用.想要修改某个控件的位置,我们可以设置它的position点.
    • 设置完毕后.layer身上的anchorPoint会自动定到position所在的位置.

    76.什么是隐式动画?

    • 根层:UIView内部自动关联着的那个layer我们称它是根层.
    • 非根层:自己手动创建的层,称为非根层.
    • 隐式动画就是当对非根层的部分属性进行修改时, 它会自动的产生一些动画的效果.
    • 我们称这个默认产生的动画为隐式动画.

    77.如何获取当前时间?

    • 创建日历类
      • NSCalendar *calendar = [NSCalendar currentCalendar];
    • 把日历类转换成一个日期组件
    • 日期组件(年,月,日,时,分,秒)
      • component:日期组件有哪些东西组成,他是一个枚举,里面有年月日时分秒
      • fromDate:当前的日期
      • NSDateComponents *cmp = [calendar components:NSCalendarUnitSecond fromDate:[NSDate date]];
    • 我们的秒就是保存在日期组件里面,它里面提供了很多get方法.
      • NSInteger second = cmp.second;

    78.ios中所有的旋转和缩放都是绕着哪个点进行的?

    • ios中所有的旋转与缩放都是绕着锚点进行的
    • 只要修改锚点,就会让旋转,与缩放的点发生变化.

    79.CoreAnimation的使用步骤

    • 1.初始化一个CAAnimation对象,并设置一些动画相关属性
    • 2.通过调用CALayer的addAnimation:forKey:方法增加CAAnimation对象到CALayer中,这样就能开始执行动画了
    • 3.通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画

    80.UIView和核心动画对比?

    • 1.UIView和核心动画区别?
      • 核心动画只能添加到CALayer
      • 核心动画一切都是假象,并不会改变真实的值。
    • 2.什么时候使用UIView的动画?
      • 如果需要与用户交互就使用UIView的动画.
      • 不需要与用户交互可以使用核心动画
    • 3.什么场景使用核心动画最多?
      • 在转场动画中,核心动画的类型比较多
      • 根据一个路径做动画,只能用核心动画(帧动画)
      • 动画组:同时做多个动画

    81.如何让按钮成为选中状态?取消按钮的高亮状态?

    • 1.在添加按钮时,给每一个按钮添加选中状态
      • 添加按钮事件的时候要注意,如果按钮添加到UIImageView上的,UIImageView默认是不接收事件的,所以需要手动把UIImageView设置为可接收事件
    • 2.让按钮成为选中状态
      • 在事件处理方法当中,我们要先定义一个成员属性记录上一个按钮的选中状态
      • 先把上一个按钮的选中状态取消选中
      • 把当前点击的按钮设置为选中状态
      • 把当前的按钮赋值给上一个按钮
    • 3.取消按钮的高亮状态
      • 自定义按钮
      • 重写按钮的setHighlighted:方法

    82.如何从一张大图当中截取某一部分为图片?

    • 首先要确定裁剪的区域,即每一张图片的宽高
      • 每一张图片的高度,为原始图片的高度
      • 每一张图片的宽度,为整个图片的宽度除以总共需要裁剪的图片的数量。
    • 方法:CGImageCreateWithImageInRect(image,rect)
      • image:为要裁剪的图片(原始图片),它的类型为CGImageRef类型,所以要转成CGImage
      • rect:为裁剪的范围,这时需要确定每一个x的位置
        • 每一个x为当前的角标*要裁剪的宽度
      • 这个方法它会返回一个图片,图片类型为CGImageRef image,所以要在设置背景图片的时候,要把这张图片给转成UIImage
      • 转化的方法:UIImage *image = [UIImage imageWithCGImage:image]

    83.如何让一张图片只显示上半部分或者下半部分?

    • 利用CALayer的一个属性 contentsRect = CGRectMake(0,0,1,0.5)

      • contentsRect就是要显示的范围,它的取值范围是0~1
    • 想让上部图片只显示上半部分contentsRect设置CGRectMake(0,0,1,0.5)

    • 下半部分图片只显示下半部分contentsRect设置为CGRectMake(0,0.5,1,0.5)

    84.如何设置渐变效果?

    • 我们可以通过CAGradientLayer这个层来创建渐变,这个层我们就称它是一个渐变层。

    • 渐变层也是需要添加到一个层上面才能够显示

    • 渐变层里面有一个colors属性,这个属性就是设置要渐变的颜色,他是一个数组,数组当中要求我们传入CGColorRef类型,所以我们要把颜色转成CGColor,但是转成CGColor后,数组就认识它是一个对象了,就要通过在前面加上一个(id)来告诉编译器是一个对象

    • 设置渐变的方向

      • startPoint
      • endPoint
      • 取值范围0~1
    • 默认方向为上下渐变

      • startPoint = CGPointMake(0,0)
      • endPoint = CGPointMake(0,1)
    • 设置左右渐变

      • startPoint = CGPointMake(0,0)
      • endPoint = CGPointMake(1,0)

    85.在手指拖动的过程当中,松开手指时,有一个动画反弹回去的效果是如何做到的?

    • [UIView animateWithDuration:0.8 delay:0 usingSpringWithDamping:0.1 initialSpringVelocity:0
      options:UIViewAnimationOptionCurveLinear
      animations:^{
      动画执行代码
      } completion:^(BOOL finished) {
      动画完成时调用.
      }];

      • Duration:动画的执行时长
      • delay:动画延时时长.
      • Damping:动画的弹性系数,越小,弹簧效果越明显
      • initialSpringVelocity:弹簧初始化速度

    86.如何使用复制层?

    • 添加复制层,首先先要让这个层显示出来
    • 复制层必须加到一个层里面才能够复制它的子层
    • 不需要设置它的尺寸,需要设置它的颜色,子层超过父层也能够显示,所以不用设置尺寸
    • CAReplicatorLayer *replicator = [CAReplicatorLayer layer];
    • 将复制层添加到_contententView.layer
      • [_contentsView.layer addSublayer:replicator];

      • instanceCount:表示原来层中的所有子层复制的份数

      • replicator.instanceCount = 2;

      • 在复制层中添加子层
        [replicator addSublayer:layer];

    87.如何使用形状图层?

    • 形式为
    - (CAShapeLayer *)shape{
       if(_shape == nil){
       //创建形状图层
       CAShapeLayer *shape = [CAShapeLayer layer];
       //设置形状图层的填充颜色
       shape.fillColor = [UIColor redColor].CGColor;
       self.shape = shape;
       //把形状图层添加到当前按钮的父层当中
       [self.superview.layer insertSublayer:shape atIndex:0];
       _shape = shape;
       }
       return _shape;  
    }
    

    88.拖动的时候如何让它有一个立体的效果?

    • 立体的效果就是有一种近大远小的感觉.
    • 想要设置立体效果.要修改它的TransForm当中的一个M34值,设置方式为弄一个空的TransFrom3D
    • CATransform3D transform = CATransform3DIdentity;
      • transform.m34 = - 1 / 200.0;
      • 200.0可以理解为,人的眼睛离手机屏幕的垂直距离,近大远小效果越明显
    • transform = CATransform3DRotate(transform, angle, 1, 0, 0);
    • 相对上一次改了m34的形变,再去旋转

    89.如何通过layer改变UIView的外观?

    • 默认图层是有阴影的, 只不过,是透明的

      • _RedView.layer.shadowOpacity = 1;
    • 设置阴影的圆角

      • _RedView.layer.shadowRadius =10;
    • 设置阴影的颜色,把UIKit转换成CoreGraphics框架,用.CG开头

      • _RedView.layer.shadowColor = [UIColor blueColor].CGColor;
    • 设置边框

    • 设置图层边框,在图层中使用CoreGraphics的CGColorRef

      • _RedView.layer.borderColor = [UIColor whiteColor].CGColor;
      • _RedView.layer.borderWidth = 2;
    • 设置圆角

    • 图层的圆角半径,圆角半径为宽度的一半, 就是一个圆

      • _RedView.layer.cornerRadius = 50;
    • 操作layer改变UIImageView的外观.

    • 设置图形边框

      • _imageView.layer.borderWidth = 2;
      • _imageView.layer.borderColor = [UIColor whiteColor].CGColor;

    90.position和anchorPoint如何使用?

    • 这两个属性是配合使用的.
      • position:它是用来设置当前的layer在父控件当中的位置的.
      • 所以它的坐标原点.以父控件的左上角为(0.0)点.
      • anchorPoint:它是决点CALayer身上哪一个点会在position属性所指的位置
      • anchorPoint它是以当前的layer左上角为原点(0.0)
      • 它的取值范围是0~1,它的默认在中间也就是(0.5,0.5)的位置.
      • anchorPoint又称锚点.就是把锚点定到position所指的位置.

    91.为什么要自定义类?

    • 当发现系统的类无法满足我们的需求的时候,想要在系统的功能上添加一些自己的功能,这个时候就可以自定义类
      • 新建一个类,继承自系统的类,添加一些属于自己的功能
      • 比如在做画板的时候,自定义了UIBeizierPath
    • 想要让代码的结构更加清晰,便于阅读(做到谁的事情谁管理)

    92.自定义tabBar的实现思路

    • 把系统的tabBar移除
    • tabBar中的按钮个数,和按钮显示什么样的图片由外界决定
    • 外界传入一个数组,数组中存放的都是UITabBarItem模型,有多少个模型就创建多少个按钮,并设置内容

    93.Block作用?

    • 保存一段代码

    94.Block的定义方式?

    返回值类型(^Block名称)(参数) = ^(参数){
       保存的代码
    }
    

    95.Block如何当做参数传递?

    • 当发现某一块的功能变化的时候,其他地方没有变化,此时,可以把变化的地方利用block的方式,当做参数传入。

    96.如何进行解耦?

    • 第一种方式:代理
    • 第二种方式:block

    97.如何自定义遮盖?

    • 自定义的遮盖是显示到最外面的,显示到最外面的东西,我们要添加到主窗口上
    • 通过UIApplication的keyWindow拿到应用程序的窗口,把遮盖添加到窗口显示出来

    98.如何显示与隐藏pop菜单?

    • 显示pop的方式,提供显示到某一个点的方法,同样是添加到窗口上面,提供隐藏到某一个点的方法
    • 通过动画的方式进行隐藏,隐藏完毕的时候,通过block方式传入,由外界决定做什么事情。

    99.如何全局修改导航条的属性?

    • 通过Appearance的方式拿到整个应用程序的导航条
    • 获取指定类下的导航条
      • UINavigationBar * bar = [UINavigationBar appearanceWhenContainedInstancesOfClasses:@[self class]];

    100.分类中如何添加属性,应该注意哪些?

    • 分类当中如果要添加属性的话,就必须要实现该属性的set与get方法,如果不写的话,要自动生成get、set方法
    • 在分类中,使用@property不会生成带有下划线的成员属性,只会声明它的set和get方法

    101.initialize

    • initialize 当前类或者子类第一次使用的时候调用
    • 如果子类也写了initialize方法,那么会先调用父类的initialize方法,再调用子类的initialize;如果子类没有写initialize,那么会调用两次父类的initialize,可以根据[self class]判断是谁先调用的
      • [self class]和[super class] 是同一个对象
      • super是优先找它父类的方法
    • initialize不只调用一次

    102.字符串是用strong还是用copy

    • 理论上应该用copy,但是在实际开发中由于字符串大多是不可变的,所有常用strong修饰

    • 为什么用copy?

      • 外界修改时,不会影响里面的值
    • 为什么声明为copy时不会影响到里面的值?

      • 使用copy时会生成新的内存地址,使用strong的时候,用的是同一个内存地址
    • copy的set方法是怎么写的?

        - (void) setName:(NSString *)name{
        _name = [name copy]
        }   
    
    • 当使用的是不可变字符串的时候,是不会生成新的内存地址的
    • 如果是不可变的字符串当使用copy的时候,它会多做一次判断,判断是否为可变
    • 在开发当中使用的字符串大多数是不可变的,比如从网络加载的字符串大多是不可变的,plist中的字符串也是不可变的
    • 所以不可变的字符串使用strong性能会好一些。

    103.如何通过代码拉伸图片?

    //取出背景图片
    UIImage *image = self.loginBtn.currentBackgroundImage;
    //拉伸图片的中间区域
    UIImage * stretchImage = [image stretchImageWithLeftCapWidth:image.size.width *0.5 topCapHeight:image.size.height *0.5]
    [self.loginBtn setBackgroundImage:stretchImage forState:UIControlStateNormal]
    

    104.static关键字的作用?

    • 函数(方法)体内,static变量的作用范围为该函数体,该变量的内存只被分配一次,因此其值在下次调用的时候仍维持在上次的值
    • 在模块内的static全局变量可以被模块内所有函数访问,但不能被模块外其他函数访问
    • 在模块内的static函数只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内;
    • 在类中static 成员变量属于属于整个类拥有,对类的所有对象只有一份拷贝
    • 在类中的static成员函数属于整个类所拥有,这个函数不接受指针,因而只能访问类的static成员变量

    105.如何全局修改返回按钮?

    - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (self.childViewControllers.count != 0) {
             NSLog(@"非根控制器");
            //设置返回按钮
            viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageWithOriImageName:@"NavBack"] style:0 target:self action:@selector(back)];
            
            //重写了系统返回,那么系统的侧滑返回功能就会失效
            self.interactivePopGestureRecognizer.delegate = nil;
            
            //当push时隐藏系统底部Tabbar
            viewController.hidesBottomBarWhenPushed = YES;
        }
    [super pushViewController:viewController animated:animated];
    }
    

    106.如何恢复侧滑返回功能?

    • 侧滑返回是一个手势,重写返回按钮的时候,侧滑返回手势会通过它的代理,不去做任务事情
    • 把系统的侧滑返回手势的代理清空
    • 清空手势代理带来的问题
    • 当是根控制器的时候,还要把侧滑返回的手势代理给设置回去

    107.如何添加全屏幕滑动返回?

    • 给导航控制器的view添加拖动手势
    • 让拖动手势的事件调用系统的侧滑返回方法

    108.通过scrollView实现无限轮播思路?

    1.确定图片的宽度等于scrollViewW
    2.设置scollView 的contentSize (3 * W,H)
    3.把scollView的offset.x设置为一个W
    4.创建两个imageV, centerImageV * reuseImageV
    5.设置centerImageV .x = W
    6. reuseImageV.x =  maxX(centerImageV .frame)
    7.当scorllView滚动时,判断offset.x是否大于2 * W
       立马把offset.x设置为W
    交换两个ImageView的位置
    8.交换两个指针
    

    109.UICollectionViewController使用的注意点?

    • 创建CollectionViewController必须得要初始化一个布局参数
    • UICollectionViewCell必须得要自己手动去注册
    • UICollectionViewCell默认内部并没有子控件,需要我们手动的去添加,自定义cell

    110.流水布局属性有哪些?

     //流水布局
        UICollectionViewFlowLayout *flowL = [[UICollectionViewFlowLayout alloc] init];
        //设置每一个格子的大小
        flowL.itemSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
        //设置最小行间距
        flowL.minimumLineSpacing = 0;
        //设置每个格子之间的间距
        flowL.minimumInteritemSpacing = 0;
        
        //设置滚动的方向
        flowL.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    

    111.initialize方法的作用?

    • 该方法是当前类或者它的子类第一次使用的时候会调用

    112.新特性业务逻辑是怎样的?

    • 获取当前软件的版本号
    • 判断当前版本是否与之前的版本相同
    • 相同,跳到程序的主框架
    • 不同,跳到新特性,保存当前的版本号

    113.如何切换根控制器?

    • 点击立即体验按钮的时候,跳转到程序的主框架
    • 新特性界面已经不需要出现了,新特性界面现有窗口的根控制器强引用
    • 所以把窗口的根控制器指向程序的主框架,新特性界面就会被释放掉

    114.为什么要抽取业务类?

    • 让代码具有更强的扩展性
    • 让代码的结构更加的清晰
    • 减少第三方框架对程序的污染

    115.KVO内部实现原理?

    • KVO是基于runtime机制实现的
    • 当某个类的属性对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter 方法。派生类在被重写的setter方法内实现真正的通知机制
    • 如果原类为Person,那么生成的派生类名为NSKVONotifying_Person
    • 每个类对象中都有一个isa指针指向当前类,当一个类对象的第一次被观察,那么系统会偷偷将isa指针指向动态生成的派生类,从而在给被监控属性赋值时执行的是派生类的setter方法
    • 键值观察通知依赖于NSObject 的两个方法: willChangeValueForKey: 和 didChangevlueForKey:;在一个被观察属性发生改变之前, willChangeValueForKey: 一定会被调用,这就 会记录旧的值。而当改变发生后,didChangeValueForKey: 会被调用,继而 observeValueForKey:ofObject:change:context: 也会被调用。

    116.如何把一个字符串转成类名?

    NSClassFromString(<#NSString * _Nonnull aClassName#>) 通过类型,就可以去创建一个对象.
    

    117.block使用的注意点有哪些?

    • 在使用block前需要对block指针做判断处理
    • 在MRC的编译环境下,block如果作为成员参数要copy一下将栈上的block拷贝到堆上
    • 在block使用之后要对block指针做赋空值处理,如果是MRC的编译环境下,要先release掉block对象,block作为类对象的成员变量,使用block的人有可能用类对象参与block中的运算而产生循环引用
    • 使用方将self或者成员变量加入block之前要先将self变为_weak
    • 在多线程环境下(block中的weakSelf有可能被析构的情况下)需要先将self转为strong指针,避免在运行到某个关键步骤的时候self对象被析构。

    118.UITableView优化技巧?

    • 1.正确的使用cell标识,缓存池.(必须讲)
    • 2.提前计算好行高.因为heightForRowAtIndexPath:是调用最频繁的方法,不要在该方法当中使用indexPath获取行返回行高
    • 3.如果cell内容非常多的时候可以在异步线程当中进行绘制.
    • 4.cell的内容来自网络时,一定要异步加载.把请求的结果缓存起来.
    • 5.减小subView的数量.
    • 6.尽量少用或者不用透明图片图层.,渲染系统就认为这个view是完全不透明的,这使得渲染系统优化一些渲染过程和提高性能。
    • 7.尽量少用addSubView给cell添加子控件,可以初始化的时候就添加好.然后通过hidden来控件显示.
    • 8.在Cell中来自网络图片时,UIImageView的图片最好跟来自网络图片一样大.因为压缩图片是非常耗费资源的,其实做的是变形transform操作,每一次的压缩图片都要乘以一个变换矩阵,
    • 9.设置阴影时尽量不要使用offset,使用shadowPath这种方法,这个会比使用offset性能要高, offset会让系统先描述好形状,然后再添加阴影.
    • 10.在View设置Frame时,尽量避免使用小数点.使用取整,或四舍5入

    119.如何解决通过drawRect方法进行绘制内存增大问题?

    • 使用CALayer的方式进行绘制

    • CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类。用CGPath来定义想要绘制的图形,CAShapeLayer会自动渲染。它可以完美替代我们的直接使用Core Graphics绘制layer,对比之下使用CAShapeLayer有以下优点:

    • 渲染快速。CAShapeLayer 使用了硬件加速,绘制同一图形会比用 Core Graphics 快很多。

    • 高效使用内存。一个 CAShapeLayer 不需要像普通 CALayer 一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。

    • 不会被图层边界剪裁掉。

    • 不会出现像素化。

    120.如何高性能的给UIImageView加一个圆角?

    • 不好的解决方案是使用layer,使用layer的方式会强制Core Animation提前渲染屏幕的离屏绘制, 而离屏绘制就会给性能带来负面影响,会有卡顿的现象出现
    • 正确的解决方案:使用绘图技术
    • 还有一种方案:使用了贝塞尔曲线"切割"个这个图片, 给UIImageView 添加了的圆角,其实也是通过绘图技术来实现的

    121.block和weak修饰符的区别?

    • _block不管是ARC还是MRC模式下都可以使用,可以修饰对象,也可以修饰基本数据类型
    • _weak只能在ARC模式下使用,只能修饰对象(NSString),不能修饰基本数据类型
    • block修饰的对象可以在block中被重新赋值,weak修饰的对象不可以

    122.如何封装一个view?

    • 可以通过纯代码或者xib的方式来封装子控件
    • 建立一个跟view相关的模型,然后将模型数据传给view,通过模型上的数据给view的子控件赋值

    相关文章

      网友评论

          本文标题:面试题集锦2(更新)

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