详细解析几个和网络请求有关的类(二) —— NSURLRequest和NSMutableURLRequest

版本记录

版本号 时间
V1.0 2018.03.08

前言

我们做APP发起网络请求,一般都是使用框架,这些框架的底层也都是苹果的API,接下来几篇就一起来看一下和网络有关的几个类。感兴趣的可以看上面几篇文章。
1. 详细解析几个和网络请求有关的类 (一) —— NSURLSession

回顾

上一篇主要介绍了网络请求中最重要的类NSURLSession,并对其中的各种任何和协议进行了分析。这一篇主要讲述请求Request方面的内容。主要从两个类NSURLRequest及其子类NSMutableURLRequest出发,并进行了详细分析。


NSURLRequest

1. NSURLRequest本类

NSURLRequest本类接口如下所示,部分已增加说明和注释。

@interface NSURLRequest : NSObject <NSSecureCoding, NSCopying, NSMutableCopying>
{
    @private
    NSURLRequestInternal *_internal;
}

/*! 
    @method requestWithURL:
    @abstract Allocates and initializes an NSURLRequest with the given
    URL.
    @discussion Default values are used for cache policy
    (NSURLRequestUseProtocolCachePolicy) and timeout interval (60
    seconds).
    // 缓存策略的默认值是NSURLRequestUseProtocolCachePolicy,timeout值为60s

    @param URL The URL for the request.
    @result A newly-created and autoreleased NSURLRequest instance.
*/
+ (instancetype)requestWithURL:(NSURL *)URL;

/*!
    @property supportsSecureCoding
    @abstract Indicates that NSURLRequest implements the NSSecureCoding protocol.
    // 表明NSURLRequest实现了NSSecureCoding协议

    @result A BOOL value set to YES.
*/
@property (class, readonly) BOOL supportsSecureCoding;

/*!
    @method requestWithURL:cachePolicy:timeoutInterval:
    @abstract Allocates and initializes a NSURLRequest with the given
    URL and cache policy.
    @param URL The URL for the request. 
    @param cachePolicy The cache policy for the request. 
    @param timeoutInterval The timeout interval for the request. See the
    commentary for the <tt>timeoutInterval</tt> for more information on
    timeout intervals.
    @result A newly-created and autoreleased NSURLRequest instance. 
*/
+ (instancetype)requestWithURL:(NSURL *)URL cachePolicy:(NSURLRequestCachePolicy)cachePolicy timeoutInterval:(NSTimeInterval)timeoutInterval;

/*! 
    @method initWithURL:
    @abstract Initializes an NSURLRequest with the given URL. 
    @discussion Default values are used for cache policy
    (NSURLRequestUseProtocolCachePolicy) and timeout interval (60
    seconds).
    @param URL The URL for the request. 
    @result An initialized NSURLRequest. 
*/
- (instancetype)initWithURL:(NSURL *)URL;

/*! 
    @method initWithURL:
    @abstract Initializes an NSURLRequest with the given URL and
    cache policy.
    @discussion This is the designated initializer for the 
    NSURLRequest class.
    @param URL The URL for the request. 
    @param cachePolicy The cache policy for the request. 
    @param timeoutInterval The timeout interval for the request. See the
    commentary for the <tt>timeoutInterval</tt> for more information on
    timeout intervals.
    @result An initialized NSURLRequest. 
*/
- (instancetype)initWithURL:(NSURL *)URL cachePolicy:(NSURLRequestCachePolicy)cachePolicy timeoutInterval:(NSTimeInterval)timeoutInterval NS_DESIGNATED_INITIALIZER;

/*! 
    @abstract Returns the URL of the receiver. 
    @result The URL of the receiver. 
*/
@property (nullable, readonly, copy) NSURL *URL;

/*! 
    @abstract Returns the cache policy of the receiver.
    @result The cache policy of the receiver. 
*/
@property (readonly) NSURLRequestCachePolicy cachePolicy;

/*! 
    @abstract Returns the timeout interval of the receiver.
    @discussion The timeout interval specifies the limit on the idle
    interval alloted to a request in the process of loading. The "idle
    interval" is defined as the period of time that has passed since the
    last instance of load activity occurred for a request that is in the
    process of loading. Hence, when an instance of load activity occurs
    (e.g. bytes are received from the network for a request), the idle
    interval for a request is reset to 0. If the idle interval ever
    becomes greater than or equal to the timeout interval, the request
    is considered to have timed out. This timeout interval is measured
    in seconds.
    @result The timeout interval of the receiver. 
*/
// timeout 超时时间间隔指定在加载过程中分配给请求的idle interval的限制。 
“idle interval”定义为自加载过程中发生的加载活动的最后一次实例以来经过的时间段。 
因此,当发生负载活动的实例发生时(例如,从网络接收到请求的字节数),
请求的空闲时间间隔将重置为0。如果空闲时间间隔变得大于或等于超时时间间隔,
则请求被认为已超时。 该超时间隔以秒为单位进行测量。
@property (readonly) NSTimeInterval timeoutInterval;

/*!
    @abstract The main document URL associated with this load.
    @discussion This URL is used for the cookie "same domain as main
    document" policy. There may also be other future uses.
    See setMainDocumentURL:
    NOTE: In the current implementation, this value is unused by the
    framework. A fully functional version of this method will be available 
    in the future. 
    @result The main document URL.
*/
// 与此次加载关联的主文档URL。此URL用于“same domain as main
document”策略的cookie。 也可能有其他未来的用途。 
请参阅setMainDocumentURL:注意:在当前实现中,该值未被框架使用。 
该方法的全功能版本将在未来可用。
@property (nullable, readonly, copy) NSURL *mainDocumentURL;

/*!
 @abstract Returns the NSURLRequestNetworkServiceType associated with this request.
 @discussion  This will return NSURLNetworkServiceTypeDefault for requests that have
 not explicitly set a networkServiceType (using the setNetworkServiceType method).
 @result The NSURLRequestNetworkServiceType associated with this request.
 */
@property (readonly) NSURLRequestNetworkServiceType networkServiceType API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));

/*!
 @abstract returns whether a connection created with this request is allowed to use
 the built in cellular radios (if present).
 @result YES if the receiver is allowed to use the built in cellular radios to
 satify the request, NO otherwise.
 */
// 是否允许使用蜂窝网络

@property (readonly) BOOL allowsCellularAccess  API_AVAILABLE(macos(10.8), ios(6.0), watchos(2.0), tvos(9.0));

@end

下面还有几点需要说明。

  • 缓存策略
@property (readonly) NSURLRequestCachePolicy cachePolicy;

typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy)
{
    NSURLRequestUseProtocolCachePolicy = 0,

    NSURLRequestReloadIgnoringLocalCacheData = 1,
    NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented
    NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,

    NSURLRequestReturnCacheDataElseLoad = 2,
    NSURLRequestReturnCacheDataDontLoad = 3,

    NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented
};
  • 网络服务类型NSURLRequestNetworkServiceType
/*!
 @enum NSURLRequestNetworkServiceType
 
 @discussion The NSURLRequestNetworkServiceType enum defines constants that
 can be used to specify the service type to associate with this request.  The
 service type is used to provide the networking layers a hint of the purpose 
 of the request.
// NSURLRequestNetworkServiceType枚举定义了可用于指定与此请求关联的服务类型的常量。 
服务类型用于向网络层提供请求目的的暗示。
 
 @constant NSURLNetworkServiceTypeDefault Is the default value for an NSURLRequest
 when created.  This value should be left unchanged for the vast majority of requests.
// NSURLNetworkServiceTypeDefault是NSURLRequest创建时的默认值。
绝大多数请求的这个值应该保持不变。
 
 @constant NSURLNetworkServiceTypeVoIP Specifies that the request is for voice over IP
 control traffic.
// NSURLNetworkServiceTypeVoIP指定该请求用于IP语音控制流量
 
 @constant NSURLNetworkServiceTypeVideo Specifies that the request is for video
 traffic.
// NSURLNetworkServiceTypeVideo指定该请求用于视频流量。

 @constant NSURLNetworkServiceTypeBackground Specifies that the request is for background
 traffic (such as a file download).
// NSURLNetworkServiceTypeBackground指定该请求用于后台流量(如文件下载)

 @constant NSURLNetworkServiceTypeVoice Specifies that the request is for voice data.
// NSURLNetworkServiceTypeVoice指定请求用于语音数据

 @constant NSURLNetworkServiceTypeCallSignaling Specifies that the request is for call signaling.
// NSURLNetworkServiceTypeCallSignaling指定该请求用于呼叫信号

*/
typedef NS_ENUM(NSUInteger, NSURLRequestNetworkServiceType)
{
    NSURLNetworkServiceTypeDefault = 0, // Standard internet traffic
    NSURLNetworkServiceTypeVoIP = 1,    // Voice over IP control traffic
    NSURLNetworkServiceTypeVideo = 2,   // Video traffic
    NSURLNetworkServiceTypeBackground = 3, // Background traffic
    NSURLNetworkServiceTypeVoice = 4,      // Voice data
    NSURLNetworkServiceTypeCallSignaling API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0)) = 11, // Call Signaling
};

2. NSURLRequest分类NSHTTPURLRequest

/*!
    @category NSURLRequest(NSHTTPURLRequest) 
    The NSHTTPURLRequest on NSURLRequest provides methods for accessing
    information specific to HTTP protocol requests.
*/
// NSHTTPURLRequest提供了获取指定HTTP协议请求的信息。
@interface NSURLRequest (NSHTTPURLRequest) 

/*!
    @abstract Returns the HTTP request method of the receiver. 
    @result the HTTP request method of the receiver. 
*/
// 请求的方式,其实就是GET/POST等
@property (nullable, readonly, copy) NSString *HTTPMethod;

/*!
    @abstract Returns a dictionary containing all the HTTP header fields
    of the receiver.
    @result a dictionary containing all the HTTP header fields of the
    receiver.
*/
// 返回一个包含所有HTTP header的字典
@property (nullable, readonly, copy) NSDictionary<NSString *, NSString *> *allHTTPHeaderFields;

/*! 
    @method valueForHTTPHeaderField:
    @abstract Returns the value which corresponds to the given header
    field. Note that, in keeping with the HTTP RFC, HTTP header field
    names are case-insensitive.
    @param field the header field name to use for the lookup
    (case-insensitive).
    @result the value associated with the given header field, or nil if
    there is no value associated with the given header field.
*/
// 返回给定的header field相对的值,注意为了遵循HTTP RFC,HTTP header field的名字是区分大小写的。 
- (nullable NSString *)valueForHTTPHeaderField:(NSString *)field;

/*!
    @abstract Returns the request body data of the receiver. 
    @discussion This data is sent as the message body of the request, as
    in done in an HTTP POST request.
    @result The request body data of the receiver. 
*/
// 返回请求体的数据,一般是在POST中请求的。
@property (nullable, readonly, copy) NSData *HTTPBody;

/*!
    @abstract Returns the request body stream of the receiver
    if any has been set
    @discussion The stream is returned for examination only; it is
    not safe for the caller to manipulate the stream in any way.  Also
    note that the HTTPBodyStream and HTTPBody are mutually exclusive - only
    one can be set on a given request.  Also note that the body stream is
    preserved across copies, but is LOST when the request is coded via the 
    NSCoding protocol
    @result The request body stream of the receiver.
*/
// 返回接收器的请求体流(如果已设置)。该流只返回用于检验,
调用者以任何方式操纵流是不安全的。 另请注意,HTTPBodyStream
和HTTPBody是相互排斥的 - 只有一个可以在给定请求上设置。 
还要注意,body流在副本中保留,但在通过NSCoding协议编码请求时丢失。
@property (nullable, readonly, retain) NSInputStream *HTTPBodyStream;

/*!
    @abstract Determine whether default cookie handling will happen for 
    this request.
    @discussion NOTE: This value is not used prior to 10.3
    @result YES if cookies will be sent with and set for this request; 
    otherwise NO.
*/
// 决定是否在此次请求中处理默认cookie,这个值在10.3之前是不可以用的。
@property (readonly) BOOL HTTPShouldHandleCookies;

/*!
 @abstract Reports whether the receiver is not expected to wait for the
 previous response before transmitting.
 @result YES if the receiver should transmit before the previous response
 is received.  NO if the receiver should wait for the previous response
 before transmitting.
 */
// 决定是否在上一次请求响应回来之前进行传输新的请求
@property (readonly) BOOL HTTPShouldUsePipelining API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));

@end

NSURLRequest类仅用于封装有关URL请求的信息。 您必须使用其他类(如NSURLSessionNSURLConnection)将这些请求发送到服务器。 有关更多信息,请阅读 URL Session Programming Guide

NSURLRequest被设计为通过添加为您自己的协议特定属性提供访问方法的类别来扩展以支持其他协议。 这些方法可以通过调用NSURLProtocol方法 propertyForKey:inRequest:setProperty:forKey:inRequest:来获取和设置实际值。

Swift覆盖到Foundation框架提供了URLRequest结构,该结构桥接到NSURLRequest类及其可变子类NSMutableURLRequest。 有关值类型的更多信息,请参阅Using Swift with Cocoa and Objective-C (Swift 4.0.1)中的Working with Cocoa Frameworks


NSMutableURLRequest

1. NSMutableURLRequest本类

@interface NSMutableURLRequest : NSURLRequest

/*! 
    @abstract The URL of the receiver.
*/
@property (nullable, copy) NSURL *URL;

/*! 
    @abstract The cache policy of the receiver.
*/
@property NSURLRequestCachePolicy cachePolicy;

/*! 
    @abstract Sets the timeout interval of the receiver.
    @discussion The timeout interval specifies the limit on the idle
    interval allotted to a request in the process of loading. The "idle
    interval" is defined as the period of time that has passed since the
    last instance of load activity occurred for a request that is in the
    process of loading. Hence, when an instance of load activity occurs
    (e.g. bytes are received from the network for a request), the idle
    interval for a request is reset to 0. If the idle interval ever
    becomes greater than or equal to the timeout interval, the request
    is considered to have timed out. This timeout interval is measured
    in seconds.
*/
@property NSTimeInterval timeoutInterval;

/*!
    @abstract Sets the main document URL
    @discussion The caller should pass the URL for an appropriate main
    document, if known. For example, when loading a web page, the URL
    of the main html document for the top-level frame should be
    passed.  This main document will be used to implement the cookie
    "only from same domain as main document" policy, and possibly
    other things in the future.
    NOTE: In the current implementation, the passed-in value is unused by the
    framework. A fully functional version of this method will be available 
    in the future. 
*/
@property (nullable, copy) NSURL *mainDocumentURL;

/*!
 @abstract Sets the NSURLRequestNetworkServiceType to associate with this request
 @discussion This method is used to provide the network layers with a hint as to the purpose
 of the request.  Most clients should not need to use this method.
 */
@property NSURLRequestNetworkServiceType networkServiceType API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));

/*!
 @abstract sets whether a connection created with this request is allowed to use
 the built in cellular radios (if present). 
 @discussion NO if the receiver should not be allowed to use the built in
 cellular radios to satisfy the request, YES otherwise.  The default is YES.
 */
@property BOOL allowsCellularAccess API_AVAILABLE(macos(10.8), ios(6.0), watchos(2.0), tvos(9.0));

@end

接口就这么多内容,和NSURLRequest是类似的,具体可参考那个,这里就不多添加注释了。

2. NSMutableURLRequest分类NSMutableHTTPURLRequest

/*!
    @category NSMutableURLRequest(NSMutableHTTPURLRequest) 
    The NSMutableHTTPURLRequest on NSMutableURLRequest provides methods
    for configuring information specific to HTTP protocol requests.
*/
@interface NSMutableURLRequest (NSMutableHTTPURLRequest) 

/*!
    @abstract Sets the HTTP request method of the receiver. 
*/
@property (copy) NSString *HTTPMethod;

/*!
    @abstract Sets the HTTP header fields of the receiver to the given
    dictionary.
    @discussion This method replaces all header fields that may have
    existed before this method call. 
    <p>Since HTTP header fields must be string values, each object and
    key in the dictionary passed to this method must answer YES when
    sent an <tt>-isKindOfClass:[NSString class]</tt> message. If either
    the key or value for a key-value pair answers NO when sent this
    message, the key-value pair is skipped.
*/
@property (nullable, copy) NSDictionary<NSString *, NSString *> *allHTTPHeaderFields;

/*! 
    @method setValue:forHTTPHeaderField:
    @abstract Sets the value of the given HTTP header field.
    @discussion If a value was previously set for the given header
    field, that value is replaced with the given value. Note that, in
    keeping with the HTTP RFC, HTTP header field names are
    case-insensitive.
    @param value the header field value. 
    @param field the header field name (case-insensitive). 
*/
- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(NSString *)field;

/*! 
    @method addValue:forHTTPHeaderField:
    @abstract Adds an HTTP header field in the current header
    dictionary.
    @discussion This method provides a way to add values to header
    fields incrementally. If a value was previously set for the given
    header field, the given value is appended to the previously-existing
    value. The appropriate field delimiter, a comma in the case of HTTP,
    is added by the implementation, and should not be added to the given
    value by the caller. Note that, in keeping with the HTTP RFC, HTTP
    header field names are case-insensitive.
    @param value the header field value. 
    @param field the header field name (case-insensitive). 
*/
- (void)addValue:(NSString *)value forHTTPHeaderField:(NSString *)field;

/*!
    @abstract Sets the request body data of the receiver.
    @discussion This data is sent as the message body of the request, as
    in done in an HTTP POST request.
*/
@property (nullable, copy) NSData *HTTPBody;

/*!
    @abstract Sets the request body to be the contents of the given stream. 
    @discussion The provided stream should be unopened; the request will take
    over the stream's delegate.  The entire stream's contents will be 
    transmitted as the HTTP body of the request.  Note that the body stream
    and the body data (set by setHTTPBody:, above) are mutually exclusive 
    - setting one will clear the other.
*/
@property (nullable, retain) NSInputStream *HTTPBodyStream;

/*!
    @abstract Decide whether default cookie handling will happen for 
    this request (YES if cookies should be sent with and set for this request;
    otherwise NO).
    @discussion The default is YES - in other words, cookies are sent from and 
    stored to the cookie manager by default.
    NOTE: In releases prior to 10.3, this value is ignored
*/
@property BOOL HTTPShouldHandleCookies;

/*!
 @abstract Sets whether the request should not wait for the previous response 
 before transmitting (YES if the receiver should transmit before the previous response is
 received.  NO to wait for the previous response before transmitting)
 @discussion Calling this method with a YES value does not guarantee HTTP 
 pipelining behavior.  This method may have no effect if an HTTP proxy is
 configured, or if the HTTP request uses an unsafe request method (e.g., POST
 requests will not pipeline).  Pipelining behavior also may not begin until
 the second request on a given TCP connection.  There may be other situations
 where pipelining does not occur even though YES was set.
 HTTP 1.1 allows the client to send multiple requests to the server without
 waiting for a response.  Though HTTP 1.1 requires support for pipelining,
 some servers report themselves as being HTTP 1.1 but do not support
 pipelining (disconnecting, sending resources misordered, omitting part of
 a resource, etc.).
 */
@property BOOL HTTPShouldUsePipelining API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));

@end

大家发现这个和NSURLRequest分类NSHTTPURLRequest也是类似的,那么也就不多添加注释了,具体大家可以参考上面所做的注释。

NSURLSessionNSURLConnectionNSURLDownload类为传递给它们的初始化器和task创建方法的每个NSMutableURLRequest对象进行了深拷贝。

URL加载系统旨在为您处理HTTP协议的各个方面。 因此,不应使用addValue:forHTTPHeaderField:或者 setValue:forHTTPHeaderField:修改以下headers。

  • Authorization
  • Connection
  • Host
  • Proxy-Authenticate
  • Proxy-Authorization
  • WWW-Authenticate

后记

本篇主要介绍了NSURLRequestNSMutableURLRequest的本类和分类的接口使用文档。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容