我需要在Swift中获取重定向网址,但阻止重定向。从其他帖子和Apple文档中我了解到,我必须实现委托方法URLSession(session:, task:, willPerformHTTPRedirection response:, request:, completionHandler:)
并通过完成闭包返回nil
。但是,我无法在swift中找到示例,也无法找到正确的方法。下面的代码在playground中重现了我的问题:委托似乎没有被执行。
import Foundation
import XCPlayground
XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true)
class MySession: NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate {
// trying to follow instructions at https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSURLSessionTaskDelegate_protocol/index.html#//apple_ref/occ/intfm/NSURLSessionTaskDelegate/URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:
// to prevent redirection -- DOES NOT SEEM TO GET CALLED
func URLSession(session: NSURLSession, task: NSURLSessionTask, willPerformHTTPRedirection response: NSHTTPURLResponse, newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) {
println("in URLSession delegate") // NEVER PRINTS
completionHandler(nil) // NO EFFECT
}
// fetch data from URL with NSURLSession
class func getDataFromServerWithSuccess(myURL: String, success: (response: String!) -> Void) {
var session = NSURLSession.sharedSession()
let loadDataTask = session.dataTaskWithURL(NSURL(string: myURL)!) { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
// OMITTING ERROR CHECKING FOR BREVITY
success(response: NSString(data: data!, encoding: NSASCIIStringEncoding) as String)
}
loadDataTask.resume()
}
// extract data from redirect
class func getRedirectionInfo(url: String) {
getDataFromServerWithSuccess(url) {(data) -> Void in
if let html = data {
if html.rangeOfString("<html><head><title>Object moved</title>", options: .RegularExpressionSearch) != nil {
println("success: redirection was prevented") // SHOULD PRINT THIS
} else {
println("failure: redirection went through") // INSTEAD PRINTS THIS
}
}
}
}
}
MySession.getRedirectionInfo("http://bit.ly/filmenczer") // ex. redirecting link
请温柔,我是新手。 提前感谢您的任何帮助!
更新:非常感谢@nate,我得到了它的工作。关键的见解是,为了调用委托,必须将委托类传递给NSURLSession()
初始化程序,而不是使用NSURLSession.sharedSession()
。传递nil
作为委托产生习惯行为(使用重定向)。这是代码的工作版本:
import Foundation
import XCPlayground
XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true)
class MySession: NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate {
// to prevent redirection
func URLSession(session: NSURLSession, task: NSURLSessionTask, willPerformHTTPRedirection response: NSHTTPURLResponse, newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) {
completionHandler(nil)
}
// fetch data from URL with NSURLSession
class func getDataFromServerWithSuccess(myURL: String, noRedirect: Bool, success: (response: String!) -> Void) {
var myDelegate: MySession? = nil
if noRedirect {
myDelegate = MySession()
}
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: myDelegate, delegateQueue: nil)
let loadDataTask = session.dataTaskWithURL(NSURL(string: myURL)!) { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
// OMITTING ERROR CHECKING FOR BREVITY
success(response: NSString(data: data!, encoding: NSASCIIStringEncoding) as String)
}
loadDataTask.resume()
}
// extract data from redirect
class func getRedirectionInfo(url: String) {
getDataFromServerWithSuccess(url, noRedirect: true) {(data) -> Void in
if let html = data {
if html.rangeOfString("<html>\n<head><title>Bitly</title>", options: .RegularExpressionSearch) != nil {
println("success: redirection was prevented")
} else {
println("failure: redirection went through")
}
}
}
}
}
MySession.getRedirectionInfo("http://bit.ly/filmenczer")
答案 0 :(得分:4)
您目前的实施方式阻碍了两件事。
您永远不会在您用于发出请求的NSURLSession
实例上设置委托属性。如果没有委托属性集,您的委托方法将永远不会被调用。不要获取NSURLSession.sharedSession()
,而是查看NSURLSession(configuration:delegate:delegateQueue:)
初始值设定项。第一个和最后一个参数可分别为NSURLSessionConfiguration.defaultSessionConfiguration()
和nil
,有关代理的详情,请参阅下文。
请注意,当您使用具有完成处理程序的
session.dataTaskWithURL
变体时,将忽略处理响应和数据传递的委托方法,但仍会使用身份验证和重定向处理程序。
由于您正在使用类方法发出请求,因此您必须稍微重构以使用MySession
作为委托。您需要一个实例用作会话的代理。
我采用了一条简短且不完整的路线,让代理人使用此备用代码接收重定向 - 您需要像#3一样重构,以确保您仍然可以拨打回叫:
class func getDataFromServerWithSuccess(myURL: String, success: (response: String!) -> Void) {
let delegate = MySession()
var session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: delegate, delegateQueue: nil)
let task = session.dataTaskWithURL(NSURL(string: myURL)!) {
// ...
}
task.resume()
}
希望有所帮助!
答案 1 :(得分:1)
对上述解决方案进行微调。这适用于XCode 7中的Swift 2。
import UIKit
import Foundation
import XCPlayground
XCPSetExecutionShouldContinueIndefinitely(true)
class MySession: NSObject, NSURLSessionDelegate {
// to prevent redirection
func URLSession(session: NSURLSession, task: NSURLSessionTask, willPerformHTTPRedirection response: NSHTTPURLResponse, newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) {
completionHandler(nil)
}
// fetch data from URL with NSURLSession
class func getDataFromServerWithSuccess(myURL: String, noRedirect: Bool, success: (response: String!) -> Void) {
var myDelegate: MySession? = nil
if noRedirect {
myDelegate = MySession()
}
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: myDelegate, delegateQueue: nil)
let loadDataTask = session.dataTaskWithURL(NSURL(string: myURL)!) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
// OMITTING ERROR CHECKING FOR BREVITY
success(response: NSString(data: data!, encoding: NSASCIIStringEncoding) as! String)
}
loadDataTask.resume()
}
// extract data from redirect
class func getRedirectionInfo(url: String) {
getDataFromServerWithSuccess(url, noRedirect: true) {(data) -> Void in
if let html = data {
if html.rangeOfString("<html>\n<head><title>Bitly</title>", options: .RegularExpressionSearch) != nil {
print("success: redirection was prevented")
} else {
print("failure: redirection went through")
}
}
}
}
}
MySession.getRedirectionInfo("http://bit.ly/filmenczer")
答案 2 :(得分:0)
我也发现该解决方案很有帮助,但是我在当前项目中使用的是Swift 4.2。
因此,这是上述解决方案的经过改编的简短版本,也可以与 Swift 4.2 和 Xcode 10 一起使用。
pip install firebase