web-dev-qa-db-ja.com

SwiftのカスタムUITableViewCellレジスタクラス

私のアプリケーションでは、配列に基づいてテーブルを埋めます。テーブルはカスタムUITableViewCellを使用します。すべてが正常に機能し、テーブルがいっぱいです。次に、検索表示コントローラーをUITableViewControllerに追加します。検索を処理するコードを記述せずに、コントローラーを追加するだけです。アプリケーションを実行すると、テーブルはまだ埋められていますが、検索バーをクリックしようとすると、エラーが発生します:

_Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier CitiesListCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'_

UITableViewController行のviewDidLoad関数に追加しようとしています:

self.tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)

アプリケーションを起動し、すぐにエラーを取得します。

_fatal error: unexpectedly found nil while unwrapping an Optional value_

行_cell.cellMyCity.text = cellText_

私は何を間違えていますか?

これは私のカスタムUITableViewCellクラスです:

_import UIKit

class MyCell: UITableViewCell {

@IBOutlet var cellMyImage: UIImageView
@IBOutlet var cellMyCity: UILabel
@IBOutlet var cellMyCountry: UILabel
@IBOutlet var cellMyTemp: UILabel

init(style: UITableViewCellStyle, reuseIdentifier: String!) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
}

override func awakeFromNib() {
    super.awakeFromNib()
}

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

}
}
_

これはセルのコードです:

_override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {

    var cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier, forIndexPath: indexPath) as MyCell!

    if cell == nil {
        cell = MyCell(style: UITableViewCellStyle.Default, reuseIdentifier: kCellIdentifier)
    }

    let cellText: String? = dataWeatherSelectedCity[indexPath.row].name as  String
    println("Строка: \(cellText)")
    cell.cellMyCity.text = cellText

    let cellSubtitle: String? = dataWeatherSelectedCity[indexPath.row].country as String
    cell.cellMyCountry.text = cellSubtitle

    cell.cellMyImage.image = UIImage(named: "Blank52")

    var currentCityWeatherURL = "http://api.wunderground.com/api/\(self.myAPI.kWundergroundApiKey)/conditions/lang:RU/q/zmw:\(self.dataWeatherSelectedCity[indexPath.row].zmv).json"

    var fullObservation:NSDictionary = self.myAPI.jsonParsingWeather(currentCityWeatherURL)
    var currentObservation:NSDictionary = fullObservation.valueForKey("current_observation") as NSDictionary

    var currentWeather = self.myAPI.parsingOneCityCurrentCondition(currentObservation)       
    cell.cellMyImage.image = currentWeather.image
    cell.cellMyTemp.text = currentWeather.temp
    return cell
}
_

TableViewCellのプロパティ: enter image description hereenter image description hereenter image description here

self.tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)またはself.tableView.registerClass(MyCell.self, forCellReuseIdentifier: kCellIdentifier)なしのテーブル:

enter image description here

17
Alexey Nakhimov

エラーとして、cellまたはUITestFieldnilを取得していることを示唆しており、Swiftはnilオブジェクトのメソッド呼び出しをサポートしていないため、クラッシュします。オブジェクトがnilであるかどうかを確認することでクラッシュを防ぐことができます

if var label = cell.cellMyCity{
    label.text = cellText
}

[〜#〜] edit [〜#〜]

ここで何が問題なのかわかったと思う...

UISearchBarにドラッグアンドドロップstoryboardがあるため、デフォルトではすべてのデータソースとデリゲートがコントローラーに設定され、たとえばViewController( UITableView DataSourceメソッドをオーバーライドするクラス)およびそのViewControllerでMyCellクラスをカスタマイズクラスとして登録します。したがって、tableViewは完璧に表示されますが、UISearchBarに何かを入力すると、同じDataSourceメソッド(ViewController)が呼び出され、そこにもMyCellをsearchResultsTableViewUISearchDisplayController tableView thatsに登録します検索結果)、しかし、それはMyCellを知らないので、cell.cellMyCityは検索の場合はnilになります。つまり、searchResultsTableViewはデフォルトのUITableViewCellを期待し、デフォルトのセルには次のような設定はしません-

cell.textLabel.text = countryList[indexPath.row]

このシナリオ全体は、以下のようにDataSourceメソッドを変更することで確認できます。

    override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {

    var cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as MyCell!
    if cell == nil {
        //tableView.registerNib(UINib(nibName: "UICustomTableViewCell", bundle: nil), forCellReuseIdentifier: "UICustomTableViewCell")
        tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)

        cell = MyCell(style: UITableViewCellStyle.Default, reuseIdentifier: kCellIdentifier)
    }
    if var label = cell.cellMyCity{
        label.text = countryList[indexPath.row]
    }
    else{
        cell.textLabel.text = countryList[indexPath.row]
    }
    return cell
}

解決策が懸念されるに関する限り、2つの解決策が考えられます。

A)。 searchResultsTableViewUISearchDisplayControllerで提供)を使用して、tableViewと同じViewControllerに検索結果を表示しないでください。そのためにできることは、ユーザーがUISearchBarに何かを入力したときにUISearchBarデリゲートをリッスンし、Predicatesで結果データソースを取得し(同じ配列で結果を表示)UITableView

B)。 UISearchDisplayControllerをカスタマイズし、searchResultsTableViewのカスタムセル(つまりMyCell)を使用します

8

私がその仕事をするためにしたことは次のようなものです:

_class MainViewController: UIViewController {

    // ...

    @IBOutlet var tableView: UITableView

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.registerNib(UINib(nibName: "UICustomTableViewCell", bundle: nil), forCellReuseIdentifier: "UICustomTableViewCell")

        // ...
    }

    // ...

}
_

注:を使用する場合–registerClass(_: forCellReuseIdentifier:)メソッド、xibファイルはロードされないため、プログラムでコンテンツを追加しない限り、実際のカスタムインターフェイスは表示されませんセル。nibファイルからインターフェイスをロードする場合は、セルをそのnibに登録する必要があります。


必須プロトコルの適合:

_extension MainViewController: UITableViewDataSource {

    func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
        let cell: UICustomTableViewCell = tableView.dequeueReusableCellWithIdentifier(UICustomTableViewCell.reuseIdentifier) as UICustomTableViewCell
        println(cell)
        return cell;
    }

}

//

extension MainViewController: UITableViewDelegate {

    func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
        return 44.0
    }

}
_

カスタムセルクラスは、UICustomTableViewCellのような意味のある名前を持つ非常に汎用的なクラスです。

_class UICustomTableViewCell: UITableViewCell {

    class var reuseIdentifier: String {
        get {
            return "UICustomTableViewCell"
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}
_

非常にランダムなインターフェースで:

random custom interface

カスタムクラスおよび識別子の再利用のこれらの設定:

custom classreuse identifier


そして、私の画面の最終結果は3行で予想通りです:

the final result in practice

注:カスタムセルをさらにカスタマイズするには、上記のコードを拡張する必要がある場合があります。

更新

UISearchBarを使用すると、最終結果は次のようになります。

with Search Bar

19
holex

selfの前にtableViewを追加すると、問題が修正されます。

var cell = self.tableView.dequeueReusableCellWithIdentifier(kCellIdentifier, forIndexPath: indexPath) as MyCell!
10

ストーリーボードを使用している場合は、ストーリーボードとそれに関連付けられているすべてのアウトリンクを上書きするため、必ず登録クラスを削除してください

確認してください https://stackoverflow.com/a/26350795/445358

私のために働く=)

2
Sunny Hardasani

SearchDisplayController.tableViewを含む、それを使用するtableViewのセルを忘れずに登録する必要があります。

1
JimmyB