将私有声明的变量委派给公共范围

时间:2019-07-10 18:07:04

标签: swift

我遇到一个问题-我正在尝试解析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,因此我在解决如何实例化和使用类中的数据时遇到了麻烦。感谢您的帮助。

1 个答案:

答案 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对象已经被释放后完成网络请求。如果此时有strongunownedself的引用,则您的应用程序将崩溃。 [weak self]还确保调用完成块时,您对自身的引用为Optional,并且可以通过调用htmlbody安全地访问self?.htmlbody。而如果呼叫为self.htmlbody,则该应用将崩溃。