我现在开始使用NSURLSession,NSURLConnection因为它是Apple提供的一种新的优雅API.以前,我曾经NSURLRequest在GCD块中调用来在后台执行它.以下是我过去的做法:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:@"www.stackoverflow.com"]];
NSURLResponse *response;
NSError *error;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (error) {
// handle error
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
// do something with the data
});
});
Run Code Online (Sandbox Code Playgroud)
现在,我的使用方法NSURLSession如下:
- (void)viewDidLoad
{
[super viewDidLoad];
/*-----------------*
NSURLSession
*-----------------*/
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:
[NSURL URLWithString:@"https://itunes.apple.com/search?term=apple&media=software"]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
NSDictionary *json …Run Code Online (Sandbox Code Playgroud) multithreading ios nsurlsession nsurlsessiontask nsurlsessiondatatask
我正在创建一个NSMutableRequest:
self.req = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];
Run Code Online (Sandbox Code Playgroud)
超时设置为10秒,因为我不希望用户等待太长时间来获得反馈.之后我创建了一个NSURLSessionDataTask:
NSURLSessionDataTask *task = [self.session dataTaskWithRequest:self.req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSHTTPURLResponse * httpResp = (NSHTTPURLResponse *)response;
if (error) {
// this is where I get the timeout
}
else if (httpResp.statusCode < 200 || httpResp.statusCode >= 300) {
// handling error and giving feedback
}
else {
NSError *serializationError = nil;
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&serializationError];
}
[task resume];
}
Run Code Online (Sandbox Code Playgroud)
问题是服务器进入Gateway Timeout并且需要花费很多时间.我收到超时错误并向用户提供反馈,但由于超时错误,以下所有API调用都以相同方式失败.阻止它的唯一方法是杀死应用程序并重新开始.在超时错误后,我应该做些什么来终止任务或连接?如果我没有设置超时并且我等到从服务器收到错误代码,则以下所有调用都能正常工作(但是用户会等待很多!).
我试图取消任务:
NSURLSessionDataTask …Run Code Online (Sandbox Code Playgroud) 我正在尝试实现本教程,该教程使用NSURLConnection实现自定义NSURLProtocol.
https://www.raywenderlich.com/76735/using-nsurlprotocol-swift
它按预期工作,但现在在iOS9中不推荐使用NSURLConnection,我试图将其转换为NSURLSession.
不幸的是,它没有用.
我正在uiwebview中加载一个网站,如果我使用NSURLConnection加载并且一切都按预期工作,则会捕获来自webview的所有http请求,但在使用NSURLSession时则不会.
任何帮助表示赞赏.
这是我的代码
import UIKit
class MyProtocol: NSURLProtocol, NSURLSessionDataDelegate, NSURLSessionTaskDelegate, NSURLSessionDelegate {
//var connection: NSURLConnection!
var mutableData: NSMutableData!
var response: NSURLResponse!
var dataSession: NSURLSessionDataTask!
override class func canInitWithRequest(request: NSURLRequest) -> Bool {
if NSURLProtocol.propertyForKey("MyURLProtocolHandledKey", inRequest: request) != nil {
return false
}
return true
}
override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
return request
}
override class func requestIsCacheEquivalent(aRequest: NSURLRequest,
toRequest bRequest: NSURLRequest) -> Bool {
return super.requestIsCacheEquivalent(aRequest, toRequest:bRequest)
}
override func startLoading() {
let …Run Code Online (Sandbox Code Playgroud) 这个My Test案例指出,当使用带有HTTP/2连接的NSURLSession时,存在内存问题.
test1:iOS 9. HTTP/2服务器
我使用NSURLSession将10M文件上传到HTTP/2服务器,如果上传的文件完成一切正常,但如果我在完成之前取消上传任务,10M将永远不会释放.
test2:iOS 9. HTTPs1.1服务器
我用https1.1文件服务器测试相同的代码,我是否取消上传任务,一切正常,内存恢复正常.(10M数据发布)
test3 iOS 8. HTTP/2服务器
这种情况一切正常.(NSURLSession没有协议协商到HTTP/2)
所以,即使有一些不适合我使用NSURLSession的东西,NSURLSession的性能也不适用于HTTP/2.
除了内存问题,当使用带有HTTP/2的NSURLSession上传文件时,进度段大小是巨大的(一次回调可能是5M'addSendBodyData')
我也读过这个页面.SSL可能会缓存一些东西,但不应该缓存整个文件.(当我取消任务或请求超时时,10M文件大小的内存泄漏)
任何人都知道导致问题的原因,可以给我一些帮助.谢谢.
问题更新0912:添加测试项目链接
测试项目:https://github.com/upyun/swift-sdk/tree/testleak
file:UPUtils.swift
//Change the url to make comparison test.
//let DEFAULT_UPYUN_FORM_API_DOMAIN = "http://v0.api.upyun.com"//http1.1
//let DEFAULT_UPYUN_FORM_API_DOMAIN = "https://httpbin.org/post" //https1.1
let DEFAULT_UPYUN_FORM_API_DOMAIN = "https://v0.api.upyun.com"//http2
Run Code Online (Sandbox Code Playgroud) 我正在使用URL后台会话将pdf上传作为数据流,使用ios版本> 9.0.我将超时间隔设置为300秒.它根本不起作用.10秒后,它会出现超时错误.
下面给出了一段代码
NSTimeInterval reqTimeInterval = 300.0f;
- (NSURLSession *)uploadSessionForMrNo:(NSString *)mrNo
userRoleId:(NSString *)userRoleId
timestamp:(NSString *)timestamp {
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 4;
NSString *backgroundSessionIdentifier = [NSString stringWithFormat:@"backgroundPdfUploadIdentifier_%@",mrNo];
NSURLSessionConfiguration *backgroundSession = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:backgroundSessionIdentifier];
backgroundSession.discretionary = true;
NSURLSession *session = [NSURLSession sessionWithConfiguration:backgroundSession delegate:self delegateQueue:queue];
[session setAccessibilityLabel:mrNo];
[session setAccessibilityValue:userRoleId];
[session setAccessibilityHint:timestamp];
return session;
}
- (void)uploadPdfRequest:(NSURLRequest *)request
forMrNo:(NSString *)mrNo
userRoleId:(NSString *)userRoleId
andTimestamp:(NSString *)timestamp {
NSURLSession *session = [self uploadSessionForMrNo:mrNo userRoleId:userRoleId timestamp:timestamp];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request];
NSLog(@"postDataTask %@ timeout %f",postDataTask,request.timeoutInterval); …Run Code Online (Sandbox Code Playgroud) 我目前正在使用 FairPlay 流实现离线流。因此,我正在使用AVAssetDownloadTask.
我想向用户提供有关开始下载的大小的反馈:
您确定要下载此流吗?下载需要 2.4GB,您目前还有 14GB 的空间
我已经检查过类似countOfBytesReceived和的属性,countOfBytesExpectedToReceive但这些不会返回正确的值。
let headRequest = NSMutableURLRequest(URL: asset.streamURL)
headRequest.HTTPMethod = "HEAD"
let sizeTask = NSURLSession.sharedSession().dataTaskWithRequest(headRequest) { (data, response, error) in
print("Expected size is \(response?.expectedContentLength)")
}.resume()
Run Code Online (Sandbox Code Playgroud)
打印大小为 2464,最后大小为 3GB。
在下载过程中,我记录了上述属性:
func URLSession(session: NSURLSession, assetDownloadTask: AVAssetDownloadTask, didLoadTimeRange timeRange: CMTimeRange, totalTimeRangesLoaded loadedTimeRanges: [NSValue], timeRangeExpectedToLoad: CMTimeRange) {
print("Downloaded \( convertFileSizeToMegabyte(Float(assetDownloadTask.countOfBytesReceived)))/\(convertFileSizeToMegabyte(Float(assetDownloadTask.countOfBytesExpectedToReceive))) MB")
}
Run Code Online (Sandbox Code Playgroud)
但这些保持为零:
已下载 0.0/0.0 MB
fairplay nsurlsession nsurlsessiondatatask avassetdownloadtask
我是iOS/Swift开发的新手,我正在开发一个向REST API提出多个请求的应用程序.以下是检索"消息"的其中一个调用的示例:
func getMessages() {
let endpoint = "/api/outgoingMessages"
let parameters: [String: Any] = [
"limit" : 100,
"sortOrder" : "ASC"
]
guard let url = createURLWithComponents(endpoint: endpoint, parameters: parameters) else {
print("Failed to create URL!")
return
}
do {
var request = try URLRequest(url: url, method: .get)
let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
if let error = error {
print("Request failed with error: \(error)")
// TODO: retry failed request
} else if let …Run Code Online (Sandbox Code Playgroud) 这就是Apple的文档中关于课程suspend方法的说法NSURLSessionTask
任务暂停时不会产生网络流量,也不会超时.
好.所以我运行以下简单代码:
let url = NSURL(string: "http://httpbin.org/delay/10")!
let urlRequest = NSURLRequest(URL: url)
self.task = NSURLSession.sharedSession().dataTaskWithURL(urlRequest.URL!, completionHandler: {
data, response, error in print("completion ERROR \(error)")
})
self.task.resume()
print("Start")
delay(5, closure: {
self.task.suspend()
print("Suspend")
})
Run Code Online (Sandbox Code Playgroud)
函数delay只是一个包装器dispatch_after,请求http://httpbin.org/delay/10在10秒后给出响应.在等待响应的过程中,我暂停了任务.然而,这不起作用.在60秒内,将调用完成块并显示超时错误.任何人都可以解释一下是什么问题吗?
我的网络逻辑中有以下代码:
let task = urlSession.dataTask(with: request) { [weak self] (data, response, error) in
if let error = error {
if error.localizedDescription.contains("The request timed out") {
// request timeout stuff ...
} else {
// other errors
}
}
}
Run Code Online (Sandbox Code Playgroud)
字符串匹配localizedDescription不是好的代码实践。如何像 in 子句一样获取错误的类型catch?
使用 Swift 4,我有以下代码尝试向 REST API 发出 POST 请求:
spinner.startAnimation(self)
btnOk.isEnabled = false
btnCancel.isEnabled = false
attemptPost()
spinner.stopAnimation(self)
btnOk.isEnabled = true
btnCancel.isEnabled = true
Run Code Online (Sandbox Code Playgroud)
执行此操作的函数(Constants并且Request是我创建的用于创建请求对象并保存常用数据的类):
func attemptPost() {
let url = Constants.SERVICE_URL + "account/post"
let body: [String : Any] =
["firstName": txtFirstName.stringValue,
"lastName": txtLastName.stringValue,
"email": txtEmail.stringValue,
"password": txtPassword.stringValue];
let req = Request.create(urlExtension: url, httpVerb: Constants.HTTP_POST, jsonBody: body)
let task = URLSession.shared.dataTask(with: req) { data, response, err in
guard let data = data, err == nil else { …Run Code Online (Sandbox Code Playgroud) nsurlsession ×9
ios ×7
swift ×5
objective-c ×2
fairplay ×1
http2 ×1
ios11 ×1
memory-leaks ×1
retry-logic ×1
urlsession ×1