我有一个实现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()
完成块,即使它位于某个函数内部也不会被释放。
答案 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
声明为类级变量。