最近公司项目不怎么忙, 闲暇时间把iOS 在面试中可能会遇到的问题整理了一番, 一部分题目是本身面试遇到的,一部分题目则是网上收录的, 方便本身巩固复习, 也分享给你们! 知识点比较多,比较杂,这里作了分类,下面是分类连接地址;git
面试知识点整理 - 目录:
iOS | 面试知识整理 - OC基础 (一)
iOS | 面试知识整理 - OC基础 (二)
iOS | 面试知识整理 - OC基础 (三)
iOS | 面试知识整理 - UI 相 关 (四)
iOS | 面试知识整理 - 内存管理 (五)
iOS | 面试知识整理 - 多 线 程 (六)
iOS | 面试知识整理 - 网络相关 (七)
iOS | 面试知识整理 - 数据持久化 (八)
iOS | 面试知识整理 - Swift 基础 (九)程序员
#include
来引入头文件,若是须要防止重复导入须要使用#ifndef...#define...#endif
#import
来引入头文件,能够防止重复引入头文件,能够避免出现头文件递归引入的现象。@class
仅用来告诉编译器,有这样一个类,编译代码时,不报错,不会拷贝头文件.若是须要使用该类或者内部方法须要使用 #import
导入id
能够做为方法的返回以及参数类型 也能够用来定义变量instancetype
只能做为函数或者方法的返回值@puplic面试
1.能够在其余类中访问被@public修饰的成员变量
2.也能够在本类中访问被@public修饰的成员变量
3.能够在子类中访问父类中被@public修饰的成员变量
复制代码
@private编程
1.不可能够在其余类中访问被@private修饰的成员变量
2.也能够在本类中访问被@private修饰的成员变量
3.不能够在子类中访问父类中被@private修饰的成员变量
复制代码
@protected (默认状况下全部的实例变量都是protected)数组
1.不可能够在其余类中访问被@protected修饰的成员变量
2.也能够在本类中访问被@protected修饰的成员变量
3.能够在子类中访问父类中被@protected修饰的成员变量
复制代码
@package缓存
介于public和private之间的,若是是在其余包中访问就是private,在当前代码中访问就是public.
复制代码
@property = ivar + getter + setter;
复制代码
get
和set
方法声明get和set
方法的实现atomic/nonatomic
若是不写默认状况为 atomic
(系统会自动加上同步锁,影响性能),在 iOS 开发中尽可能指定为 nonatomic
,这样有助于提升程序的性能readwrite(读写)、readooly (只读)
retain、assign、strong、 weak、unsafe_unretained、copy
getter=、setter=
atomic
与nonatom
的主要区别就是系统自动生成的getter/setter
方法不同安全
atomic不是线程安全的ruby
weak
来解决, 好比:delegate
代理属性, 自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用 weak
,自定义 IBOutlet
控件属性通常也使用 weak
;固然,也可使用 strong
,可是建议使用 weak
weak 和 assign 的不一样点bash
weak
策略在属性所指的对象遭到摧毁时,系统会将 weak
修饰的属性对象的指针指 向 nil
,在 OC
给 nil
发消息是不会有什么问题的; 若是使用 assign
策略在属性所指 的对象遭到摧毁时,属性对象指针还指向原来的对象,因为对象已经被销毁,这时候就产生了野指针,若是这时候在给此对象发送消息,很容形成程序奔溃 assigin
能够用于修饰非 OC
对象,而 weak
必须用于 OC
对象weak
, 对于weak: 指明该对象并不负责保持delegate这个对象,delegate这个对象的销毁由外部控制。assign
,也有weak的功效, 对于使用 assign 修饰delegate, 在对象释放前,须要将 delegate 指针设置为 nil,否则会产生野指针atomic,readwrite,assign
atomic,readwrite,strong
NSString、NSArray、NSDictionary 等等常用 copy
关键字,是由于他们有对应 的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary
,为确保 对象中的属性值不会无心间变更,应该在设置新属性值时拷贝一份,保护其封装性block
也常用 copy
关键字,方法内部的 block
默认是 在栈区的,使用 copy
能够把它放到堆区.block
使用 copy
仍是 strong
效果是同样的,可是 建议写上 copy
,由于这样显示告知调用者“编译器会自动对 block
进行了 copy
操 做若想令本身所写的对象具备拷贝功能,则需实现 NSCopying
协议。若是自定义的对象分为可变版本与不可变版本,那么就要同时实现 NSCopyiog 与 NSMutableCopying 协议
服务器
// 实现不可变版本拷贝
- (id)copyWithZone:(NSZone *)zone;
// 实现可变版本拷贝
- (id)mutableCopyWithZone:(NSZone *)zone;
// 重写带 copy 关键字的 setter
- (void)setName:(NSString *)name {
_name = [name copy];
}
复制代码
方式一: 不是线程安全的,若是多线程须要加锁
static ClassName *_instance;
+ (instancetype)sharedInstance{
@synchronized (self) {
if(!_instance) {
_instance = [self alloc]init];
}
}
return _instance;
}
复制代码
方式二: 注意多线程问题 GCDdispatch_once 默认是线程安全的
static ClassName *_instance;
+ (instancetype)sharedInstance{
static dispatch_one_t oneToken;
dispatch_once(&onetoken,^{
_instance = [self alloc]init];
});
return _instance;
}
+ (instancetype)allocWithZone:(NSZone *) zone{
static dispatch_t onetoken;
dispatch_once(&oncetoken ^{
_instance = [super allocwithzone:zone];
})
retun _instance
}
复制代码
好比:
NSObject *obj = [NSObject new];
[obj release]; // obj 指向的内存地址已经释放了,
obj 若是再去访问的话就是野指针错误了.
野指针错误形式在Xcode中一般表现为:Thread 1:EXC_BAD_ACCESS,由于你访问了一块已经不属于你的内存。
复制代码
@property (copy, nonatomic) NSMutableArray * array
复制代码
使用 copy 修饰,会生成不可变数组,在添加删除数组元素时候会崩溃
@synthesize
,一个是@dynamic
。@synthesize 和@dynamic
都没写,那么默认的就是@syntheszie var = _var
;@synthesize
的语义是若是你没有手动实现 setter
方法和 getter
方法,那么编译器 会自动为你加上这两个方法@dynamic
告诉编译器:属性的 setter 与 getter
方法由用户本身实现,不自动生成(固然对于 readonly 的属性只需提供 getter 便可)setValue
仍然是调用了 setObject
方法, 若是参数 value 为 nil,则会调用removeObject
移除这个键值对;setObjectForKey
是 NSMutableDictionary特有的, value 不能为 nil,不然会崩溃setValueForKey
是KVC的,key 必须是字符串类型, setObject 的 key 能够是任意类型[self performSelector:@selector(Delay) withObject:nil afterDelay:3.0f];
复制代码
[NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:@selector(Delay) userInfo:nil repeats:NO];
复制代码
[NSThread sleepForTimeInterval:3.0f];
复制代码
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self Delay];
});
- (void)Delay {
NSLog(@"执行");
}
复制代码
- (void)test_Function:(int(^)(int num)) block{}
复制代码
(Procedure Oriented)
是一种以过程为中心的编程思想。就是分析出解决问题所须要的步骤,而后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就能够了。注重的是实现过程!“面向对象”是一种以对象为中心的编程思想。
面向对象的三大特性:
继承、封装、多态
,从而使得面向对象编程更具备容易让人接受,更贴近与人们的生活,比面向对象编程更加方便与快捷,必定程度上下降了程序员的工做量,使程序的可读性也获得了提升,代码的效率也获得了提升。OC的动态特性可从三方面:
cocoa touch底层技术架构 主要分为4层:
谓词(NSPredicate
)是OC针对数据集合的一种逻辑帅选条件,相似一个过滤器,简单实实用代码以下:
Person * p1 = [Person personWithName:@"alex" Age:20];
Person * p2 = [Person personWithName:@"alex1" Age:30];
Person * p3 = [Person personWithName:@"alex2" Age:10];
Person * p4 = [Person personWithName:@"alex3" Age:40];
Person * p5 = [Person personWithName:@"alex4" Age:80];
NSArray * persons = @[p1, p2, p3, p4, p5];
//定义谓词对象,谓词对象中包含了过滤条件
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < 30"];
//使用谓词条件过滤数组中的元素,过滤以后返回查询的结果
NSArray *array = [persons filteredArrayUsingPredicate:predicate];
复制代码
类工厂方法就是用来快速建立对象的类方法, 他能够直接返回一个初始化好的对象,具有如下特征:
好比系统 UIButton 的buttonWithType 就是一个类工厂方法:
// 类工厂方法
+ (instancetype)buttonWithType:(UIButtonType)buttonType;
// 使用
+ UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
复制代码
糖衣语法又叫作语法糖
或语法盐
,是指在计算机语言中添加某种语法,这种语法对语言的功能没有影响,但更方便程序员使用,增长程序的可读性,减小代码出错机会
OC中的字面量,其实就是语法糖
NSNumber * number = @1;
NSArray * array = @[@1, @2, @3];
NSDictionary * dict = @{@"key":@"value"};
NSNumber * num1 = array[0];
NSString * value = dict[@"key"];
复制代码
svn 和 git 都是用来对项目进行版本控制以及代码管理的.能够监测代码及资源的更改变化.有利于实现高效的团队合做;
svn 是集中式的,集中式是指只有一个远程版本库,git 是分布式的,分布式有本地和远程版本库,本地仓库都保留了整个项目的完整备份;
若是存储远程版本库的服务器挂了,全部人的代码都没法提交,甚至丢失版本库, git则由于有本地版本库而不会有这个问题。
因为二者的架构不一样,git 和 svn 的分支也是不一样的, svn 的分支是一个完整的目录,包含全部的实际文件,和中心仓库是保持同步的,若是某个团队成员建立新的分支,那么会同步到全部的版本成员中,全部人都会收到影响. 而 git下建立的分支合并前是不会影响到任何人的.建立分支能够在本地脱机进行任何操做.测试无误后在合并到主分支,而后其余成员才能够看获得.
OC中没有二维数组, 能够经过一维数组嵌套来实现二维数组;
// 字面量定义
NSArray * array = @[
@[@1,@2,@3,@4,@5],
@[@11,@12,@13,@14,@15],
@[@21,@22,@23,@24,@25],
@[@31,@32,@33,@34,@35],
@[@41,@42,@43,@44,@45],
];
// 访问
NSLog(@"%@",array[1][1]);
复制代码
CocoaPods 是一个 objc 的依赖管理工具,而其自己是利用 ruby 的依赖管理 gem 进行构建的
const
const常量修饰符,常用的字符串常量,通常是抽成宏,可是苹果不推荐咱们抽成宏,推荐咱们使用const常量。
- const 做用:限制类型
- 使用const修饰基本变量, 两种写法效果一致 , b都是只读变量
const int b = 5;
int const b = 5;
- 使用const修饰指针变量的变量
第一种: const int *p = &a 和 int const *q = &a; 效果一致,*p 的值不能改,p 的指向能够改;
第二种: int * const p = &a; 表示 p 的指向不能改,*p 的值能够改
第三种:
const int * const p = &a; *p 值和 p 的指向都不能改
const 在*左边, 指向可变, 值不可变
const 在*的右边, 指向不可变, 值可变
const 在*的两边, 都不可变
复制代码
宏
* 基本概念:宏是一种批量处理的称谓。通常说来,宏是一种规则或模式,或称语法替换 ,用于说明某一特定输入(一般是字符串)如何根据预约义的规则转换成对应的输出(一般也是字符串)。这种替换在预编译时进行,称做宏展开。编译器会在编译前扫描代码,若是遇到咱们已经定义好的宏那么就会进行代码替换,宏只会在内存中copy一份,而后全局替换,宏通常分为对象宏和函数宏。 宏的弊端:若是代码中大量的使用宏会使预编译时间变长。
const与宏的区别?
* 编译检查 宏没有编译检查,const有编译检查;
* 宏的好处 定义函数,方法 const不能够;
* 宏的坏处 大量使用宏,会致使预编译时间过长
复制代码
static
* 修饰局部变量: 被static修饰局部变量,延长生命周期,跟整个应用程序有关,程序结束才会销毁,被 static 修饰局部变量,只会分配一次内存
* 修饰全局变量: 被static修饰全局变量,做用域会修改,也就是只能在当前文件下使用
复制代码
extern
声明外部全局变量(只能用于声明,不能用于定义)
经常使用用法(.h结合extern联合使用)
若是在.h文件中声明了extern全局变量,那么在同一个类中的.m文件对全局变量的赋值必须是:数据类型+变量名(与声明一致)=XXXX结构。而且在调用的时候,必须导入.h文件。代码以下:
.h
@interface ExternModel : NSObject
extern NSString *lhString;
@end
.m
@implementation ExternModel
NSString *lhString=@"hello";
@end
调用的时候:例如:在viewController.m中调用,则能够引入:ExternModel.h,不然没法识别全局变量。固然也能够经过不导入头文件的方式进行调用(经过extern调用)。
复制代码
常量指针本质是指针,常量修饰它,表示这个指针乃是一个指向常量的指针(变量)。
指针指向的对象是常量,那么这个对象不能被更改。
指针常量的本质是一个常量,而用指针修饰它,那么说明这个常量的值应该是一个指针。
指针常量的值是指针,这个值由于是常量,因此不能被赋值
指针函数
// 指针函数
int *sum(int a, int b){
int result = a + b;
int *c = &result;
return c;
}
int *p = sum(10, 20);
printf("sum:%d\n", *p);
复制代码
函数指针
// 函数指针
int max(int a, int b){
return (a > b)?a:b;
}
int (*p)(int, int) = max;
int result = p(10, 20);
printf("result:%d\n", result);
复制代码
#define Max(a,b) a>b?a:b
复制代码
float a = 1;
float b = MIN(a++,1.5);
问 a= ? b = ?
答案: a = 3; b = 2
a++ 会后执行, a++在表达式出现了2次,得3, a++<1.5,返回a++,得2
// 扩展
float a = 1;
float b = [self getMix:a++ b:1.5];
- (CGFloat)getMix:(CGFloat ) a b:(CGFloat)b{
return a>b?a:b;
}
运行 a = 2; b =1;
复制代码
其实呢做为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是个人微信 你们有兴趣能够添加 邀请小伙伴们进入微信群里一块儿 交流(想要进入的可加小编微信17512010526)
做者:LEON_iOS
连接:www.jianshu.com/p/51c9eb362…