61

このコード スニペットの何が問題なのかを理解するのに苦労しています。これは現在 Objective-C で機能していますが、Swift ではメソッドの最初の行でクラッシュするだけです。コンソール ログにエラー メッセージが表示されます: Bad_Instruction

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!  {
        var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell

        if (cell == nil) {
            cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "Cell")
        }

        cell.textLabel.text = "TEXT"
        cell.detailTextLabel.text = "DETAIL TEXT"

        return cell
    }
4

17 に答える 17

82

ソリューションの後半を含むマットの回答も参照してください

カスタム サブクラスや nib を作成せずに解決策を見つけてみましょう

nil本当の問題は、Swift が空にできるオブジェクト ( ) と空にできないオブジェクトを区別するという事実にあります。識別子の nib を登録しない場合は、dequeueReusableCellWithIdentifierを返すことができnilます。

つまり、変数をオプションとして宣言する必要があります。

var cell : UITableViewCell?

as?notを使用してキャストする必要がありますas

//variable type is inferred
var cell = tableView.dequeueReusableCellWithIdentifier("CELL") as? UITableViewCell

if cell == nil {
    cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "CELL")
}

// we know that cell is not empty now so we use ! to force unwrapping but you could also define cell as
// let cell = (tableView.dequeue... as? UITableViewCell) ?? UITableViewCell(style: ...)

cell!.textLabel.text = "Baking Soda"
cell!.detailTextLabel.text = "1/2 cup"

cell!.textLabel.text = "Hello World"

return cell
于 2014-06-04T09:48:05.480 に答える
64

スルタンの答えは巧妙ですが、本当の解決策は次のとおりですdequeueReusableCellWithIdentifier。それは最初のあなたの間違いでした。

このメソッドは完全に時代遅れであり、正式に廃止されていないことに驚いています。Swift に対応できるシステム (iOS 7 または iOS 8) は、目的を問わず Swift を必要としません。

代わりに、最新のメソッドdequeueReusableCellWithIdentifier:forIndexPath:. これには、オプションが含まれていないという利点があります。セルが返されることが保証されます。クエスチョンマークやエクスクラメーションマークがすべて消え、セルの存在が保証されているためlet代わりに使用でき、便利な現代の世界に住んでいます。var

ストーリーボードを使用していない場合は、事前にこの識別子のテーブルを登録して、クラスまたは nib を登録する必要があります。それを行う従来の場所はviewDidLoad、テーブルビューが存在するのと同じくらい早いです。

カスタム セル クラスを使用した例を次に示します。

override func viewDidLoad() {
    super.viewDidLoad()
    self.tableView.registerClass(MyCell.self, forCellReuseIdentifier: "Cell")
}

// ...

override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath:indexPath) as MyCell
    // no "if" - the cell is guaranteed to exist
    // ... do stuff to the cell here ...
    cell.textLabel.text = // ... whatever
    // ...
    return cell
}

ただし、ストーリーボードを使用している場合 (ほとんどの人が使用しています)、テーブル ビューを に登録する必要さえありませんviewDidLoad。ストーリーボードにセル識別子を入力するだけで、すぐに使用できますdequeueReusableCellWithIdentifier:forIndexPath:

于 2014-07-23T14:18:52.630 に答える
18

@Sulthanの答えは的を射ています。考えられる便利な変更の 1 つは、セルを UITableViewCell ではなく UITableViewCell! としてキャストすることです。

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
    var cell = tableView.dequeueReusableCellWithIdentifier("CELL") as UITableViewCell!
    if !cell {
        cell = UITableViewCell(style:.Default, reuseIdentifier: "CELL")
    }
    // setup cell without force unwrapping it
    cell.textLabel.text = "Swift"
    return cell
}

これで、セル変数を毎回強制的にアンラップすることなく変更できます。暗黙的にラップ解除されたオプションを使用する場合は注意してください。アクセスしている値に値があることを確認する必要があります。

詳細については、The Swift Programming Languageの「Implicitly Unwrapped Optionals」セクションを参照してください。

于 2014-06-15T22:10:21.157 に答える
8

これを試して:

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
    cell.textLabel.text = "\(indexPath.row)"

    return cell
}

UITableViewCellインスタンス化を作成するときは、あなたと IDを登録する必要があることに注意してUITableViewください。

tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: "Cell")
于 2014-06-03T18:55:05.423 に答える
8

これが私がそれを機能させるために書いたものです...

最初にテーブルビューセルをテーブルビューに登録します

self.tableView.registerClass(MyTableViewCell.self, forCellReuseIdentifier: "Cell")

次に、cellForRowAtIndexPath を構成します

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!  {
    var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as MyTableViewCell

    cell.textLabel.text = "Cell Text"
    cell.detailTextLabel.text = "Cell Detail Text in Value 1 Style"

    return cell
}

次に、ファイルの下部にカスタム セル サブクラスの書き込みを定義しました (これは非常に簡単になったためです)。

class MyTableViewCell : UITableViewCell {

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

}
于 2014-06-04T03:38:41.063 に答える
4

ここにはいくつかの答えがありますが、宣言の後、オプションの UITableViewCell が必要になるため、いずれも理想的ではないと思いますcell!...。これはより良いアプローチだと思います(これがXcode 6.1でコンパイルされることを確認できます):

var cell:UITableViewCell

if let c = tableView.dequeueReusableCellWithIdentifier("cell") as? UITableViewCell {
    cell = c
}
else {
    cell = UITableViewCell()
}
于 2014-10-27T06:12:11.423 に答える
2

さて、私はこのようにしました:

Swiftを使用したUITableViewの手順:

  • ViewControllerでUITableView取得する
  • ViewController.swiftクラスで参照アウトレット与える
  • OutletsにdataSourceを与え、ViewController委譲する

ViewController.swiftクラスのSwiftコード:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var mTableView: UITableView!

    var items: [String] = ["Item 1","Item 2","Item 3", "Item 4", "Item 5"]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.mTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.items.count;
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell:UITableViewCell = self.mTableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell

        cell.textLabel?.text = self.items[indexPath.row]
         println(self.items[indexPath.row])

        return cell
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        println("You have selected cell #\(indexPath.row)!")
    }
}

次に、プログラムを実行します

終わり

于 2015-08-02T14:23:11.333 に答える
1

「as」キーワードを使用すると、次の 2 つの手順が実行されます
。1.UITableViewCell の変数をラップするオプションの値を作成します。
2.オプションの値をアンラップします。

なので、こうすることで

var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Component") as UITableViewCell

「プレーンな」UITableViewCell型変数を取得します: cell.理論的に言えば、これを実行しても問題ありません.しかし、次の行

if (cell == nil) {}

Swiftでは、オプションの値のみをnilに割り当てることができるため、問題が発生します。

したがって、この問題を解決するには、セルを Optional 型の変数にする必要があります。ちょうどこのような:

var cell = tableView.dequeueReusableCellWithIdentifier("Component") as? UITableViewCell

「as?」というキーワードを使用して Optional 変数を作成しますが、これには間違いなく nil を割り当てることができます。

于 2015-01-16T06:28:46.253 に答える
1

実際、Apple の TableView ガイド ドキュメントとサンプル コードには、次の文があります。

dequeueReusableCellWithIdentifier: メソッドがストーリーボードで定義されているセルを要求する場合、メソッドは常に有効なセルを返します。再利用されるのを待っているリサイクルされたセルがない場合、メソッドはストーリーボード自体の情報を使用して新しいセルを作成します。これにより、nil の戻り値を確認して手動でセルを作成する必要がなくなります。

したがって、次のようにコーディングできます。

var identifer: String = "myCell"
var cell = tableView.dequeueReusableCellWithIdentifier(identifer) as UITableViewCell
cell.textLabel.text = a[indexPath.row].name
cell.detailTextLabel.text = "detail"

これはtableViewの適切な使用方法だと思います

于 2014-09-01T02:44:06.540 に答える
0

仲間、サンプルを見てください https://github.com/brotchie/SwiftTableView

于 2014-06-07T09:32:08.747 に答える