Ich wollte beginnen, meine Android App mit Swift zu schreiben. Die App soll ein xml von einer URL verwenden, um eine Liste von Objekten anzuzeigen.Swift Fehler beim Auslagern einer Methode auf eine statische Methode
Die Analyse und Anzeige in einem UITableViewController funktioniert bereits. Jetzt möchte ich die Analyse in eine statische Klasse auslagern, die ich verwenden kann, wann immer ich die Liste der Objekte erhalten möchte.
Das Problem ist, dass ich einen EXC_BAD_ACCESS Fehler erhalte, wenn ich die ausgelagerte Klasse verwende. Ich denke, das Problem könnte sein, dass ich versuche, auf Speicher zuzugreifen, der bereits freigegeben wurde, aber ich bin mir nicht sicher.
Im Folgenden finden Sie den Code finden können, die ich verwende:
XML (vereinfacht):
<result>
<row>
<id>1</id>
<name>Alpha</name>
</row>
<row>
<id>2</id>
<name>Beta</name>
</row>
<row>
<id>3</id>
<name>Gamma</name>
</row>
</result>
XMLHelper.swift (Outsourcing-Klasse, verwendet die ausgelagerte Klasse ToolXMLParserDelegate.swift):
import Foundation
class XMLHelper : NSObject{
static var baseURL = "{myServerUrl}" // not public for security reasons
static var toolListString = "getToolList.php"
class func getToolList() -> [Tool]? {
var toolList: [Tool] = []
let url = baseURL+toolListString
guard let myURL = URL(string: url) else {
print("URL not defined properly")
return nil
}
guard let parser = XMLParser(contentsOf: myURL as URL) else {
print("Cannot Read Data")
return nil
}
parser.delegate = ToolXMLParserDelegate(toolList: &toolList)
if !parser.parse() { //HERE I GET THE ERROR
print("Data Errors Exist:")
let error = parser.parserError!
print("Error Description:\(error.localizedDescription)")
//print("Error reason:\(error.localizedFailureReason)")
print("Line number: \(parser.lineNumber)")
}
return toolList
}
}
ToolXMLParserDelegate.swift:
import Foundation
class ToolXMLParserDelegate : NSObject, XMLParserDelegate {
var tools: [Tool] = []
var eName: String = String()
var toolId = String()
var toolName = String()
init(toolList : inout [Tool]) {
self.tools = toolList
}
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
eName = elementName
if elementName == "row" {
toolId = String()
toolName = String()
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
if elementName == "row" {
let tool = Tool()
tool.id = Int(toolId)!
tool.name = toolName
tools.append(tool)
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
let data = string.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
if (!data.isEmpty) {
if eName == "id" {
toolId += data
} else if eName == "name" {
toolName += data
}
}
}
}
Tool.swift:
import UIKit
class Tool: NSObject {
var id: Int = Int()
var name: String = String()
override init() {}
init(id: Int, name: String) {
self.id = id
self.name = name
}
init(name: String) {
self.name = name
}
}
ToolTableViewController.swift: (verwendet XMLHelper.getToolList())
import UIKit
class ToolTableViewController: UITableViewController, XMLParserDelegate {
var tools: [Tool] = []
var eName: String = String()
var toolId = String()
var toolName = String()
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView() // to remove empty cells in the list
}
override func viewWillAppear(_ animated: Bool) {
tools = XMLHelper.getToolList()!
// this code piece is working, but i want to outsource it, so i can use it again
/*
let url = "{myUrl}" // not public for security reason
let myURL = URL(string: url)
let parser = XMLParser(contentsOf: myURL!)!
parser.delegate = self as XMLParserDelegate
parser.parse()
*/
tableView.reloadData()*/
print("view did refresh")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tools.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
let cellIdentifier = "ToolTableViewCell" // simple TableViewCell with a label
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? ToolTableViewCell else {
fatalError("The dequeued cell is not an instance of ToolTableViewCell.")
}
let tool = tools[indexPath.row]
cell.labelName.text = String(tool.id)+" "+tool.name
return cell
}
// MARK: XMLParserDelegate (this code here is only used when the code above is uncommented, it is the same as the code in ToolXMLParserDelegate)
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
eName = elementName
if elementName == "row" {
toolId = String()
toolName = String()
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
if elementName == "row" {
let tool = Tool()
tool.id = Int(toolId)!
tool.name = toolName
tools.append(tool)
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
let data = string.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
if (!data.isEmpty) {
if eName == "id" {
toolId += data
} else if eName == "name" {
toolName += data
}
}
}
}
können Sie Vergangenheit Fehlerprotokoll, ich, was Sie etwas deutlicher verpasst. – Maxime
um Klassenfunktionen statisch zu machen, deklariere die Funktion als 'class func()' {} –
Könntest du die Klasse XMLParser posten? Ich weiß nicht, ob du die Delegiertenklasse richtig verstanden hast –