知识点总结1

OC的理解与特性

OC作为一门面向对象的语言,自然具有面向对象的语言特性:封装、继承、多态。它既具有静态语言的特性(如C++),又有动态语言的效率(动态绑定、动态加载等)。总体来讲,OC确实是一门不错的编程语言,多态:不同对象以自己的方式响应相同的消息的能力叫做多态。意思就是假设生物类(life)都用有一个相同的方法-eat;

Objective-C具有相当多的动态特性,表现为三方面:动态类型(Dynamic typing)、动态绑定(Dynamic binding)和动态加载(Dynamic loading)。动态——必须到运行时(run time)才会做的一些事情。

动态类型:即运行时再决定对象的类型,这种动态特性在日常的应用中非常常见,简单来说就是id类型。事实上,由于静态类型的固定性和可预知性,从而使用的更加广泛。静态类型是强类型,而动态类型属于弱类型,运行时决定接受者。

动态绑定:基于动态类型,在某个实例对象被确定后,其类型便被确定了,该对象对应的属性和响应消息也被完全确定。

动态加载:根据需求加载所需要的资源,最基本就是不同机型的适配,例如,在Retina设备上加载@2x的图片,而在老一些的普通苹设备上加载原图,让程序在运行时添加代码模块以及其他资源,用户可根据需要加载一些可执行代码和资源,而不是在启动时就加载所有组件,可执行代码可以含有和程序运行时整合的新类。

autorelease:即延迟释放。

自动释放池的作用:在程序执行完毕即池子即将销毁的时候会对池子中所有调用autorelease的对象进行一次release操作。

面试题一:自动释放池什么时候创建,什么时候销毁?

每一次运行循环执行后,也就是每当事件被触发时都会创建自动释放池。在程序执行的过程中,所有autorelease的对象在出了作用域之后会被添加到最近创建的自动释放池中。运行循环结束前会释放自动释放池,还有池子满了也会销毁。

其工作原理是:自动释放池被销毁或耗尽时会向池中的所有对象发送release消息,释放所有autorelease对象。

自动释放池常见面试题代码

for (int i = 0; i < 100000; ++i) {

NSString *str = @"Hello World";

str = [str stringByAppendingFormat:@"- %d",i];  //字符串拼接

  str = [str uppercaseString];  //将字符串替换成大写

}

如果循环的次数过大,会出现什么问题?该怎么解决?

  会出现内存溢出,循环内部创建大量的临时对象,没有被释放

  每次循环都将上一次创建的对象release

for(inti =0; i <100000; ++i) {

      @autoreleasepool{

NSString*str =@"Hello World";

str = [strstringByAppendingFormat:@"- %d",i];

str = [struppercaseString];

    }

    }

不会自动管理内存的情况?

编译器不会自动管理CoreFoundation框架的数据类型对象的生命周期,因此使用CoreFoundation框架直接桥接数据类型,就必须手动管理这些对象的内存


AFNetwork

AF底层基于 NSURlsession  (session:会议)

AF的五个功能模块

1.网络通信 (AFURLsessionManager)(Manager:管理)

2.网络通讯安全

3.网络状态监听

4.网络通讯序列化反序列化

5.对UIkit的封装

AF的实现流程

通过AFHTTPRequestOperationManager---->(确定请求方式 get ,post ,请求参数)----->给到AFURLRequestSerialization(Serialization:序列化;进行参数拼接)----->AFHTTPRequestOperation(Operation:经营,计算;下放到请求队列 NSOperationQueue中)---->最后由最底层的AFURLconnectionOperation (去完成请求,做https认证)--->数据返回到AFhttpRequestOperation----->通过AFURLResponseSerialization (Response [rɪ'spɒns] 响应)--->进行数据解析成json xml格式  返回到AFHTTPRequestOperationManager中


1、带block形式, 内部是任务队列进行下载 ,就是对operation的一个封装下载。

2、还对uikit 内部的类进行类别形式添加方法(异步下载图片)。

3、还可以检测网络状态。


多线程:

GCD 与 NSOperation 的区别:NSThread

GCD 和 NSOperation 都是用于实现多线程:

GCD 基于C语言的底层API,GCD主要与block结合使用,代码简洁高效。

NSOperation 属于Objective-C类,是基于GCD更高一层的封装。复杂任务一般用NSOperation实现。

performSelectorOnMainThread:

使用NSOperation的情况:各个操作之间有依赖关系、操作需要取消暂停、并发管理、控制操作之间优先级,限制同时能执行的线程数量.让线程在某时刻停止/继续等。

使用GCD的情况:一般的需求很简单的多线程操作,用GCD都可以了,简单高效。

CGD :1.充分利用设备的多核最高效 2.自动管理线程的生命周期3.CGD 是先进先出的 4.基于c实现

NSoperation:  1.基于GCD 封装的 使用更加面向对象 2.可以改变队列的执行顺序3.比GCD多了一些简单实用的功能

GCD 的方法1.获取全局并行队列  dipatch _ get_grolop_queue

                    2.获取主队列  dispatch_get_main_queue           

                    3.创建串行行队列  dispatch _queue_serial

                  4.创建并行行队列  dispatch _queue_concurrent [kən'kʌr(ə)nt]

                  5.延迟提交  dispatch_after【啊 f t】

                    dispatch_time_t

                  6.行完成后 dispatch_group_notify

barrier【百瑞额】:表示栅栏,当在并发队列里面使用栅栏时候,栅栏之前的并发任务开始并发执行,执行完毕后,执行栅栏内的任务,等栅栏任务执行完毕后,再并发执行栅栏后的任务。

Objective-C 中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码、方法又是什么?

答:线程创建有三种方法:使用NSThread创建、使用GCD的dispatch、使用子类化的NSOperation,然后将其加入NSOperationQueue;

NSOperation在主线程执行代码,方法是performSelectorOnMainThread,perform[执行]

如果想延时执行代码可以用performSelector:onThread:withObject:waitUntilDone:

GCD:Main Dispatch Queue/Global Dispatch Queue  主队列特殊的串行、全局的并行队列

dispatch  _after  延迟执行


FMDB

插入数据  @"insert into user (name, password) values(?, ?) ";表名 (字段1, 字段2...) values (值1, 值2...);

删除数据 @"delete from user  where";

更新数据 @"UPDATE USER SET id = ? WHERE  name = ?";

FMDatabaseQueue多线程安全:  原理创建一个队列(串行线程队列),然后将放入的队列的block顺序执行,这样避免了多线程同时访问数据库

设计模式

代理  单利 观察者 MVC 工厂

单例模式: 一个类只有一个实例对象。

创建方法:GCD的一次函数(dispatch_once_t)通知中心就是单利

应用场景 封装FMDB 整个程序使用

工厂方法模式:定义创建对象的接口,让子类决定实例化哪一个类。工厂方法使得一个类的实例化延迟到其子类。

应用场景 :多种样式的cell 根据model 产出不同的cell布局

KVO: 的实现依赖于  Runtime实现 . 当某个类的属性对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter 方法。派生类在被重写的setter方法内实现真正的通知机制

KVO 的键值观察通知依赖于 NSObject 的两个方法:willChangeValueForKey:和 didChangevlueForKey:

KVC:即键值编码

1,对私有变量进行赋值

2,字典转模型

当观察某对象 A 时,KVO 机制动态创建一个对象A当前类的子类,并为这个新的子类重写了被观察属性 keyPath 的 setter 方法。setter 方法随后负责通知观察对象属性的改变状况。

Notification 通知

默认是以同步的方式发送通知的;

异步发送通知:将通知加到通知队列中,就可以将一个通知异步的发送到当前的线程,这些方法调用后会立即返回,不用再等待通知的所有监听者都接收并处理完。

做多线程开发时,需要在线程调度方法中手动添加自动释放池,尤其是当执行循环的时候,如果循环内部有使用类的快速创建方法创建的对象, 一定要将循环体放到自动释放池中。

Block:获取其它函数局部变量的匿名函数

匿名函数:没有函数名的函数,一对{}包裹的内容是匿名函数的作用域,OC中的Block则可以用指针来直接调用一个函数;

虽然使用Block不用声明类,但是Block提供了类似Objective-C的类一样可以通过成员变量来保存作用域外变量值的方法,那些在Block的一对{}里使用到但却是在{}作用域以外声明的变量,就是Block截获的自动变量。

block的注意点

1). 在block内部使用外部指针且会造成循环引用情况下,需要用__week修饰外部指针:

__weak typeof(self) weakSelf = self;

2). 在block内部如果调用了延时函数还使用弱指针会取不到该指针,因为已经被销毁了,需要在block内部再将弱指针重新强引用一下。

__strong typeof(self) strongSelf = weakSelf;

3). 如果需要在block内部改变外部栈区变量的话,需要在用__block修饰外部变量。

__block在__main_block_func_0里面可以看到传递的是指针。所以成功改变了变量的值。

什么时候在 block 中不需要使用 weakSelf

问题:我们知道,在使用 block 的时候,为了避免产生循环引用,通常需要使用 weakSelf 与 strongSelf,写下面这样的代码:

__weaktypeof(self) weakSelf =self

;[selfdoSomeBlockJob:^{ 

__strongtypeof(weakSelf) strongSelf = weakSelf;if(strongSelf)

{        ...    }}];

那么请问:什么时候在 block里面用self,不需要使用weakself?

当block本身不被self 持有,而被别的对象持有,同时不产生循环引用的时候,就不需要使用weakself了。最常见的代码就是UIView的动画代码,我们在使用UIView animateWithDuration:animations方法 做动画的时候,并不需要使用weakself,因为引用持有关系是:

UIView 的某个负责动画的对象持有block,block 持有了self因为 self 并不持有 block,所以就没有循环引用产生,因为就不需要使用 weak self 了。

[UIView animateWithDuration:0.2 animations:^{

    self.alpha = 1;

}];

当动画结束时,UIView会结束持有这个 block,如果没有别的对象持有block的话,block 对象就会释放掉,从而 block会释放掉对于 self 的持有。整个内存引用关系被解除。

Block不允许修改外部变量的值,这里所说的外部变量的值,指的是栈中指针的内存地址。__block 所起到的作用就是只要观察到该变量被 block 所持有,就将“外部变量”在栈中的内存地址放到了堆中。进而在block内部也可以修改外部变量的值。

介绍一下分类,能用分类做什么?内部是如何实现的?它为什么会覆盖掉原来的方法?

category:我们可以给类或者系统类添加实例方法方法。我们添加的实例方法,会被动态的添加到类结构里面的methodList列表里面。categort

类别 (category)和扩展(Extension) 继承

使用分类(category)。

1.分类(category)的作用

1.1作用:可以在不修改原来类的基础上,为一个类扩展方法。

1.2最主要的用法:给系统自带的类扩展方法。

1.类扩展(extension)是category的一个特例,有时候也被称为匿名分类。他的作用是为一个类添加一些私有的成员变量和方法。

继承:子类不仅拥有父类所有的属性和方法,而且可以创建属于自己的属性和方法。


iOS手动局框架-Masonry

运用JavaScriptCore框架进行交互

在iOS 7之后,apple添加了一个新的库JavaScriptCore,用来做JS交互,因此JS与原生OC交互也变得简单了许多。这是我做的一个例子

- (void)webViewDidFinishLoad:(UIWebView *)webView {

    self.webTitle = [self.webView stringByEvaluatingJavaScriptFromString:@"document.title"];

  [self needNavigationleftButtonTitle:nil RightButtonTiele:nil TitleLable:self.webTitle targat:self];

    self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    self.jsContext[@"submitFrom"] = self;

    self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {

        context.exception = exceptionValue;

        NSLog(@"异常信息:%@", exceptionValue);

    };

}

析核心动画CoreAnimation

基础动画(CABaseAnimation)

关键帧动画(CAKeyframeAnimation)

组动画(CAAnimationGroup)

过渡动画(CATransition)


Instruments提供了很多功能,我会重点介绍一下我最常用的几类:

1.Time Profiler:CPU分析工具分析代码的执行时间。

2.Core Animation:离屏渲染,图层混合等GPU耗时。

3.Leaks:内存检测,内存泄漏检测工具。

4.Energy Log:耗电检测工具。

5.Network:流量检测工具。


栈区和堆区

栈区(stack)由编译器自动分配释放 ,存放方法(函数)的参数值, 局部变量的值等,栈是向低地址扩展的数据结构,是一块连续的内存的区域。即栈顶的地址和栈的最大容量是系统预先规定好的。

堆区(heap)一般由程序员分配释放, 若程序员不释放,程序结束时由OS回收,向高地址扩展的数据结构,是不连续的内存区域,从而堆获得的空间比较灵活。

碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出.

全局区(静态区)(static),全局变量和静态变量的存储是放在一块 的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后有系统释放。

文字常量区—常量字符串就是放在这里的。程序结束后由系统释放。

程序代码区—存放函数体的二进制代码


CornerStone使用分享[康那思透恩]

CornerStone是mac下非常流行的一个SVN管理工具,mac版本svn管理中最推荐使用的一个。

用@property声明的 NSString / NSArray / NSDictionary 经常使用 copy 关键字,为什么?如果改用strong关键字,可能造成什么问题?

答:用 @property 声明 NSString、NSArray、NSDictionary 经常使用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间可能进行赋值操作(就是把可变的赋值给不可变的),为确保对象中的字符串值不会无意间变动,应该在设置新属性值时拷贝一份。

1. 因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本。

2. 如果我们使用是 strong ,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性。

//总结:使用copy的目的是,防止把可变类型的对象赋值给不可变类型的对象时,可变类型对象的值发送变化会无意间篡改不可变类型对象原来的值。

@synthesize 和 @dynamic 分别有什么作用?

@property有两个对应的词,一个是@synthesize(合成实例变量),一个是@dynamic。

如果@synthesize和@dynamic都没有写,那么默认的就是 @synthesize var = _var;

// 在类的实现代码里通过 @synthesize 语法可以来指定实例变量的名字。(@synthesize var = _newVar;)

1. @synthesize 的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上这两个方法。

2. @dynamic 告诉编译器,属性的setter与getter方法由用户自己实现,不自动生成(如,@dynamic var)。

如何对iOS设备进行性能测试?

答: Profile-> Instruments[in吹门特] ->Time Profiler

写一个完整的代理,包括声明、实现

// 创建

@protocol MyDelagate

@required

-(void)eat:(NSString *)foodName;

@optional

-(void)run;

@end

//  声明 .h

@interface person: NSObject

@end

//  实现 .m

@implementation person

- (void)eat:(NSString *)foodName {

  NSLog(@"吃:%@!", foodName);

}

- (void)run {

  NSLog(@"run!");

}

@end

iOS的沙盒目录结构是怎样的?

沙盒结构:

1). Application:存放程序源文件,上架前经过数字签名,上架后不可修改。

2). Documents:常用目录,iCloud备份目录,存放数据。(这里不能存缓存文件,否则上架不被通过)

3). Library:

Caches:存放体积大又不需要备份的数据。(常用的缓存路径)

Preference:设置目录,iCloud会备份设置信息。

4). tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能。


介绍一下XMPP?

XMPP是一种以XML为基础的开放式实时通信协议。

简单的说,XMPP就是一种协议,一种规定。就是说,在网络上传东西,XMM就是规定你上传大小的格式。

冒泡排序

/**

* 【冒泡排序】:相邻元素两两比较,比较完一趟,最值出现在末尾

* 第1趟:依次比较相邻的两个数,不断交换(小数放前,大数放后)逐个推进,最值最后出现在第n个元素位置

* 第2趟:依次比较相邻的两个数,不断交换(小数放前,大数放后)逐个推进,最值最后出现在第n-1个元素位置

* ……  ……

* 第n-1趟:依次比较相邻的两个数,不断交换(小数放前,大数放后)逐个推进,最值最后出现在第2个元素位置

*/

void bublleSort(int *arr, int length) {

    for(int i = 0; i < length - 1; i++) { //趟数

        for(int j = 0; j < length - i - 1; j++) { //比较次数

            if(arr[j] > arr[j+1]) {

                int temp = arr[j];

                arr[j] = arr[j+1];

                arr[j+1] = temp;

            }

        }

    }

}

热更新

Weex

跨平台,一套代码,iOS、Android都可以运行。用前端语法实现原生效果。比React Native更好用。

weex基于vue.js,ReactNative使用React。

ReactNative安装配置麻烦。 weex安装cli之后就可以使用。

react模板JSX有一定的学习成本,vue和常用的web开发类似,模板是普通的html,数据绑定用mustache风格,样式直接使用css。

四、React Native

不像Weex能一套代码多端运行,需要自己分别做修改。

React Native 可以动态添加业务模块,但无法做到修改原生OC代码。

JSPatch、lua 配合React Native可以让一个原生APP时刻处于可扩展可修改的状态。

UIImage初始化一张图片有几种方法?简述各自的优缺点。

imageNamed:系统会先检查系统缓存中是否有该名字的Image,如果有的话,则直接返回,如果没有,则先加载图像到缓存,然后再返回。

initWithContentsOfFile【文件的内容】:系统不会检查系统缓存,而直接从文件系统中加载并返回。

函数式编程

函数式编程总结

如果想再去调用别的方法,那么就需要返回一个对象;

如果想用()去执行,那么需要返回一个block;

如果想让返回的block再调用对象的方法,那么这个block就需要返回一个对象(即返回值为一个对象的block)。


深拷贝与浅拷贝


你可能感兴趣的:(知识点总结1)