用枚举表示状态、选项、状态码

来源 ——《Effective Objective-C 2.0 》Matt Galloway

由于OC基于C语言,所以C语言的功能它都有。其中之一就是枚举类型:enum。系统框架中频繁用到此类型,然而开发者容易忽视它。在以一系列常量来表示错误状态码或可组合的选项时,使用枚举为其命名是常见的。由于C++11标准扩充了枚举的特性,所以最新版系统框架使用了“强类型”(strong type)的枚举。没错,OC也能得益于C++11标准。

枚举只是一种常量命名方式。某个对象所经历的各种状态就可以定义为一个简单的枚举集(enumeration set)。比如说,可以用下列枚举表示“套接字连接”(socket connection)的状态:

由于每种状态都用一个便于理解的值来表示,所以这样写出来的代码更易读懂。编译器会为枚举分配一个独有的编号,从0开始,每个枚举递增1。实现枚举所用的数据类型取决于编译器,不过其二进制位(bit)的个数必须能完全表示枚举编号才行。在范例中,由于最大编号是2,所以使用1个字节的char类型就可以。然而定义枚举变量的方式却不太简洁,要依据如下语法编写:

若是每次不用敲入enum而只需写EOCConnectionState就好了。要想这么做,则需要使用typedef关键字重新定义枚举类型:

现在可以用简写的EOCConnectionState来代替完整的enum EOCConnectionState了:

继续阅读用枚举表示状态、选项、状态码

多用字面量语法,少用与之等价的方法

来源 ——《Effective Objective-C 2.0 》Matt Galloway

编写OC程序时,总会用到某几个类,它们属于Foundation框架。虽然从技术上来说,不用Foundation框架也能写出OC代码,但实际上却经常用到此框架。这及各类是NSString、NSNumber、NSArray、NSDictionary。从类名上即可看出各自所表示的数据结构。

OC以语法繁杂而著称,事实上的确实这样。不过,从OC1.0起,有一种非常简单的方式创建NSString对象。这就是“字符串字面量”(string literal),其语法如下:

如果不用这种语法的话,就要以常见的alloc,然后init方法来分配并且初始化NSString对象了。在版本较新的编译器中,也能用这种字面量语法来声明NSNumber、NSArray、NSDictionary类的实例。使用字面量语法(literal syntax)可以缩减源代码长度,使其更为易读。 继续阅读多用字面量语法,少用与之等价的方法

@class与#import

来源 ——《Effective Objective-C 2.0 》Matt Galloway

与C和C++一样,OC也使用“头文件”(header file)与“实现文件”(implementation file)来分离代码。用OC语言编写的“类”(class)的标准方式为:以类名做文件名,分别创建两个文件,头文件后缀用.h,实现文件后缀用.m。创建好一个类以后,其代码看上去是这样的:

用OC语言编写任何类几乎都需要引入Foundation.h。如果不在该类本身引入这个文件的话,那么就要引入其父类所属框架相对应的“基本头文件”(base header file)。例如,在创建iOS应用程序时,通常会继承UIViewController类。而这些子类的头文件需要引入UIkit.h。

现在看来,EOCPerson类还好,虽然其头文件引入了整个Foundation框架。如果此类继承自Foundation框架中的某个类,那么EOCPerson的使用者(consumer)可能会用到其基类中的许过内容。继承UIViewController的那些类也是如此,其使用者可能会用到UIKit中的大部分内容。 继续阅读@class与#import

Objective-C语言的起源

来源 ——《Effective Objective-C 2.0 》Matt Galloway

OC语言和C++、Java等面向对象语言相似,但是在许多方面还是有差别的。比如OC使用消息结构(message structure)而不是函数调用(function calling)。OC语言由Smalltalk演化而来,后者是消息语言的鼻祖。消息结构和函数调用结构之间的区别简单来讲是这样的:

关键区别在于: 使用消息结构的语言,其运行时所应该执行的代码由运行时环境(run time)来决定;而使用函数调用的语言,则由编译器决定。如果范例代码中调用的函数是多态的,那么在运行时候就要按照“虚表”(virtual table:是编程语言为实现“动态派发”(dynamic dispatch)或者“运行时方法绑定”(run time method binding)而采用的一种机制)来检索应该执行哪个函数。如果使用消息结构的语言,不论是否多态,总是在运行时才会去查找索要执行的方法。实际上,编译器甚至不关心接收消息的对象的具体类型,这个也是在运行时处理的,其过程叫做“动态绑定”(dynamic binding)。 继续阅读Objective-C语言的起源

iOS远程推送

Apple Push Notification service(APNs)

 

registration_sequence_2x

推送服务的工作流程:
1.APP向系统注册推送服务。
2.设备从APNs请求deviceToken。
3.通过代理方法将deviceToken返回给APP。
4.APP将deviceToken发送给应用后台服务器(Provider)。
5.应用后台服务器保存deviceToken,然后在需要推送通知的时候,给APNs发送信息,使用deviceToken标识所要送达的客户端。
6.APNs将后台服务器发过来的数据推送到设备。
7.设备将消息分发给应用程序。
8.在使用推送功能的时候,需要在开发者中心创建支持Push Notification的证书,并且将证书和私钥用于应用后台服务器与APNs之间通信。

继续阅读iOS远程推送

Xcode常见错误总结

1.Undefined symbols for architecture i386 error
原因:在Build Phrases找到Compile Sources把报错的.m文件都加进去

2.duplicate symbols for architecture i386
原因:可能是应该引用.h的头文件的地方引用了.m文件造成的

3.’NSUnknownKeyException’, ………………setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key xxx.’
原因:xib中某个控件已经通过outlet连接到ViewController中的某个变量上了,后来变量删除了,但是这种连接关系没有删除,导致启动时找不到对应的key,抛出上述exception

4.libxml/xxx file not found in Xcode6:
原因:应该在 Build Settings -> Header Search Paths里设置:

不是之前的路径:

但是编译还是无法通过,怎么回事?记得在test的target中也要添加

iOS多线程GCD的使用

1.什么是GCD
GCD是Grand Central Dispatch的缩写,是苹果公司开发的一种基于block的并行操作机制。它由两部分组成,一是FIFO队列,二个是线程池,队列添加任务,线程池执行任务。其中FIFO队列称为dispatch queue,这保证了先进来的任务先得到执行,但不保证先结束。
dispatch queue分为下面两种:
第一种,Serial Dispatch Queue,线程池只提供一个线程,所以后一个线程必须等到前一个前程执行结束才能开始,顺序执行。
第二种,Concurrent Dispatch Queue,线程池提供多个线程,所以可以按照顺序启动多个线程,并发执行。 继续阅读iOS多线程GCD的使用

iOS的HTTP请求(GET,POST,同步,异步)

同步请求:可以从因特网请求数据,一旦发送同步请求,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作。
异步请求:不会阻塞主线程,而会建立一个新的线程来操作,用户发出异步请求后,依然可以对UI进行操作,程序可以继续运行。
GET请求:将参数直接写在访问路径上。操作简单,不过容易被外界看到,安全性不高,地址最多255字节。
POST请求:将参数放到body里面。POST请求操作相对复杂,需要将参数和地址分开,不过安全性高,参数放在body里面,不易被捕获。 继续阅读iOS的HTTP请求(GET,POST,同步,异步)

iOS加载图片的两种方法

一般情况下我们是这样加载图片的:
UIImage *image = [UIImage imageNamed:@”icon.png”];
这种方法在application bundle的顶层文件夹寻找由供应的名字的图象。如果找到,装载到iPhone系统缓存图象。那意味图片是放在内存里的,如果图很多很大那么运行起来要占很大的内存空间的。
所以,可以这么做
NSString *path = [[NSBundle mainBundle] pathForResource:@”icon” ofType:@”png”];
UIImage *image = [UIImage imageWithContentsOfFile:path];
这样做就没有缓存了,但是如果有高清图,也就是@2x的,就不能自动获取到了,自己把握吧,做UI可以用imageNamed,要处理的大图就推荐使用后面的方法。