允许完成处理程序超过其创建所在的本地范围

时间:2019-02-18 21:38:26

标签: ios swift memory-management automatic-ref-counting object-lifetime

我有一个实现XMLParserDelegate协议的类,在初始化期间,它获得一个字符串和一个完成处理程序作为参数。我正在尝试在字符串解析后调用完成处理程序,但是由于类的释放,因此未达到XMLParserDelegate方法。

class MyXMLParser: NSObject, XMLParserDelegate {

private (set) var parser: XMLParser?
private (set) var completion: ((String?) -> Void)?

public init(_ xml: String, _ completion: @escaping ((String?) -> Void)) {
    let data = xml.data(using: String.Encoding.utf8)
    self.parser = XMLParser(data: data ?? Data())
    self.completion = completion
    self.parser?.delegate = self
    self.parser?.parse()
}

deinit {
    // Being called before Parser methods
}

// MARK: - Parser delegate methods

func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
    // Custom implementation
}

func parserDidEndDocument(_ parser: XMLParser) {
    // Custom implementation
    self.completion?("Test")
}

func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
    self.completion?(nil)
}

}

我用以下方式称呼它:

func someFunc() {
    let parser = MyXMLParser(someXMLString) { text in
        // Custom implementation
    }
}

我希望闭包在获得值之前一直保持活动状态,而不是在函数内部的局部作用域结束后取消初始化。我想要实现的一个很好的例子是UIView.animate()完成块,即使它位于某个函数内部也不会被释放。

2 个答案:

答案 0 :(得分:0)

您需要将MyXMLParser存储在本地变量以外的其他位置。就这么简单。

请注意,UIView.animate(...) class 方法。这意味着该类以某种方式参与了生命周期管理。

一种简单的模仿方法是稍微更改您的界面,以便让类代替您直接创建MyXMLParser,而不是直接创建class MyXMLParser : NSObject, XMLParserDelegate { private static var createdParsers: Set<MyXMLParser> = [] static func parse(_ xml: String, _ completion: @escaping (String?) -> Void) { let newParser = MyXMLParser(xml, completion) self.createdParsers.insert(newParser) } private static func parserDidEndParsing(_ parser: MyXMLParser) { self.createdParsers.remove(parser) } private let parser: XMLParser private let completion: (String?) -> Void private init(_ xml: String, _ completion: @escaping (String?) -> Void) { // Same as existing code } //... func parserDidEndDocument(_ parser: XMLParser) { //... MyXMLParser.parserDidEndParsing(self) } }

MyXMLParser.parse(myXmlString) { (text) in /* whatever */ }

这里,单个解析器归其类所有,您可以通过调用parserDidEndDocument创建一个解析器。重要的是要注意 public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; } 中的清理步骤,即从该类的存储集合中删除该实例,这样就不会再有未使用的实例了。

答案 1 :(得分:0)

您需要确保您的parser对象保持存在。现在someFunc结束时,它消失了。您可能需要将parser声明为类级变量。