-
Notifications
You must be signed in to change notification settings - Fork 1
制作流程
制作SSURLSession
1.复制FoudationNetwork下URLSession文件夹,以及URLCache,URLProtocol,DataURLProtocol文件到目录 2.全局SwiftFoundation替换成Foundation 3.URLSessionTaskMetrics 27行taskInterval没用上,注释掉 4.URLSessionConfiguration ephemeral方法用不上,注释掉 5.HTTPURLProtocol 400行 if request.isTimeoutIntervalSet 这个属性是内部方法,无法得知,使用timeoutInterval>0替换使用,判断一下是否为inf和nan let requestTimeOut = request.timeoutInterval if !requestTimeOut.isInfinite && !requestTimeOut.isNaN && request.timeoutInterval > 0 { timeoutInterval = Int(request.timeoutInterval) * 1000 } 6.URLCache 447行使用了ios11的api,需要把旧的api加上 if #available(iOS 11.0, *) { return try NSKeyedUnarchiver.unarchivedObject(ofClasses: [StoredCachedURLResponse.self], from: data) as? StoredCachedURLResponse } else { return NSKeyedUnarchiver.unarchiveObject(with: data) as? StoredCachedURLResponse } 500行也是一样 var serialized: Data? if #available(iOS 11.0, *) { serialized = (onDisk && diskCapacity > 0) ? try? NSKeyedArchiver.archivedData(withRootObject: object, requiringSecureCoding: true) : nil } else { // Fallback on earlier versions serialized = (onDisk && diskCapacity > 0) ? NSKeyedArchiver.archivedData(withRootObject: object) : nil } 7.URLProtocol使用了URLRequest的私有变量,转向Foundation.URLProtocol的方法,这里网络库没有用,这几个方法,注释也可以 return Foundation.URLProtocol.property(forKey: key, in: request) Foundation.URLProtocol.setProperty(value, forKey: key, in: request) Foundation.URLProtocol.removeProperty(forKey: key, in: request) 8.NativeProtocol缺少方法_InputStreamSPIForFoundationNetworkingUseOnly,在NativeProtocol底部加上
// add- public struct _InputStreamSPIForFoundationNetworkingUseOnly { var inputStream: InputStream
public init(_ inputStream: InputStream) {
self.inputStream = inputStream
}
public func seek(to position: UInt64) throws {
try inputStream.seek(to: position)
}
}
extension InputStream { enum _Error: Error { case cantSeekInputStream }
func seek(to position: UInt64) throws {
guard position > 0 else {
return
}
guard position < Int.max else { throw _Error.cantSeekInputStream }
let bufferSize = 1024
var remainingBytes = Int(position)
let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: bufferSize, alignment: MemoryLayout<UInt8>.alignment)
guard let pointer = buffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
buffer.deallocate()
throw _Error.cantSeekInputStream
}
if self.streamStatus == .notOpen {
self.open()
}
while remainingBytes > 0 && self.hasBytesAvailable {
let read = self.read(pointer, maxLength: min(bufferSize, remainingBytes))
if read == -1 {
throw _Error.cantSeekInputStream
}
remainingBytes -= read
}
buffer.deallocate()
if remainingBytes != 0 {
throw _Error.cantSeekInputStream
}
}
} 9.HTTPMessage使用了ios13的获取HeaderValue的方法,把旧的方法加上 if #available(iOS 13.0, *) { guard let authenticateValue = response.value(forHTTPHeaderField: "WWW-Authenticate") else { return [] } return challenges(from: authenticateValue) } else { // Fallback on earlier versions let allHeaders = response.allHeaderFields guard let authenticateValue = allHeaders["WWW-Authenticate"] as? String else { return [] } return challenges(from: authenticateValue) } 10.NetworkingSpecific有找不到的结构体_NSNonfileURLContentLoading,这个在swiftRuntime中,把结构体定义拷过来即可,注册这个loader也可以,这里没有调用
public protocol _NSNonfileURLContentLoading: AnyObject { init() func contentsOf(url: URL) throws -> (result: NSData, textEncodingNameIfAvailable: String?) }
11.URLSessionTask 788 行使用了URLProtectionSpace.create(with: response)私有方法,在底部加上这些缺少的
extension URLProtectionSpace { //an internal helper to create a URLProtectionSpace from a HTTPURLResponse static func create(with response: HTTPURLResponse) -> URLProtectionSpace? { // Using first challenge, as we don't support multiple challenges yet guard let challenge = _HTTPURLProtocol._HTTPMessage._Challenge.challenges(from: response).first else { return nil } guard let url = response.url, let host = url.host, let proto = url.scheme, proto == "http" || proto == "https" else { return nil } let port = url.port ?? (proto == "http" ? 80 : 443) return URLProtectionSpace(host: host, port: port, protocol: proto, realm: challenge.parameter(withName: "realm")?.value, authenticationMethod: challenge.authenticationMethod) } }
extension _HTTPURLProtocol._HTTPMessage._Challenge { var authenticationMethod: String? { if authScheme.caseInsensitiveCompare(_HTTPURLProtocol._HTTPMessage._Challenge.AuthSchemeBasic) == .orderedSame { return NSURLAuthenticationMethodHTTPBasic } else if authScheme.caseInsensitiveCompare(_HTTPURLProtocol._HTTPMessage._Challenge.AuthSchemeDigest) == .orderedSame { return NSURLAuthenticationMethodHTTPDigest } else { return nil } } }
class URLSessionAuthenticationChallengeSender : NSObject, URLAuthenticationChallengeSender { func cancel(_ challenge: URLAuthenticationChallenge) { fatalError("swift-corelibs-foundation only supports URLSession; for challenges coming from URLSession, please implement the appropriate URLSessionTaskDelegate methods rather than using the sender argument.") }
func continueWithoutCredential(for challenge: URLAuthenticationChallenge) {
fatalError("swift-corelibs-foundation only supports URLSession; for challenges coming from URLSession, please implement the appropriate URLSessionTaskDelegate methods rather than using the sender argument.")
}
func use(_ credential: URLCredential, for challenge: URLAuthenticationChallenge) {
fatalError("swift-corelibs-foundation only supports URLSession; for challenges coming from URLSession, please implement the appropriate URLSessionTaskDelegate methods rather than using the sender argument.")
}
func performDefaultHandling(for challenge: URLAuthenticationChallenge) {
fatalError("swift-corelibs-foundation only supports URLSession; for challenges coming from URLSession, please implement the appropriate URLSessionTaskDelegate methods rather than using the sender argument.")
}
func rejectProtectionSpaceAndContinue(with challenge: URLAuthenticationChallenge) {
fatalError("swift-corelibs-foundation only supports URLSession; for challenges coming from URLSession, please implement the appropriate URLSessionTaskDelegate methods rather than using the sender argument.")
}
}
extension URLCredentialStorage { @objc public func getCredentials(for protectionSpace: URLProtectionSpace, task: URLSessionTask, completionHandler: ([String : URLCredential]?) -> Void) { completionHandler(credentials(for: protectionSpace)) }
@objc
public func set(_ credential: URLCredential, for protectionSpace: URLProtectionSpace, task: URLSessionTask) {
set(credential, for: protectionSpace)
}
@objc
public func remove(_ credential: URLCredential, for protectionSpace: URLProtectionSpace, options: [String : AnyObject]? = [:], task: URLSessionTask) {
remove(credential, for: protectionSpace, options: options)
}
@objc
public func getDefaultCredential(for space: URLProtectionSpace, task: URLSessionTask, completionHandler: (URLCredential?) -> Void) {
completionHandler(defaultCredential(for: space))
}
@objc
public func setDefaultCredential(_ credential: URLCredential, for protectionSpace: URLProtectionSpace, task: URLSessionTask) {
setDefaultCredential(credential, for: protectionSpace)
}
}
到这步swift就能编译通过了 剩余的就是在适当的地方加上@objc,使库支持oc访问