NSURLConnection支持的內置URL協議可以處理http,https,file,ftp,about和數據的方案。我想支持sftp。我聽說有一種方法可以通過繼承NSURLProtocol來實現此目的。但我沒有得到如何去做。我想通過sftp從文件夾下載圖像。如何通過繼承NSURLProtocol來成功處理sftp://協議?
來源:https://www.raywenderlich.com/76735/using-nsurlprotocol-swift
的教程說的子類,我們可以支持自定義URL。但是當我運行代碼時,連接總是失敗。我想當我們嘗試連接到sftp,委託方法在MyURLProtocol.swift即didReceiveAuthenticationChallenge會被調用,但這並沒有發生。相反,代理方法didFailWithError被調用。我不明白爲什麼連接失敗。這兩種方法都來自NSURLConnectionDelegate
我有一個ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let urlString = "sftp://[email protected]:22/batman"
// Open a connection for the URL.
var url = NSURL(string: urlString)
request = NSURLRequest(URL: url!)
connection = NSURLConnection(request: request, delegate: self, startImmediately: true)//(request: request, delegate: self)
}
在我AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
NSURLProtocol.registerClass(MyURLProtocol)
return true
}
我MyURLProtocol.swift
import UIKit
import CoreData
var requestCount = 0
class MyURLProtocol: NSURLProtocol, NSURLConnectionDelegate {
var connection: NSURLConnection!
var mutableData: NSMutableData!
var response: NSURLResponse!
override class func canInitWithRequest(request: NSURLRequest) -> Bool {
print("Request #\(requestCount++): URL = \(request.URL!.absoluteString)")
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() {
// 1
let possibleCachedResponse = self.cachedResponseForCurrentRequest()
if let cachedResponse = possibleCachedResponse {
print("Serving response from cache")
// 2
let data = cachedResponse.valueForKey("data") as! NSData
let mimeType = cachedResponse.valueForKey("mimeType") as! String
let encoding = cachedResponse.valueForKey("encoding") as! String
// 3
let response = NSURLResponse(URL: self.request.URL!, MIMEType: mimeType, expectedContentLength: data.length, textEncodingName: encoding)
// 4
self.client!.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
self.client!.URLProtocol(self, didLoadData: data)
self.client!.URLProtocolDidFinishLoading(self)
} else {
// 5
print("Serving response from NSURLConnection")
let newRequest = self.request.mutableCopy() as! NSMutableURLRequest
NSURLProtocol.setProperty(true, forKey: "MyURLProtocolHandledKey", inRequest: newRequest)
self.connection = NSURLConnection(request: newRequest, delegate: self)
}
}
override func stopLoading() {
if self.connection != nil {
self.connection.cancel()
}
self.connection = nil
}
func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
self.client!.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
self.response = response
self.mutableData = NSMutableData()
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
self.client!.URLProtocol(self, didLoadData: data)
self.mutableData.appendData(data)
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
self.client!.URLProtocolDidFinishLoading(self)
self.saveCachedResponse()
}
func connection(connection: NSURLConnection, didFailWithError error: NSError) {
self.client!.URLProtocol(self, didFailWithError: error)
}
func connection(connection: NSURLConnection, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge) {
}
func saveCachedResponse() {
print("Saving cached response")
// 1
let delegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context = delegate.managedObjectContext
// 2
let cachedResponse = NSEntityDescription.insertNewObjectForEntityForName("CachedURLResponse", inManagedObjectContext: context) as NSManagedObject
cachedResponse.setValue(self.mutableData, forKey: "data")
cachedResponse.setValue(self.request.URL!.absoluteString, forKey: "url")
cachedResponse.setValue(NSDate(), forKey: "timestamp")
cachedResponse.setValue(self.response.MIMEType, forKey: "mimeType")
cachedResponse.setValue(self.response.textEncodingName, forKey: "encoding")
// 3
do {
try context.save()
} catch let error as NSError {
print(error)
print("Could not cache the response")
}
}
func cachedResponseForCurrentRequest() -> NSManagedObject? {
// 1
let delegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context = delegate.managedObjectContext
// 2
let fetchRequest = NSFetchRequest()
let entity = NSEntityDescription.entityForName("CachedURLResponse", inManagedObjectContext: context)
fetchRequest.entity = entity
// 3
let predicate = NSPredicate(format:"url == %@", self.request.URL!.absoluteString)
fetchRequest.predicate = predicate
// 4
let possibleResult:Array<NSManagedObject>?
do {
possibleResult = try context.executeFetchRequest(fetchRequest) as? Array<NSManagedObject>
if let result = possibleResult {
if !result.isEmpty {
return result[0]
}
}
} catch let error as NSError {
print(error)
}
return nil
}
}
不caninitWithRequest曾經被調用? –
是的,它被調用。 –