iOS 网络编程模式总结
IOS 可以采用三类api 接口进行网络编程,根据抽象层次从低到高分别为socket方式、stream方式、url 方式。
一 、socket 方式
IOS 提供的socket 方式的网络编程接口为CFSocket。CFSocket是BSD sockets的抽象和封装,CFSocket提供BSD sockets几乎所有的功能,并与run loop集成,用来实现多线程网络编程和网络事件监听。基于 CFSocket可以实现各种类型的 socket编程,包括stream-based 的sockets(如tcp)和packet-based 的sockets(如udp)。需要注意的是在iOS中CFSocket接口在需要时不自动激活设备的 cellular modem或on-demand VPN。
CFSocket包括以下编程接口,包括Socket的 创建、配置,以及根据创建和配置好的Socket 进行 远程通讯等接口。
1 Socket的 创建
1 .1、CFSocketCreate
创建一个特定协议和类型的 CFSocket对象
1.2、CFSocketCreateWithSocketSignature
该接口根据一个包含通讯协议和地址的CFSocketSignature结构来创建一个CFSocket对象
1.3、 CFSocketCreateConnectedToSocketSignature
该接口在创建一个CFSocket对象的同时还与一个远端主机进行连接。
1.4、CFSocketCreateWithNative
该接口通过封装一个存在的 BSD socket来创建一个CFSocket对象。
2 Socket的配置
2.1 CFSocketCopyAddress
功能: 返回一个 CFSocket对象的本地地址。
语法:
SWIFT
func CFSocketCopyAddress(_ s: CFSocket!) -> CFData!
2.2、CFSocketCopyPeerAddress
功能:返回与一个 CFSocket对象连接的远端地址。
语法:
SWIFT
func CFSocketCopyPeerAddress(_ s: CFSocket!) -> CFData!
2.3 CFSocketDisableCallBacks
功能:临时取消一个CFSocket对象创建时指定的某种类型的事件回调。
语法:
SWIFT
func CFSocketDisableCallBacks(_ s: CFSocket!,
_ callBackTypes: CFOptionFlags)
2.4 CFSocketEnableCallBacks
功能:重新允许先前CFSocketDisableCallBacks函数取消的某种类型的事件回调。
语法:
SWIFT
func CFSocketEnableCallBacks(_ s: CFSocket!,
_ callBackTypes: CFOptionFlags)
2.5 CFSocketGetContext
功能:返回一个CFSocket对象的上下文信息。
语法:
SWIFT
func CFSocketGetContext(_ s: CFSocket!,
_ context: UnsafeMutablePointer<CFSocketContext>)
2.6 CFSocketGetNative
返回与一个CFSocket对象相关的本地 BSD socket。
语法:
SWIFT
func CFSocketGetNative(_ s: CFSocket!) -> CFSocketNativeHandle
2.7 CFSocketGetSocketFlags
功能:返回控制一个CFSocket对象的确定行为的 标志。
语法:
SWIFT
func CFSocketGetSocketFlags(_ s: CFSocket!) -> CFOptionFlags
2.8 CFSocketSetSocketFlags
功能:设置控制一个CFSocket对象的确定行为的 标志。
语法:
SWIFT
func CFSocketSetSocketFlags(_ s: CFSocket!,
_ flags: CFOptionFlags)
2.9 CFSocketSetAddress
语法:
SWIFT
func CFSocketSetAddress(_ s: CFSocket!,
_ address: CFData!) -> CFSocketError
功能:为一个CFSocket对象绑定一个本地地址并在本地socket支持的情况下对socket进行配置使其处于监听状态。该函数对应本地socket的 bind以及listen功能。一旦CFSocket对象绑定地址,依赖于socket的协议,其它进程和主机能连接到该CFSocket对象。
3、Sockets的使用
3.1 CFSocketConnectToAddress
功能:打开与一个远程socket的一个连接。
语法:
SWIFT
func CFSocketConnectToAddress(_ s: CFSocket!,
_ address: CFData!,
_ timeout: CFTimeInterval) -> CFSocketError
3.2 CFSocketCreateRunLoopSource
语法:
SWIFT
func CFSocketCreateRunLoopSource(_ allocator: CFAllocator!,
_ s: CFSocket!,
_ order: CFIndex) -> CFRunLoopSource!
功能:为一个CFSocket对象创建一个CFRunLoopSource对象。该创建的 CFRunLoopSource对象不自动添加到一个run loop。为了增加该run loop source到某个run loop,需要调用CFRunLoop对象 的CFRunLoopAddSource函数来为该CFRunLoop对象添加run loop source。
3.3 CFSocketGetTypeID
功能:返回CFSocket对象的 opaque类型对应的类型标示符。
语法:
SWIFT
func CFSocketGetTypeID() -> CFTypeID
3.4 CFSocketInvalidate
功能:使一个CFSocket对象无效,使其停止接收和发送任何消息。
语法:
SWIFT
func CFSocketInvalidate(_ s: CFSocket!)
3.5 CFSocketIsValid
功能:返回一个指示一个CFSocket对象是否有效及是否能够发送和接收消息的布尔值。
语法:
SWIFT
func CFSocketIsValid(_ s: CFSocket!) -> Boolean
3.6 CFSocketSendData
功能:该函数用来通过一个CFSocket对象发送数据。
语法:
SWIFT
func CFSocketSendData(_ s: CFSocket!,
_ address: CFData!,
_ data: CFData!,
_ timeout: CFTimeInterval) -> CFSocketError
二、stream编程模式
stream编程模式提供了与 unix 的文件操作类似的模式。首先创建和设置流,接着打开流,然后读写流,在流存在时还可以通过查询流的相关属性来读取流的相关信息,在流使用完毕后关闭流。
iOS 为stream编程模式提供的api编程接口包括两大类,一类是Core Foundation框架层用C语言实现的CFStream API(包括CFStream、 CFReadStream 、CFWriteStream等),一类是基于其上的在Foundation框架层用Objective-C语言实现的NSStream API(包括NSStream、NSInputStream NSOutputStream等),两者提供相似的接口和行为,其中某些对象是toll-free bridged类型的,如CFStream 与NSStream,CFReadStream与NSInputStream,CFWriteStream与NSOutputStream之间,因此可以混合使用。
开发人员可以根据自己的语言偏好选择使用。
CFStream API的主要接口:
1、CFStream 创建接口
1.1 CFStreamCreatePairWithPeerSocketSignature
功能:创建一对到一个socket的可读和可写流。
1.2 CFStreamCreatePairWithSocketToHost
功能:创建连接到一个特定主机的特定端口的一对可读写流。
1.3 CFStreamCreatePairWithSocket
功能:创建一对连接到一个socket的可读写流
1.4 CFStreamCreateBoundPair
功能:创建一对读写流。
其它可读写流创建接口:
1.5 CFReadStreamCreateForHTTPRequest
功能:为一个CFHTTP请求创建一个可读流。
1.6 CFReadStreamCreateForStreamedHTTPRequest
功能:为一个HTTP请求的body保持在内存的CFHTTP请求创建一个可读流。
1.7 CFReadStreamCreateWithFTPURL
功能:创建一个FTP可读流
1.8 CFWriteStreamCreateWithFTPURL
功能:创建一个FTP可读流
2. CFReadStream接口
2.1 流的打开和关闭
CFReadStreamOpen
CFReadStreamClose
2.2 读取数据
CFReadStreamRead
2.3. 调度一个可读流
CFReadStreamScheduleWithRunLoop(_:_:_:)
CFReadStreamUnscheduleFromRunLoop(_:_:_:)
2.4 检查可读流的属性
CFReadStreamCopyProperty(_:_:)
CFReadStreamGetBuffer(_:_:_:)
CFReadStreamCopyError(_:)
CFReadStreamGetError(_:)
CFReadStreamGetStatus(_:)
CFReadStreamHasBytesAvailable(_:)
2.5 设置可读流的属性
CFReadStreamSetClient(_:_:_:_:)
CFReadStreamSetProperty(_:_:_:)
2.6 得到 CFReadStream的 Type ID
CFReadStreamGetTypeID()
3.CFWriteStream 相关接口
3.1 CFWriteStreamClose(_:)
3.2 CFWriteStreamOpen(_:)
3.3 CFWriteStreamWrite(_:_:_:)
3.4 CFWriteStreamScheduleWithRunLoop(_:_:_:)
3.5 CFWriteStreamUnscheduleFromRunLoop(_:_:_:)
3.6 CFWriteStreamCanAcceptBytes(_:)
3.7 CFWriteStreamCopyProperty(_:_:)
3.8 CFWriteStreamCopyError(_:)
3.9 CFWriteStreamGetError(_:)
3.10 CFWriteStreamGetStatus(_:)
3.11 CFWriteStreamSetClient(_:_:_:_:)
3.12 CFWriteStreamSetProperty(_:_:_:)
3.13 CFWriteStreamGetTypeID()
CFStream API的使用步骤:
1) 利用流创建接口创建相关流;
2)、调用CFReadStreamSetClient (可读流)或CFWriteStreamSetClient (可写流)来登记要接收的流相关的事件;
3)、调用CFReadStreamScheduleWithRunLoop(可读流)或CFWriteStreamScheduleWithRunLoop(可写流)来使在流在一个run loop上进行调度以便接收相关事件;
4)、调用CFReadStreamOpen 或CFWriteStreamOpen 来打开已创建的流;
5)、在读取流的创建时登记的回调中,在接收到kCFStreamEventHasBytesAvailable事件时来读取数据, 在可写流已登记的回调中,在接收到kCFStreamEventCanAcceptBytes 事件时开始发送数据或请求;
6) 数据传输完成,关闭和释放打开和创建的相关流;
2、NSStream API的使用
在ios 中由于NSStream类不支持 与一个远程主机连接,而CFStream支持,因此为了使用 NSStream,你需要使用流创建函数CFStreamCreatePairWithSocketToHost或CFStreamCreatePairWithSocketToCFHost来打开一个与远程主机连接的socket并分配一对CFStream 对象(CFReadStream和CFWriteStream),并cast这些对象到NSStream 对象(对应NSInputStream 和 NSOutputStream)。从而可以使用NSStream类的相关接口进行相关网络编程。如设置接收网络事件的代理对象,调度到当前的run loop,然后打开它们进行相应处理。
代码片段如下:
{ NSURL *website = [NSURL URLWithString:urlStr]; if (!website) { NSLog(@"%@ is not a valid URL"); return; } CFReadStreamRef readStream; CFWriteStreamRef writeStream; CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)[website host], 80, &readStream, &writeStream); NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream; NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream; [inputStream setDelegate:self]; [outputStream setDelegate:self]; [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [inputStream open]; [outputStream open]; /* Store a reference to the input and output streams so that they don't go away.... */ ... }
在NSStream对象打开后,当接收到相关的stream-event网络消息,其代理对象中的handleEvent: 函数被调用,从而进行流相关的网络消息处理, 如发送相关协议的请求或接收应答等。以下为handleEvent: 函数进行事件处理的代码片段:
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode { NSLog(@"stream:handleEvent: is invoked..."); switch(eventCode) { case NSStreamEventHasSpaceAvailable: { if (stream == oStream) { NSString * str = [NSString stringWithFormat: @"GET / HTTP/1.0\r\n\r\n"]; const uint8_t * rawstring = (const uint8_t *)[str UTF8String]; [oStream write:rawstring maxLength:strlen(rawstring)]; [oStream close]; } break; } // continued ... } }
三、url 编程模式
url 编程模式通过URL 的方式来实现网络编程,任何要存取的网络资源(包括局域网和广域网)都可以用一个URL来表示和存取,并支持设备间的资源共享。url 编程模式系统提供http, https, file, ftp, data等五种协议支持,并允许用户自己开发和登记相关类来支持另外的应用层网络协议,进行协议的扩展。
url 编程模式在IOS系统可以使用两种编程接口:NSURLSession 和NSURLConnection。
对于iOS 7 以后的最新系统推荐使用NSURLSession API,对于老版本由于不支持NSURLSession,因此必须使用NSURLConnection API。
NSURLSession编程模式是对相关的连接请求通过一个会话来完成,应用通过创建一系列sessions来实现网络通讯,每一个session协调一组相关数据的传输任务。在每一个session内,应用添加一系列任务,每一个任务表现一个特定URL 请求。
NSURLSession相比NSURLConnection的优点是支持在应用挂起、停止或crashed时能够在后台继续下载数据,即支持任务的取消、重启(恢复)、挂起,以及支持从已挂起、取消或失败的下载中重新恢复下载的能力。
对于简单的请求,还可以直接通过一个简单的NSURL对象来发出请求,并使用一个NSData内存对象或者一个文件的方式来引出NSURL指向的内容。而NSURLConnection API只能通过构造一个NSURLRequest对象或其子类来发出URL请求来请求下载或上传URL数据。 使用一个NSURLRequest请求对象封装一个URL请求,例如HTTP协议方法,除了可以封装一些协议特定的属性外,还可以规定任意本地cached数据的使用策略。
对于NSURLRequest请求对象的应答包括两部分:描述内容的元数据metadata及内容数据本身。两种API对于使用NSURLRequest请求接收的元数据metadata都由NSURLResponse类来封装,其中包含MIME类型、内容长度、编码及提供应答的URL等内容。NSURLResponse协议特定的子类还能提供额外的元数据,如NSHTTPURLResponse提供协议头和WEB服务器返回的状态码 等信息。
NSURLSession API的使用:
NSURLSession类支持三种会话类型(默认会话类型、临时会话、后台会话)以及三种类型的任务(数据任务、下载任务、上传任务)。
数据任务使用NSData 对象来发送和接收内存数据,不存储数据到一个文件,因此不支持后台会话。
下载任务以一个文件的形式引出数据,并支持在应用没有运行时的后台下载。
上传任务用来上传数据(文件),也能够支持应用没有运行时的后台上传。
默认会话和后台会话的区别是后台会话使用一个分离的进程处理所有的数据传输任务,并带有一些限制:后台会话必须使用特定应用代理来提供事件提交,并仅支持HTTP和HTTPS 协议,不支持其它定制协议,并仅支持上传和下载任务,不支持数据任务。
临时会话不存储任何数据到磁盘,所有接收的内容都保存到与会话关联的RAM中,当会话无效时,RAM中接收的内容自动被清除。
NSURLSession API的使用步骤:
1 、创建一个NSURLSessionConfiguration配置对象
NSURLSessionConfiguration配置对象提供广泛的配置选项,包括:
1)、特定于单个会话的私有数据存储,包括caches, cookies, credentials, 和protocols;
2)、与一个特定请求或一个会话关联的Authentication;
3)、与一个主机的最大连接数;
4)、与一个资源关联的超时;
5)、最小和最大TLS版本支持;
6)、定制的代理词典;
7)、cookie策略的控制;
8)、HTTP pipelining行为的控制
2、根据配置创建相应的NSURLSession;
如下代码片段展示了根据不同的配置对象创建不同类型的NSURLSession会话对象。
/* Create a session for each configurations. */
self.defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
self.backgroundSession = [NSURLSession sessionWithConfiguration: backgroundConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
self.ephemeralSession = [NSURLSession sessionWithConfiguration: ephemeralConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
NSURLSession API通过代理来实现异步URL内容存取,代理可以是系统提供的代理,还可以是应用提供的特定代理对象。任务对象当从服务器接收到数据或传输完成时调用这些代理对象的方法。
在创建会话指定相应的代理对象。
3、为会话添加任务;
使用如下方法来添加数据任务到一个会话。
dataTaskWithURL(_:)
dataTaskWithURL(_:completionHandler:)
dataTaskWithRequest(_:)
dataTaskWithRequest(_:completionHandler:)
使用如下方法来添加下载任务到一个会话。
downloadTaskWithURL(_:)
downloadTaskWithURL(_:completionHandler:)
downloadTaskWithRequest(_:)
downloadTaskWithRequest(_:completionHandler:)
downloadTaskWithResumeData(_:)
downloadTaskWithResumeData(_:completionHandler:)
使用如下方法来添加上传任务到一个会话
uploadTaskWithRequest(_:fromData:)
uploadTaskWithRequest(_:fromData:completionHandler:)
uploadTaskWithRequest(_:fromFile:)
uploadTaskWithRequest(_:fromFile:completionHandler:)
uploadTaskWithStreamedRequest(_:)
如下是数据任务创建代码片段:
NSURL *url = [NSURL URLWithString: @"http://www.example.com/"]; NSURLSessionDataTask *dataTask = [self.defaultSession dataTaskWithURL: url]; [dataTask resume];
下面是下载任务创建代码片段:
NSURL *url = [NSURL URLWithString: @"https://developer.apple.com/library/ios/documentation/Cocoa/Reference/" "Foundation/ObjC_classic/FoundationObjC.pdf"]; NSURLSessionDownloadTask *downloadTask = [self.backgroundSession downloadTaskWithURL: url]; [downloadTask resume];
4、使用代理方法接收数据及状态信息
会话的数据任务在使用应用特定代理接收数据时必须实现如下两个代理方法:
URLSession:dataTask:didReceiveData:
一次一片的提供请求的数据给会话任务。
URLSession:task:didCompleteWithError:
指示请求数据已经全部接收。
会话的下载任务在下载文件时应该实现如下代理方法:
URLSession:downloadTask:didFinishDownloadingToURL:
下载内容存储到一个URL指定的一个临时文件,在该方法返回之前,必须把临时文件的内容移到一个永久位置,而临时文件被删除。
URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
为应用提供关于当前下载进度的状态信息
URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:
告诉应用已经从从先前的失败下载中恢复。
URLSession:task:didCompleteWithError:
告诉应用下载已经失败。
下载失败恢复处理:
在应用使用cancelByProducingResumeData: 方法取消下载任务时,可以使用downloadTaskWithResumeData: 或 downloadTaskWithResumeData:completionHandler:方法重新创建一个新下载任务并传送cancelByProducingResumeData:产生的恢复数据从而接着继续下载。
在传输失败时,如果任务可恢复,则调用URLSession:task:didCompleteWithError: 方法。在传送给URLSession:task:didCompleteWithError: 方法的参数NSError中的 userInfo 词典中包含键值为NSURLSessionDownloadTaskResumeData的恢复数据,因此可以使用downloadTaskWithResumeData: 或 downloadTaskWithResumeData:completionHandler:方法重新创建一个新下载任务来接着恢复数据继续下载。
系统代理仅能支持基本的URL资源存取任务,不支持认证和后台下载,并且还必须提供一个completion handler block来把返回的URL数据提交到应用。如下是一个使用系统代理的代码例子:
NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]]; [[delegateFreeSession dataTaskWithURL: [NSURL URLWithString: @"http://www.example.com/"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSLog(@"Got response %@ with error %@.\n", response, error); NSLog(@"DATA:\n%@\nEND DATA\n", [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding]); }] resume];
会话的上传任务的任务创建和相关代理方法:
会话的上传任务使用HTTP POST方法来上传数据。可以以一个NSData对象、一个文件或使用一个流为HTTP POST请求的body提供内容。
在以NSData对象提供上传数据时,应用调用uploadTaskWithRequest:fromData: 或uploadTaskWithRequest:fromData:completionHandler: 方法来创建上传任务。
在以文件形式提供上传数据时,应用调用uploadTaskWithRequest:fromFile: 或 uploadTaskWithRequest:fromFile:completionHandler:方法来创建上传任务
在以流方式提供上传数据时,应用调用uploadTaskWithStreamedRequest:方法来创建上传任务。
应用特定代理可以通过实现URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:方法来获得上传进度信息。
iOS 网络编程模式总结的更多相关文章
- iOS网络编程模型
iOS网络编程层次结构也分为三层: Cocoa层:NSURL,Bonjour,Game Kit,WebKit Core Foundation层:基于 C 的 CFNetwork 和 CFNetServ ...
- IOS网络编程——第三方类库
IOS网络编程——第三方类库 目录 概述 ASIHttpRequest AFNetworking 其他 概述 ASIHttpRequest AFNetworking 其他
- IOS网络编程:HTTP
IOS网络编程:HTTP HTTP定义了一种在服务器和客户端之间传递数据的途径. URL定义了一种唯一标示资源在网络中位置的途径. REQUESTS 和 RESPONSES: 客户端先建立一个TCP连 ...
- iOS网络编程笔记——Socket编程
一.什么是Socket通信: Socket是网络上的两个程序,通过一个双向的通信连接,实现数据的交换.这个双向连路的一端称为socket.socket通常用来实现客户方和服务方的连接.socket是T ...
- 浅谈iOS网络编程之一入门
计算机网络,基本上可以抽象是端的通信.实际在通讯中会用到不同的设备,不同的硬件中,为了能友好的传输信息,那么建立一套规范就十分必要了.先来了解一些基本概念 了解网络中传输的都是二进制数据流. 2.了 ...
- iOS 网络编程(HTTP协议)
HTTP协议的概念HTTP协议,Hyper Text Transfer Protocol (超文本传输协议)是用于从万维网服务器传送超文本到本地浏览器的传输协议,HTTP是一个应用层协议,由请求和响应 ...
- 从socket开始讲IOS网络编程
home list tags talk user rss Mac&iOS Socket 大纲 一.Socket简介 二.BSD Socket编程准备 1.地址 2.端口 3.网络字节序 4.半 ...
- iOS 网络编程:socket
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- ios网络编程(入门级别)-- 基础知识
在学习ios的过程中,停留在UI控件很长时间,现在正在逐步的接触当中!!!!!!在这个过程中,小编学到了一些关于网络编程知识,并且有感而发,在此分享一下: 关于网络请求的重要性我想不用多说了吧!!!对 ...
随机推荐
- JVM远程DEBUG(JPDA )
原理 1. JPDA简介 JPDA(Java Platform Debugger Architecture)为Java平台上的调试器定义了一个标准的体系结构.该体系结构包括3个主要组成部分:JVM T ...
- NuGet包断线续传下载
NuGet包断线续传下载(金庆的专栏)NuGet是VC的扩展,用来下载依赖包.NuGet下载没有断线续传,下载源又很容易断开. https://nuget.org/api/v2/ https:// ...
- AR模块常用函数
--AR模块常用函数 FUNCTION get_fnd_user_name ( p_user_id IN NUMBER ) return VARCHAR2 IS CURSOR c_user_name ...
- 基于Web在线考试系统的设计与实现
这是一个课程设计的文档,源码及文档数据库我都修改过了,貌似这里复制过来的时候图片不能贴出,下载地址:http://download.csdn.net/detail/sdksdk0/9361973 ...
- Android Multimedia框架总结(七)C++中MediaPlayer的C/S架构补充及MediaService介绍
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼,文章链接: http://blog.csdn.net/hejjunlin/article/details/52465168 前面一篇主要介绍 ...
- Android 在 SElinux下 如何获得对一个内核节点的访问权限
点击打开链接 Android 5.0下,因为采取了SEAndroid/SElinux的安全机制,即使拥有root权限,或者对某内核节点设置为777的权限,仍然无法在JNI层访问. 本文将以用户自定义的 ...
- Android View架构总结
View和Activity的区别 android的四大组件,Activity是四大组件中唯一一个用来和用户进行交互的组件.可以说Activity就是android的视图层. 如果再细化,Activit ...
- 【原创】Nginx+PHP-FPM优化技巧总结
php-fpm的安装很简单,参见PHP(PHP-FPM)手动编译安装.下面主要讨论下如何提高Nginx+Php-fpm的性能. 1.Unix域Socket通信 之前简单介绍过Unix Domain S ...
- (七十)Xcode5及以上对于状态栏和导航栏样式的设定方法
[状态栏] 在Xcode5以前,状态栏是通过UIApplication单例来管理的,而在此后,默认情况下状态栏通过控制器来管理,而且如果控制器有NavigationController,那么设置状态栏 ...
- java开源项目之IQQ学习记录之单例模式与log4j日志记录
作者:sushengmiyan 本文地址:http://blog.csdn.net/sushengmiyan/article/details/18992741 打开IQQ项目,打开包iqq.app中的 ...