[swift4] XMLparserでXMLを読み込み、TableViewに反映
XMLparserでXMLを読み込み、TableViewに反映させるには、以下のコードのように実装する
XMLParserDelegateを実装して、Delegeteのレスポンスごとに配列を作成し、XMLの読み込みが終了したら、TableViewをReloadする。
import UIKit
class testTableViewContoller: UIViewController, UITableViewDelegate, UITableViewDataSource,XMLParserDelegate{
@IBOutlet weak var tableView: UITableView!
//XMLのフィード取得用URL
let feedUrl : NSURL = NSURL(string:"xxxxx.xml")!
//XMLの現在要素名を入れる変数
var currentElementName : String!
//取得する要素名(とりはじめの要素)
let itemElementName : String = "item"
//取得する要素名の決定(item要素の下にあるもの)
let nameElementName : String = "name"
let makerElementName : String = "maker"
let priceElementName : String = "price"
let typeElementName : String = "type"
let urlElementName : String = "url"
let imageElementName : String = "image"
//各エレメント用の変数
var posts:[Dictionary]!
var elements:Dictionary = [String: String]()
var element:String!
var name:String!
var maker:String!
var price:String!
var type:String!
var url:String!
var image:String!
//MARK: didload
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
posts = []
}
override func viewDidAppear(_ animated: Bool) {
//NSXMLParserクラスのインスタンスを準備
let parser : XMLParser = XMLParser(contentsOf: feedUrl as URL)!
if parser != nil {
// XMLParserDelegateをセット
parser.delegate = self;
parser.parse()
//print("parser.parse")
} else {
// パースに失敗した時
print("failed to parse XML")
}
}
//XMLを読み込み開始
func parserDidStartDocument(_ parser: XMLParser) {
//print("parserDidStartDocument")
}
//XMLの読み込み終了
func parserDidEndDocument(_ parser: XMLParser!)
{
print("reload table")
self.tableView.reloadData() //TableViewをReload
}
//各エレメントの読み込み開始
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
self.element = elementName as String
//要素名が「item」の要素が見つかった場合には上で設定したメンバ変数を初期化
if (elementName as NSString).isEqual(to: self.itemElementName){
self.elements = [:]
self.name = ""
self.maker = ""
self.price = ""
self.type = ""
self.url = ""
self.image = ""
}
}
//各エレメントの中の要素を見つけた場合のメソッド
func parser(_ parser: XMLParser, foundCharacters string: String){
if self.element.isEqual(self.nameElementName) {
self.name.append(
strip(str:string)
)
}
if self.element.isEqual(self.makerElementName) {
self.maker.append(
strip(str:string)
)
}
if self.element.isEqual(self.priceElementName) {
self.price.append(
strip(str:string)
)
}
if self.element.isEqual(self.typeElementName) {
self.type.append(
strip(str:string)
)
}
if self.element.isEqual(self.urlElementName) {
self.url.append(
strip(str:string)
)
}
if self.element.isEqual(self.imageElementName) {
self.image.append(
strip(str:string)
)
}
}
//改行と半角スペースの除去
func strip(str: String) -> String {
var strBr: String
var strSp: String
//改行除去
strBr = str.replacingOccurrences(of:"\n", with: "")
//半角スペース除去
strSp = strBr.replacingOccurrences(of:" ", with: "")
return strSp
}
//エレメントの読み込みが終了
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
if (elementName as NSString).isEqual(to: self.itemElementName) {
//各メンバ変数がnilでなければメンバ変数elementsへ「キー」と「値」のペアを格納
if !self.name.isEqual(nil) {
self.elements[nameElementName] = self.name
}
if !self.maker.isEqual(nil) {
self.elements[makerElementName] = self.maker
}
if !self.price.isEqual(nil) {
self.elements[priceElementName] = self.price
}
if !self.type.isEqual(nil) {
self.elements[typeElementName] = self.type
}
if !self.url.isEqual(nil) {
self.elements[urlElementName] = self.url
}
if !self.image.isEqual(nil) {
self.elements[imageElementName] = self.image
}
self.posts.append(self.elements)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//セルの数
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if posts.count > 0{
return posts.count
}
return 10 //最初もしくはXMLが読み込まなれなかった場合は10行
}
// sectionの数を決める
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
//TableViewのセルの設定
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath)
let imageView = cell.contentView.viewWithTag(1) as! UIImageView
imageView.image = nil //イメージ初期化
let label = cell.contentView.viewWithTag(2) as! UILabel
//イメージ読み込みのインジケータ
let indicator = cell.contentView.viewWithTag(3) as! UIActivityIndicatorView
indicator.startAnimating()
indicator.isHidden = true
//要素を読みこんだpostsがあれば
if(posts.count>0){
if let name = posts[indexPath.row]["name"] {
label.text = name as? String
} else {
label.text = ""
}
//画像の読み込み(Optionalの型のnil判定がうまく行かず2段確認になってしまった)
if let imageURL:String = posts[indexPath.row]["image"] {
if(!imageURL.isEmpty){
indicator.isHidden = false
//画像の非同期ダウンロード(ただしキャッシュされないので、キャッシュの実装が必要)
let catPictureURL = URL(string: imageURL)
let session = URLSession(configuration: .default)
let downloadPicTask = session.dataTask(with: catPictureURL!) { (data, response, error) in
// The download has finished.
indicator.isHidden = true
if let e = error {
print("Error downloading cat picture: \(e)")
} else {
if let res = response as? HTTPURLResponse {
print("Downloaded cat picture with response code \(res.statusCode)")
if let imageData = data {
imageView.image = UIImage(data: imageData)
} else {
print("Couldn't get image: Image is nil")
}
} else {
print("Couldn't get response code for some reason")
}
}
}
downloadPicTask.resume()
}
}else{
//画像がない場合
}
}
return cell
}
}