整理一些重点和面试问到几率比较大的题目给小伙伴
对您有帮助或者您喜欢的话 希望能点个赞或者添加一下关注
同步:串行的执行任务 异步:并行的执行任务.同步函数不具备开启线程的能力,而异步函数具备
所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回.但是一旦调用返回,就得到返回值了.也就是 由调用者主动等待这个调用结果
而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果.换句话说就是当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用.
用互斥锁,队列组,栅栏函数,依赖
在OC中,一个类继承另一个类,就是继承了父类所有的属性和方法,并且可以扩充自己的属性:而类别是在不改变原有类的基础上进行方法扩充;
因此,根据开发需求,如果这个类需要扩充属性,或者需要重写系统的类的某些方法,用继承;如果只是对一个类扩充接口和模块,使用类别更加方便.
当使用const修饰指针类型变量时:
-> loadView
-> viewDidLoad
-> viewWillAppear
-> viewWillLayoutSubviews
-> viewDidLayoutSubviews
-> viewDidAppear
-> viewWillDisappear
-> viewDidDisappear
内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是就产生溢出.
内存泄漏就是指你向系统申请分配内存进行使用,可以说使用完后没有惊喜释放,结果这块内存也无法分配给其他程序,称之为内存泄漏
内存泄漏的累计危害非常大 最后会导致内存溢出 程序闪退;
内存泄漏分为四大类;
响应者链条是一条由UIResponder的子类组成的链条,它们都能够响应时间,由事件的最佳相应者起,如果它是控制器的view的话,它的上一级响应者就是这个控制器,否则就是它的父控件;控制器的上一级响应者是它父控制器的view,最终一直到window.
SDWebImage基本使用
http://www.jianshu.com/p/e614270a53c7
clear 先把之前的缓存文件夹删除掉,然后在新建一个文件夹
clean 先删除过期的文件,然后计算剩余缓存文件的大小(currrentSize)>maxSize,继续删除,按照它缓存文件创建的时间删除,直到(currrentSize)<=maxSize
一周
NSCache
6条
两种:先进先出和先进后出
实现:依赖来实现的
沙盒下的default下
对URL进行MD5加密
得到二进制的第一个字节
NSURLConnection这个类,用代理方法下载图片
15秒
-------------------加餐---------------------
监听系统发出的警告通知,然后清空内存缓存
NSCache使用方法和可变字典类似80% 它线程安全 可设置缓存成本 ,通过代理方法能拿到被处理的对象
可以自动清理缓存数据
长宽缩放比例*缩放比例
image.size.height * image.size.width * image.scale * image.scale
因为内部设置了一个黑名单 (内部是NSMutableset)
包括代理,这些都是同步的;监听和回调都是在同一个线程中执行
可以理解@selector()就是取类方法的编号,他的行为基本可以等同C语言中的函数指针,只不过C语言中,可以吧函数名之间赋给一个函数指针,而Objective-C的类不能之间应用函数指针,这样只能做一个@selector语法来取.
它的结果是一个SEL类型,这个类型的本质是累方法的编号(函数地址).方法以selector为索引.selector的数据类型是SEL定义成char*,我们可以把它想象成int .每个方法的名字对应一个唯一的值.
私有API是指存放在PrivateFrameworks框架中的API 是苹果明确不能使用的API 也可以说 一般在官方文档和头文件中看不到,但是实际存在于框架中的API 就是私有API,具体在提交应用的时候回自动检测.
私有API的存在很大一部分是为了保护隐私和系统安全,进制开发者使用这些功能.但是由于Objective-C的动态特性 ,使得实际上不可能存在真正意义的阻止调用这些API.
frame的位置是相对父空间的左上角来说的 参照的是父类的坐标系,指的是空间在父控件内的位置和大小
bounds的位置是相对控件自身的左上角来说的,参照的是自身坐标系,指的是自己本身的大小
NSTimer 可以调用invalidate进行撤销,创建和撤销必须在同一线程
NSTimer需要交定时器添加到当前的runloop中
它的时间单位是秒
GCD一旦执行就不能撤销
GCD中的定时器不受runloop模式的影响
时间单位是纳秒
将应用程序的数据文件保存在该目录下.不过这些数据类型仅限于不可以再生的数据,可再生的数据文件应该存在LIbrary/Cache下
各种临时文件, 保存应用再次启动时不需要的文件.而且,当应用不在需要这些文件时应主动将其删除,因为该目录下的东西随时有可能被系统清除,目前已知的一种可能清理的原因是系统磁盘存储空间不足的时候
MVC是一种设计模式,它强制的将应用程序的输入、处理、和输出分开。使用了MVC的应用程序被分为3个核心部件:试图(View)、模型(Model)、控制器(Controller)。它们各司其职,既分工明确又相互合作。
首先视图接受用户输入请求,然后将请求传递给控制器,控制器再调用某个模型来处理用户的请求,在控制器的控制下,再将处理后的结果交给某个视图进行格式化输出给用户。MVC不仅实现了功能模块和显示模块的分离,同时它还提高了系统的可维护性、可扩展性和组件的可复用性.
iOS分为显式动画,隐式动画
UIKit是iOS上的AppKit的变种,用于为iOS应用程序提供界面对象和控制器。
与AppKit类似,UIKit框架有UIResponder,也采用事件(UIEvent类)机制。
另外,iOS上的应用程序都是一个UIApplication实例。 所有的iOS应用程序都基于UIKit ,它提供了在屏幕上绘制的机制,捕获事件,和创建通用用户界面元素。
UIKit也通过管理显示在屏幕上的组件来组织复杂的项目。
使用UIKit可以:
• 构建和管理你的用户界面
• 捕获触摸和基于移动的事件
• 呈现文字和web内容
• 优化你的多任务程序
• 创建定制的用户界面元素
第一次握手:客户端发送syn(syn=j)包到服务器;并进入SYN_SEND状态,等待服务器确认
第二次握手:服务器收到syn包,确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
注意:三次握手中发送的包不包含数据,三次握手完毕,客户端和服务器才正式开始传送数据。TCP连接一旦建立,在通信双方的任何一方主动关闭连接之前,TCP连接都将被一直保持下去
对象呗释放的时候,指向nil
如果两件事有依赖关系,事件二必须等到事件一执行完毕才执行,那么放在一个线程就可以了,如果两者并没有什么关联,放到两个线程并发执行效率较高
NSSet: 里面存放的元素是无序的,不重复的,可以通过anyObject来访问单个元素.在搜索一个一个元素时NSSet比NSArray效率高,主要是它用到了数据结构中的哈希算法,而NSArray则是需要遍历全部的数组元素,效率会低一些.
NSArray : 里面存放的元素是有序的,可以有重复的对象,可以通过下标来访问里面的数组元素
当两个对象互相引用的时候,一端用strong,另一端必须用weak .例如: A拥有B, B也拥有A, 那么必须一方使用weak
一般UI控件都可以使用weak,因为自身已经对它进行一次强引用,没有必要再强引用一次.
NSArray,NSDictionary,NSSet,以及他们的可变类
存放二进制的有NSData类
viewDidLoad方法
controller 是被系统用强指针引用者 只要它存在 那么里面的子控件也就存在 controller强引用着它的view controller又强引用着它的数组对象subviews 数组对象又强引用着它所包含的数组内容 那么创建出来的一个UI控件将其加入subviews的时候 那么就会被一个强指针所引着它
内存的合理使用 当控件我们需要的时候就已经有一个强引用在引用着它 我们就不必再弄一个强指针来强引用它 当我们不需要的时候 weak直接释放掉 用strong的话就还会保留它 这就还占着内存了.
iOS设备内存有限 如果使用UITableView显示非常多的数据 就需要非常多的UI TableViewcell
那么设备的内存就会耗尽 解决该问题就需重用 UITableView 对象
当滚动出列表的时候 部分UITableViewCell 会移出窗口 UITableView会将窗口外的UITableVIewcell 放入一个对象缓存池中
当UITableView 要求dataSource 返回UITableView时 dataSource 会先查看缓存池中是否有未使用的UITableViewCell 有就用新的数据配置这个UITableViewCell 重新使用到窗口 就避免了重新创建对象
abstract修饰,它只能用来作父类,本身并没有生成实例的能力
它将一类最公有的属性和方法抽取出来抽象类是将类共有的方法抽取出来,声明为抽象方法, 抽象方法只有声明没有具体的实现, 拥有抽象方法的类就是抽象类; 这样新增一种类型时候只需要继承抽象类,实现抽象方法就可以了,降低了实现新类的难度。
抽象方法修饰符 abstract 抽象类不能被实现
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
为什么要有抽象类?
用于类型隐藏在面向对象领域,抽象类主要用来进行类型隐藏。我们可以构造出一个固定的一组行为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类。
用于拓展对象的行为功能
这一组任意个可能的具体实现则表现为所有可能的派生类(子类),模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体,因此它可以是不允许修改的;同时,通过从这个抽象体派生,也可扩展此模块的行为功能。
没事
Runloop和线程的关系:一个Runloop对应着一条唯一的线程
懒加载,指得是需要用到的时候才加载,其好处是节省内存空间,不必一开始就创建所有的变量,用到了就创建一块内存,同时也加快了程序运行速度.一般用于我们只需要创建一次的变量就可以的地方,例如字典转模型的数组,以及控制器的view等,都是懒加载的
perform selector
NSTimer
GCD:dispatch_after
用过
CoreText是用于处理文字和字体的底层技术。Quartz能够直接处理字体(font)和字形(glyphs),将文字渲染到界面上,它是基础库中唯一能够处理字形的模块。因此,CoreText为了排版,需要将显示的文本内容、位置、字体、字形直接传递给Quartz。相比其它UI组件,由于CoreText直接和Quartz来交互,所以它具有高速的排版效果。
coreImage是IOS5中新加入的一个Objective-c的框架,提供了强大高效的图像处理功能,用来对基于像素的图像进行操作与分析. iOS提供了很多强大的滤镜(Filter),其中IOS5中有48种,而到了最新的IOS6 Filter已经增加到了93种之多,并且这一数字会继续增加。这些Filter提供了各种各样的效果,并且还可以通过滤镜链将各种效果的Filter叠加起来,形成强大的自定义效果,如果你对该效果很满意,还可以子类化滤镜
POST:将参数放在请求体中,参数的大小原则上没有限制一般传输的数据包含隐私相关的用POST
GET:将参数附加在URL后面,因为URL长度的限制,所以参数的大小是有限制的,通常不能超过1KB
1 在设置断点的地方,选Add Exception Breakpoint.之后crash就会停在出错的位置.
2 如果是在测试阶段报错的话,可以在(设置 - 通用 -关于本机 -诊断与用量)里面看到崩溃的堆栈信息.
3如果用RAC的话,访问到已经释放了的内存,和内存警告这2种粗出错的几率高一些
直接修改view的样式,系统提供好的了
view.layer.cornerRadius = 6;
view.layer.masksToBounds = YES;
用layer做就可以了,十分简单.需要库QuartzCore.framework;
画矩形直接利用UIBezierPath给我们封装好的路径方法
(x,y)点决定了矩形左上角的点在哪个位置
(width,height)是矩形的宽度高度
bezierPathWithOvalInRect:CGRectMake(x, y, width, height)
[UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 100, 100)];
圆角矩形的画法多了一个参数,cornerRadius
cornerRadius它是矩形的圆角半径.
通过圆角矩形可以画一个圆.当矩形是正方形的时候,把圆角半径设为宽度的一半,就是一个圆.
UIBezierPath*path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(50,50,100,100) cornerRadius:50];
扇形:
画扇形的方法为:先画一个圆孤再添加一个一根线到圆心,然后关闭路径.
关闭路径就会自动从路径的终点到路径的起点封闭起下
用填充的话,它会默认做一个封闭路径,从路径的终点到起点.
[path fill];
Cocoa Touch提供了4中 Core Animation 分别是交叉淡化 推挤 显示和覆盖.
不能向编译后得到的类中增加实例变量
因为编译后的类以及注册在runtime中,类结构同中objc_ivar_list实例变量的链表和instance_size实例变量的内存大小已经确定
同时runtime会调用class_setlvarLayout或class_setWeakIvarLayout来处理 strong weak 引用。所以不能向存在的类中添加实例变量
能向运行时创建的的类添加实例变量运行时创建的类是可以添加实例变量,调用 class_addIvar 函数。但是得在调用 objc_allocateClassPair 之后,objc_registerClassPair 之前,原因同上。
2)程序运行后,查看log信息,找到错误的地方
3)在错误的地方设置断点进行调试,可以加条件断点
4)查看断点运行的信息,进行修改
5).如果是在测试阶段报错的话,可以在(设置-通用-关于本机-诊断与用量)里面看到崩溃的堆栈信息。
6).如果用rac的话,访问到已经释放了的内存,和内存警告这2种出错几率要高些。
NSDictionary 使用Hash表实现Key/Object存储;
Hash表是一种访问速度很快的数据结构,前提是Hash函数设计合理,能够使数据在各个子节点均匀分布,这一点使用NSString对象可以保证,这是文档中的说明:
Classes such as NSString that are part of Foundation have a good hash function.
永远不写retain,release和autorelease三个关键字就好~这是ARC的基本原则。
KVO:只能监听属性值的变化,而且有一定的弊端;
当程序接到内存警告时View Controller将会收到这个消息:didReceiveMemoryWarning
从iOS3.0开始,不需要重载这个函数,把释放内存的代码放到viewDidUnload中去。
这个函数的默认实现是:检查controller是否可以安全地释放它的view(这里view指的是controller的view属性),比如view本身没有superview并且可以被很容易地重建(从nib或者loadView函数)。
如果view可以被释放,那么这个函数释放view并调用viewDidUnload。
你可以重载这个函数来释放controller中使用的其他内存。但要记得调用这个函数的super实现来允许父类(一般是UIVIewController)释放view。
如果你的ViewController保存着view的子view的引用,那么,在早期的iOS版本中,你应该在这个函数中来释放这些引用。而在iOS3.0或更高版本中,你应该在viewDidUnload中释放这些引用。
NSNumber存放数字,NSValue可以存放CGrect
沙箱模型就是指iOS的每一个程序对应到APP自己的一个目录,这个目录只有这个应用有读写权限,其他任何APP都没有这个目录的读写权限。这个APP对应的这个目录,就好比是这个app的沙箱。
沙箱的作用就是保证APP数据的安全性,防止恶意软件、病毒等窃取信息。
阻塞模式和非阻塞模式的主要区别在于无请求来到时,阻塞模式会一直停在接收函数即accep函数,直到有请求到来才会继续向下进行处理。
而非阻塞模式下,运行接收函数,如果有请求,则会接收请求,如果无请求,会返回一个负值,并继续向下运行。一般来说,使用阻塞模式
的程序比较多,因为阻塞模式是由内核保障等待请求的,当他阻塞时不占用系统资源,而非阻塞模式需要我们人工轮询,占用资源较多。
另外,阻塞模式可以使用select函数设置超时时间,具体可以参考相关书籍。
在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息
CSS中有两种阴影效果,一种是DropShadow(投影),另一种是Shadow(阴影).
(1)DropShadow
语法
{FILTER:DropShadow(Color=color,OffX=offX,OffY=offY,Positive=positive)}
Color 代表投影的颜色,格式为“#RRGGBB”
OffX 和 OffY 代表x和y方向的投影偏移量。必须用整数值,正数代表x轴的右方向和y轴的下方向。负值相反。
Positive 参数是一个布尔值。值为true(非0),那么就为任何的非透明像素建立可见的投影。如果值为false(0),那么就为
透明的像素部分建立可见的投影。
(2)Shadow
语法
{FILTER:Shadow(Color=color,Direction=direction)}
Color 代表阴影的颜色,格式为“#RRGGBB”
Direction是设置投影的方向,按照顺时针方向进行,0度代表垂直向上,然后每45度为一个单位。默认值是向左的270度。共8个方向。
不是,只能加到RunLoop中特定模式下才能工作;不需要,因为它只在单一线程工作
可以,父类遵守的协议,子类也会继承这个协议
第一阶段:应用程序把要发送的消息 目的iPhone的标识打包,发给APNS.
第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找 有相应标识的iPhone,并把消息发送到iPhone.
第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知
if(IOS8_OR_LATER && [UINavigationBar conformsToProtocol:@protocol(UIAppearanceContainer)]) {
[[UINavigationBar appearance] setTranslucent:NO];
}
storyboard segue show
原因:在iOS7下如果没有设置navigationController为initController,show会自动将push转换成modal。简而言之就是在sb里每个show的segue
解决:保证它的初始位置有个navigationController。
constrain to margin
原因:这是设置了constrain to margins的关系,这玩意也是iOS8后才有的
一般使用retain或者strong修饰属性时,是使用引用对象的指针指向同一对象,即为同一块内存地址.只要其中有一个指针变量被修饰时所有其他引用该对象的变量都会被改变
而使用copy关键字修饰在赋值时是释放旧对象,拷贝新对象内容.重新分配了内存地址.以后该指针变量被修改时就不会影响旧对象的内容了.
copy只有实现了NSCopying协议的对象类型才有效,常用于NSString和Block
@@property (copy) NSMutableArray *array;
当一个NSMutableArray对象使用initWithArray: 初始化方法创建时,并将该对象赋值给了array属性。那么之后array执行可变数组的方法,如: removeObjectAtIndex: 时会出现unrecognized selector sent to instance的崩溃。原因在于array属性在被赋值(setter)的时候默认执行了copy方法后变为了不可变NSArray对象。
该类必须要实现NSCopying协议。实现 - (id)copyWithZone:(NSZone *)zone; 方法。
重写copy关键字的setter时,需要调用一下传入对象的copy方法。然后赋值给该setter的方法对应的成员变量。
Xcode自带检测工具.
property在编译时编译器会自动的为我们生成一个私有成员变量和setter与getter方法的声明和实现.反编译property大致生成五个东西
@property有两个对应的词,一个是@synthesize,一个是@dynamic。如果@synthesize和@dynamic都没写,那么默认的就是@syntheszie var = var,var为property变量。可以手动修改属性var对应的实例变量。例如:@syntheszie var = var1
@synthesize的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上这两个方法, 在Xcode4.4之后的版本可以省略不写.
@dynamic告诉编译器不要自动生成成员变量的getter和setter方法,而是开发者自己手工生成或者运行时生成.
使用copy的目的是为了让本对象的属性不受外界影响,使用copy无论给我传入一股可变对象还是不可对象,我本身就是一股不可变副本.
如果使用strong.这个属性有可能指向一个可变对象,如果这个可变对象呗外部意外的修改了,由于可变对象呗改变之后起始地址不会发生变化.而strong修饰的属性依然会指向这块内存地址,下次读取的时候就会是被改变以后的对象了, 也就是说strong可能会被外部意外修改.
一般使用nonatomic
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,
优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
下面是volatile变量的几个例子:
1) 并行设备的硬件寄存器(如:状态寄存器)
2) 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3)多线程应用中被几个任务共享的变量
可以是
尽管这种情况并不常见,但它还是可以,例如
当一个中断服务子程序企图去修改一个指向一个buffer指针的时候.
优点
缺点
栈:向低地址扩展的数据结构,是一块连续的内存的区域。栈顶的地址和栈的最大容量是 系统预先规定好的,从栈获得的空间较小。
堆:向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
ObjC Runtime 其实是一个 Runtime 库,基本上用 C 和汇编写的,这个库使得 C 语言有了面向对象的能力。这个库做的事情就是加载类的信息,进行方法的分发和转发之类的。OC是一种面向runtime(运行时)的语言,也就是说,它会尽可能地把代码执行的决策从编译和链接的时候推迟到运行时。这给程序员写代码带来很大的灵活性,比如说你可以把消息转发给你想要的对象,或者随意交换一个方法的实现之类的。这就要求runtime能检测一个对象是否能对一个方法进行响应,然后再把这个方法分发到对应的对象去。我们拿 C 来跟 ObjC 对比一下。在 C 语言里面,一切从 main 函数开始,程序员写代码的时候是自上而下地,一个 C 的结构体或者说类吧,是不能把方法调用转发给其他对象的。这个问题其实涉及到两个概念,运行时和多态。 简单来说,运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。 多态:不同对象以自己的方式响应相同的消息的能力叫做多态。意思就是假设生物类(life)都用有一个相同的方法-eat; 那人类属于生物,猪也属于生物,都继承了life后,实现各自的eat,但是调用是我们只需调用各自的eat方法。 也就是不同的对象以自己的方式响应了相同的消息 响应了eat这个选择器。因此也可以说,运行时机制是多态的基础。比如KVO中我们就用了。
单例设计模式,一个类只有一个实例,而且该实例易于外界访问,方便对实例个数的控制并节约系统资源。类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法。在程序中,我需要一系列的对象,他们每一个内部都包含有一组变量和功能,是静态的,而且整个程序都只需要拥有一个该类的对象。例如:
1.登陆界面(点击多个地方都弹出相同的控制器);
2.管理数据库;
3.音效控制;
4.文件处理:
5.封装网络工具类等等...
object_c比C++稍慢,是因为object_c的一些语言特性,比如反射,影响了执行效率。区别主要有以下一些方面。
代理优势:
1.语法严格,将要监听的事件必须是delegate协议中有清晰的定义
2.如果delegate中的一个方法没有实现那么就会出现编译警告/错误
3.在一个应用中的控制流程是可跟踪的并且是可识别的;
4.在一个控制器中可以定义定义多个不同的协议,每个协议有不同的delegate
5.没有第三方对象要求保持/监视通信过程。
代理缺点
1.需要编写很多代码.
通知优点
1.不需要编写太多代码,实现比较简单.
2.对于一个发出的通知,多个对象能够做出反应,即1对多的方式实现简单.
3.controller能够传递context对象(dictionary),context对象携带了关于发送通知的自定义的信息
4.层级结构比较深的时候用.
通知缺点
1.在编译期不会检查通知是否能够被观察者正确的处理;
2.在释放注册的对象时,需要在通知中心取消注册;
3.在调试的时候应用的工作以及控制过程难跟踪;
4.观察者需要提前知道通知名称.
5.通知发出后,controller不能从观察者获得任何的反馈信息。
KVO优点
1.能够提供一种简单的方法实现两个对象间的同步。
2.能够对非我们创建的对象,即内部对象的状态改变作出响应.
KVO缺点
1.我们观察的属性必须使用strings来定义。因此在编译器不会出现警告以及检查;
2.它只能用来对属性作出反应,而不会用来对方法或者动作作出反应.
3.需要手动移除观察者。
怎么都做不到
BASE64是网络传输中最常用的编码格式 - 用来将二进制的数据编码成字符串的编码方式.
1> 能够编码,能够解码.
2> 被很多的加密算法作为基础算法.
可以绕过运营商,通过标准TCP/IP网络直接向这些手机发送消息.这些消息就称为推送消息.推送消息是通过Apple和Google掌控的互联网服务器发送的.推送消息从根本上就是设计用于与应用程序通信的.它们可以发送文本,多媒体文件和特定于应用程序的数据,例如警告声音和显示在应用程序图标上的标记等.
一系列方法的声明,某个类遵守了某个协议就拥有了该协议的所有方法的声明.就必须实现协议中规定的@require的方法.