我遇到一个问题-我正在尝试解析html正文内容,以便可以访问HTML响应的原始文本。我遇到的问题是由于缺乏处理范围变量的知识-例如
let _RequestPartsURL = URL(string:"http://xxxxxxx.on.ca/getData.aspx?requestType=Tech")!;
let _WebSession = URLSession.shared;
class _WebSessionCredentials {
let _RequestURL = _RequestPartsURL;
let _InstancedSession = _WebSession;
let _InstancedTask = _WebSession.dataTask(with: _RequestPartsURL) { data,response,error in
if error != nil {
// Error
print("Client Error!");
return;
};
guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
print("Server Error!");
return;
};
guard let mime = response.mimeType, mime == "text/html" else {
print("Wrong mime type!");
return;
};
var htmlbody = String(data: data!, encoding: String.Encoding.utf8)!;
print(htmlbody.utf8)
};
};
_WebSessionCredentials()._InstancedTask.resume();
_WebSessionCredentials()._InstancedTask.htmlbody;
Error: Value of type 'URLSessionDataTask' has no member 'htmlbody
当我访问位于data!
中的原始数据时,我了解到该变量是let _InstancedTask
的局部变量,但是为什么要通过_WebSessionCredentials()._InstancedTask.htmlbody;
访问数据是不正确的语句-我不是说我想从htmlbody
访问_InstancedTask
中的_WebSessionCredentials()
吗?
我来自Python,因此我在解决如何实例化和使用类中的数据时遇到了麻烦。感谢您的帮助。
答案 0 :(得分:0)
htmlbody
变量是URLSessionDataTask
块本地的变量。如果您想访问htmlbody
,我建议将htmlbody
作为类本身的实例变量,并在该块中对其进行初始化。因此您的课程如下所示:
class _WebSessionCredentials {
let _RequestURL = _RequestPartsURL
let _InstancedSession = _WebSession
var htmlbody: String?
let _InstancedTask = _WebSession.dataTask(with: _RequestPartsURL) { [weak self] (data,response,error) in
if error != nil {
// Error
print("Client Error!")
return
}
guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
print("Server Error!")
return
}
guard let mime = response.mimeType, mime == "text/html" else {
print("Wrong mime type!");
return
}
self.htmlbody = String(data: data!, encoding: String.Encoding.utf8)!
print(htmlbody.utf8)
}
}
现在,您可以通过在htmlbody
对象上调用.htmlbody
来访问_WebSessionCredentials()
。
我建议对代码进行一些更改以使Swift-y更加实用>
class WebSessionCredentials {
static let requestURL = URL(string:"http://xxxxxxx.on.ca/getData.aspx?requestType=Tech")!
var htmlbody: String?
var instancedTask: URLSessionDataTask?
static var sharedInstance = WebSessionCredentials()
init() {
self.instancedTask = URLSession.shared.dataTask(with: WebSessionCredentials.requestURL) { [weak self] (data,response,error) in
if let error = error {
// Error
print("Client Error: \(error.localizedDescription)")
return
}
guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
print("Server Error!")
return
}
guard let mime = response.mimeType, mime == "text/html" else {
print("Wrong mime type!");
return
}
if let htmlData = data, let htmlBodyString = String(data: htmlData, encoding: .utf8) {
self?.htmlbody = htmlBodyString
print(htmlbody.utf8)
}
}
}
}
现在您可以做我想做的事情了:
WebSessionCredentials.sharedInstance.instancedTask.resume()
WebSessionCredentials.sharedInstance.htmlbody
快速命名约定没有下划线,并遵循驼峰式大小写。我创建了一个名为sharedInstance
的单例,因为您似乎两次初始化_WebSessionCredentials
并期望它引用同一对象。全局变量也不是首选,因此我将您的_RequestPartsURL
变成了一个名为requestURL
的类变量。可以通过调用WebSessionCredentials.requestURL
来访问它。
[weak self]
确保您对self
的引用是weak
引用,以免建立一个强大的引用周期。在像您在此处这样的网络请求中,可以在WebSessionCredentials
对象已经被释放后完成网络请求。如果此时有strong
或unowned
对self
的引用,则您的应用程序将崩溃。 [weak self]
还确保调用完成块时,您对自身的引用为Optional
,并且可以通过调用htmlbody
安全地访问self?.htmlbody
。而如果呼叫为self.htmlbody
,则该应用将崩溃。