面试题总结

@property与@synthesize、@dynamic


@property:声明和实现getter/setter方法,生成_成员变量

@synthesize::合成属性的getter/setter 方法

@dynamic:告诉编译器 不生成getter/setter方法 包括成员变量

@property +@sythesize  //property:声明set/get方法  @sythesize 负责生成_成员变量,实现getter/setter方法。


@interface categoryController ()
@property (nonatomic )NSString *dynamicStr;
@property (nonatomic )NSString *synthesizeStr;

@end

@implementation categoryController

{
    NSString *asd;
}

@dynamic dynamicStr;                           //告诉编译器 禁止实现该属性的 getter,setter方法,同时成员变量也不会创建。
@synthesize synthesizeStr = synthesizeStr;     //合成器语法 自动合成getter,setter方法,同时设置成员变量 synthesizeStr
- (void)viewDidLoad {
    [super viewDidLoad];
    
    //dynamic
    self.testStr = @"123";
    NSLog(@"self.testStr==%@",self.testStr);
    
    //synthesize
    synthesizeStr = @"100";
    NSLog(@"self.synthesizeStr==%@",self.synthesizeStr);
    
    self.synthesizeStr = @"200";
    NSLog(@"synthesizeStr===%@",synthesizeStr);
}

- (void)setTestStr:(NSString *)testStr
{
    asd = testStr;
}
- (NSString *)testStr
{
    return asd;
}

@end

//控制台打印
2017-06-22 11:09:11.189 TestForMe[2021:522795] self.testStr==123
2017-06-22 11:09:11.189 TestForMe[2021:522795] self.synthesizeStr==100
2017-06-22 11:09:11.189 TestForMe[2021:522795] synthesizeStr===200

二: 比较 NSString 中 copy strong区别

@property (copy ,nonatomic)NSString *cStr;
@property (strong ,nonatomic)NSString *sStr;


- (void)viewDidLoad {
    [super viewDidLoad];
    [self copyWithStrongMethod1];
    [self copyWithStrongMethod2];

 
}

#pragma MARK 测试 日常 copy 和strong 的区别
- (void)copyWithStrongMethod1
{
    NSMutableArray *books = [@[@"book1"] mutableCopy];
    Person *person = [[Person alloc] init];
    person.strBooks = books;     //strong属性
    person.copBooks = books;    //copy属性
    [books addObject:@"book2"];
    NSLog(@"bookArray1:%@",person.strBooks);
    NSLog(@"bookArray2:%@",person.copBooks);
}

//控制台打印
2017-07-06 15:08:30.858 TestForMe[15547:8771374] bookArray1:(
    book1,
    book2
)
2017-07-06 15:08:30.859 TestForMe[15547:8771374] bookArray2:(
    book1
)

- (void)copyWithStrongMethod2
{
    NSMutableString *str = @"abc".mutableCopy;
    
    self.cStr = str;
    self.sStr = str;
//    str = @"asdsad".mutableCopy;不行
    [str appendString:@" 123"];
   
    NSLog(@"str1===%@ str2===%@", self.cStr, self.sStr); // str1:hello world str2:hello
}

//控制台打印
2017-07-06 15:08:30.859 TestForMe[15547:8771374] str1===abc str2===abc 123

备注:

备注:
使用strong,则person.bookArray1与可变数组books指向同一块内存区域,books内容改变,导致person.bookArray1的内容改变,因为两者是同一个东西;而使用copy,person.bookArray2在赋值之前,将books内容复制,创建一个新的内存区域,所以两者不是一回事,books的改变不会导致person.bookArray2的改变。
说到底,其实就是不同的修饰符,对应不同的setter方法,
1. strong对应的setter方法,是将_property先release(_property release),然后将参数retain(property retain),最后是_property = property。
2. copy对应的setter方法,是将_property先release(_property release),然后拷贝参数内容(property copy),创建一块新的内存地址,最后_property = property。

*实现原理总结

*****关于kvo: 

1 监听机制,基于nsobject 两个方法willChangeValueForKey 和didChangeValueForKey,实现的。

2 当给一个属性添加观察者时候,运行时,会创建一个继承对象所属类的派生类,并且重写被观察属性的set方法,默认一个对象的isa指针会之前所属类,而这是isa会指向这个新的派生类,所以其实被观察的属性的赋值操作是在这个派生类 里实现的。

3 的当被监听的属性发生改变前,调用willChange方法 记录旧的值,改变结束 调用DidChangeValue新的值,出发kvo监听方法。

*****kvo应用场景

1 推送消息 消息时 放数组里面 我们的birgeValue显示红点提示 需要兼监听数组改变 给提示

2 视频 监听进度条

3 做轮播图监听 scrollview 监听contentOffSet 

*****深拷贝 浅拷贝

1 最大的区别就是 有否创建新对象。深拷贝内容拷贝,浅拷贝指针拷贝(内存地址拷贝)

2 深拷贝,修改一个对象不影响另一个对象。

3 浅拷贝,修改一个对象影响另外一个对象

大体上 copy mutable copy 策略是深拷贝

retain  strong是浅拷贝

*****SDWebImage细节

1 sd_setImageWithURL

2 SDWebImageManager  单例 downloadImageWithURL

 内部  SDImageCache类(nscache)以以url为key queryDiskCacheForKey方法 Memory Cache 以url为key去内存中查询缓存图片,如果没有  Disk Cache:去磁盘上找。

如果磁盘找到,会将图片设置到memory cache中。

3 如果缓存数据查询成功,则返回,不成功则请求网络self.imageDownloader down…

4 如果下载成功 [self.imageCache storeImage]储存 completedBlock回调前端展示

ps 磁盘缓存清除策略

1 清理过期缓存

2 清理写入时间早的图片

@interface SDImageCache : NSObject

@property (assign, nonatomic) NSInteger maxCacheAge;//最大缓存时间

@property (assign, nonatomic) NSUInteger maxCacheSize;//最大缓存空间

//设置最大缓存空间

[SDImageCache sharedImageCache].maxCacheSize = 1024 * 1024 * 50;    // 50M

SDWebImage Bug

磁盘图片渲染之前,需要得到图片的原始像素数据,然后去做绘制操作,所以图片需要解压缩。

*****公司刷新 流程

size :取多少

offset:从哪里取

count:总数

刷新:

设定size 20条 10条,offset 为0 加到数组中

加载:

设定size20条 10条,第一次 获取数据数组长度 offset 从这取值 取size条,加到数组。

判断更多 has 数据数组个数< count总数

设置footer view 给个提示 没有更多

***** svpullrefresh 原理

创建个scrollView的分类  分类添加属性刷新头部显示的view 高度60 添加头部刷新view为scrollview的观察者,监听contentOffSet的改变,刷新头部view 有几种状态,加载状态,初始状态,停止状态,拖拽状态,在观察者监听方法里面,根据几种状态切换执行layoutSubview的显示

*****bug

当下拉刷新比较少时候 会先调用下拉加载 在调用下拉刷新,由于头部view,后尾部view都是scrollview的观察者,所以当offset改变时候,观察者方法都会调用,然后判断的也都是拖拽,

解决:尾部控件拖拽状态进入加载还不都,还要&&上scollview.cotentset>0

uiscrollview的分类

/**********************************************************************************/

*****tableview 滑动 cell 崩溃 (会议人气榜)

且仅仅4s崩溃,其他的不崩溃 而且会有内存明显的飙升 正常100左右飙升到800

断点调试 崩溃在sdwebimage里面 沙盒取出的图片转码 转位图时候,正常我们设置图片imageview setimage 都是在主线程中设置的 这其就包括解压图片为位图(很耗cpu) 然后calyer在view上做渲染。sdwebimage做法是开子线程去去做这个位图的解压缩,然后缓存 供ui使用,去沙盒中去图片的时候不做任何处理,直接取,这次奔溃的原因就是后台返回的图片太大 3000*5000,方案有两个第一大图片不处理 不解码这样性能差点 但不崩溃

第二种是 沙盒取出的图片 先等比压缩下。

我的方案是综合下 沙盒取出图片先判断如果款大于屏幕宽度 等比压缩下,小的不压缩,然后再去转码

*******多线程场景应用

qq分享要求的图片1m以内,后台传的图片1.2m发布出去 回调不掉。

方案:下载图片nsdata datawithurl 网速慢直接卡死 要开线程 图片存储沙盒,等比压缩图片

xmpp 环境配置

材料:openfire服务器 mysql数据库(默认装到控制面板)

1 openfire mac版 基于java开发的 所以要求电脑有java运行环境 

没有的话需要安装jdk 查看java运行环境 终端执行命令 运行java -version 

2 mysql (服务端的数据库)使用是需要有账户密码默认装到控制面板)

  1》安装完 mysql 默认账户是root 密码为空

  2》终端命令配置命令行配置 开启mysql 并设置密码 

  3》创建的数据库默认四个文件 有个test文件 

  4》管理工具navcat 还有个海豚(mysqlworkbeech)的 登录输入连接名称(自定义)输入IP地址 端口号默认3306

       账户名称 root 密码(你配置过得)配置的数据库名称为你自定义的名称

3 关联openfire 和数据库1 导入openfire数据表文件到mysel(创建字段包括用户等)

 1》openfire建立数据库文件openfire数据库编码选择utf-8的

 2》默认open fire数据库安装到/user/local/openfire/ 数据库脚本保存在/user/local/openfire/ /resources/database/中

支持很多种数据库 保存mysql的数据库到桌面 导入到mysql中,这样mysql就添加好数据库字段了

4 关联openfire 和数据库1  后台管理设置关联数据库mysql

 

后台配置 选中驱动类型:mysql 指定mysql路径 输入mysql   用户名密码:root 密码:123456

配置openfire 后台账户密码 admin 123456

设置jid:

***** coast / 宏定义

coast(常量):修饰变量之用 (可以修饰基本数据类型 int ,oc对象:nesting),标记变量只读…

应用场景:1 修饰全局变量 2 修饰方法参数

PS:NSString *coast str;//  当用在全局变量,防止外部引用extern 修改..

  -(void)setTest:(int coast)a { }  修饰方法参数,防止参数被修改,修改了,当然set方法你就外面白白设置了!~ 

ps:什么叫做常量,10.@“SDSADD” 叫常量 nssting *a  a叫做变量....

***** static / extern  全局变量 局部变量牛逼闪闪 

static:修饰变量(全局,局部)使用

修饰局部变量:

作用:延长局部变量生命周期 (类似给局部变量变为全局变量的意思!)

ps:局部变量本身存储堆栈区,方法结束局部变量随之销毁;static修饰后将局部变量copy到静态区,修饰后变量在运行中在静态区给局部变量分配一次内存空间,且仅仅执行一次,程序运行期间变量一直存在不会销毁。

ps:打点断 ,发现下次执行这里断点过到下面去了。

修饰全局变量:

主要是作用域的问题,static修饰后仅在本类中可以使用,无法extain引用,全局变量则可以外部引用。

场景:int做自增运算

extern:外部引用  UIKIT EXTERN(牛逼闪闪的宏定义 吼吼~~)

一个类中声明(及时写在方法里面也无妨),另一个类extern 可以直接引用。

ps:无需等到程序会否执行到该方法,程序启动即分配内存空间,所以无需加载到该方法。

ps:个人理解,类似通过extern关键字从静态区 引出一个全局变量的意思,然后重新声明,使用。。。

全局变量:变量存储在静态区,程序运行时分配一次内存空间,然后不会再去执行了。

局部变量:存放在栈空间中,方法执行结束,变量销毁。

????为什么 类方法 要用static 修饰全局变量

***** 项目性能优化

1 懒加载  场景:初始化UI控件 2NSDateFormatter(日期格式化)

2 tableview优化 实现: 高度,数据 提前缓存,tableview只做赋值运算 减少subVies数量,rowHeight sectionHooterHeight 直接设定,少用代理

3 常识注意

***** NSURLCache

缓存原理 NSURLQequest 对应一个NSURLURLCacheResponse

缓存NSURLCache *cache = [NSURLCache shareURLCache];//掌握全局缓存

***** Block常识 (一)

方法常用声明:@property (copy) void(^MyBlock)(void); 如果超出当前作用域之后仍然继续使用block,那么最好使用copy关键字,拷贝到堆区,防止栈区变量销毁

_weak typeof(self) weakSelf = self;

因此,__block和__weak修饰符的区别其实是挺明显的: 

1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。 

2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。 

3.__block对象可以在block中被重新赋值,__weak不可以。 

PS:__unsafe_unretained修饰符可以被视为iOS SDK 4.3以前版本的__weak的替代品,不过不会被自动置空为nil。所以尽可能不要使用这个修饰符。

***** Block和copy (二)

为什么要用copy:出于作用域考虑,默认block 存放在栈中,函数调用,栈分配内存,函数结束释放内存,block 销毁。再次调用block 时候报错野指针错误。当前block 变量指向的被释放的内存地址。所以需要copy到堆中,包住block的命。

“他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。”

***** Block  copy/strong (三)

使用retain也可以,但是block的retain行为默认是用copy的行为实现的,

因为block变量默认是声明为栈变量的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的操作一致,最好声明为copy。

***** Block  copy/strong 扩展

block内部不引入外部变量:__ NSGlobalBlock

block内部引入外部变量   :__ NSStackBlock

***** weak 实现原理

runtime维护这个一个weak表(哈希表),记录已对象的地址为key,value为 所有指向该对象的weak弱指针地址的数组,当对象销毁时候通过weak表中该对象地址的value,查找到存有所有弱指针的地址的数组,赋值为nil,然后从weak表中删除。

对象销毁 会调用objec_clear_deallocating函数

assign weak 区别

assign:修饰对象,和基本数据类型;当被修饰的变量指向变量释放或置空,会出现野指针错误!

weak:只能修饰对象,不会出现野指针错误,当被修饰的变量指向的变量释放或是置空,被修饰变量指向nil,不会出现野指针错误。

引申

***** 内存分析

静态内存分析 analyze、分析/ 蓝色

例如:逻辑错误

logic error  /  Dead store/Memory

不是太准 不可变赋值给可变数组 ,调方法时候传入的字典参数未实例化

动态内存分析 profile -allocation /leaks   侧面/分配/泄漏

*****手势 响应者链条

分两块,

1 定位接收者

2 响应者链条

1定位接收者 当点击屏幕的ui出发一个事件,流程是事件添加到UIAplication的事件组,传递事件经历 window ,父控件且判断控件是否接受事件,如果是,则父控件遍历子控件,判断当前出发点是否在子控件上,继续遍历直到找到触发该点的最后一个子控件,事件传递不可以断,以为这所有控件务必可以处理事件,获取执行触发事件的控件。 

ps:这就说明了 为什么交互期间中间有个什么uiimageview等不能交互的夫控件,导致子控件不接受响应事件

可以接受响应事件的控件需要继承uiresponder 但还不够 需要可以交互 不是隐藏的 alpha值不是太小

2 响应者链条,功能是一个事件的发生,可以被多个控件获取。回传靠的是super执行方法

举例子:view上事件触发 默认事件互传给父控件,继续回传父控件,控制器.view 控制器(一样继承uiresponder);如果控制器还有父控制器那就父控件传递 给控制器 然后self.view 然后父控制器 window uiapplication 

*****注册登录 加密流程 对称非对称加密

*****get post tcp udp

*****缓存策略

*****镂空的遮罩

     0 思路:蒙版.layer.mask = layer对象

     1 创建蒙版

     2 绘制贝塞尔路径 添加反转图形(叠加部分会镂空)

     3 创建layer(CAShapeLayer子类).path = 贝塞尔路径.path

     4 设置 蒙版.layer.mask = layer对象

*****ios webp格式图片应用 及交互

博客园详解

***** ios 堆栈详解

博客园详解

原文地址:https://www.cnblogs.com/ly1973/p/7063912.html