このコードスニペットの何が問題なのかを理解するのに苦労しています。これは現在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
}
また、ソリューションの後半を含む mattの答え も参照してください
カスタムサブクラスやペン先を作成せずに解決策を見つけましょう
本当の問題は、Swiftが空にできるオブジェクト(nil
)と空にできないオブジェクトを区別するという事実にあります。識別子にペン先を登録しない場合、dequeueReusableCellWithIdentifier
はnil
を返すことができます。
つまり、変数をオプションとして宣言する必要があります。
var cell : UITableViewCell?
as
ではなく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
スルタンの答えは賢明ですが、本当の解決策は次のとおりです。dequeueReusableCellWithIdentifier
を呼び出さないでください。それは最初の間違いでした。
このメソッドは完全に時代遅れであり、正式に廃止されていないことに驚いています。 Swift(iOS 7またはiOS 8)に対応できるシステムは、どんな目的でもそれを必要としません。
代わりに、最新のメソッドdequeueReusableCellWithIdentifier:forIndexPath:
を呼び出します。これには、オプションが関係しないという利点があります。あなたはguaranteedセルが返されます。疑問符と感嘆符はすべて消えます。セルの存在が保証されているため、let
の代わりにvar
を使用できます。また、便利で現代的な世界に住んでいます。
ストーリーボードを使用していない場合は、事前にこの識別子のテーブルを登録し、クラスまたはペン先を登録する必要があります。これを行うための従来の場所は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:
を使用できます。
@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の「暗黙的にラップされていないオプション」セクションを参照してください。
これを試して:
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
のインスタンスを作成するときに、UITableView
とIDを登録する必要があることに注意してください。
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: "Cell")
これが動作するように書いたものです...
最初にテーブルビューセルをテーブルビューに登録します
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)
}
}
Swift 2:でテーブルセルを定義する簡単な方法を次に示します。
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let identifier = "cell"
let cell = tableView.dequeueReusableCellWithIdentifier(identifier) ??
UITableViewCell.init(style: UITableViewCellStyle.Default, reuseIdentifier: identifier)
cell.textLabel!.text = "my text"
return cell
}
スウィフト3:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let identifier = "cell"
let cell = tableView.dequeueReusableCell(withIdentifier: identifier) ??
UITableViewCell(style: .default, reuseIdentifier: identifier)
cell.textLabel!.text = "my text"
return cell
}
ここにはいくつかの答えがありますが、私はそれらのどれも理想的ではないと思います。なぜなら、宣言の後、オプションのUITableViewCellになり、そのために宣言でcell!...
が必要になるからです。私はこれがより良いアプローチだと思います(これはXcode 6.1でコンパイルすることを確認できます):
var cell:UITableViewCell
if let c = tableView.dequeueReusableCellWithIdentifier("cell") as? UITableViewCell {
cell = c
}
else {
cell = UITableViewCell()
}
さて、私はこのようにした:
ITableViewを使用する手順Swiftを使用:
今SwiftViewController.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)!")
}
}
それでは、プログラムを実行するにします。
完了
実際、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を使用するのに適した方法だと思います
「as」キーワードを使用すると、次の2つのステップが実行されます。
1.UITableViewCellの変数をラップするオプションの値を作成します。
2。オプション値のアンラップ。
だから、これをすることで
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Component") as UITableViewCell
「プレーンな」UITableViewCell型変数を取得します:cell。理論的には、これを行うことは問題ありません。
if (cell == nil) {}
swiftでは、nilを使用してオプション値のみを割り当てることができるため、問題が発生します。
したがって、この問題を解決するには、セルをオプション型の変数にする必要があります。ちょうどこのような:
var cell = tableView.dequeueReusableCellWithIdentifier("Component") as? UITableViewCell
キーワード「as?」を使用するオプション変数を作成しますが、これは間違いなくnilで割り当てることができます。
仲間、サンプルを見てください https://github.com/brotchie/SwiftTableView
セルテンプレートの場合:
func tableView(tableView:UITableView !, cellForRowAtIndexPath indexPath:NSIndexPath!)-> UITableViewCell! { let myCell:youCell = youCell(style:UITableViewCellStyle.Subtitle、reuseIdentifier: "cell") return myCell }
DetailTextLabelを表示するには、次のようにしました。テキスト値
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellIdentifier: String = "cell"
var cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier) as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: CellIdentifier)
}
//cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
// parse the value of records
let dataRecord = self.paymentData[indexPath.row] as! NSDictionary
let receiverName = dataRecord["receiver_name"] as! String
let profession = dataRecord["profession"] as! String
let dateCreated = dataRecord["date_created"] as! String
let payAmount = dataRecord["pay_amount"] as! String
println("payment \(payAmount)")
cell!.textLabel?.text = "\(receiverName)\n\(profession)\n\(dateCreated)"
cell!.detailTextLabel?.text = "$\(payAmount)"
cell!.textLabel?.numberOfLines = 4
return cell!
}// end tableview
どうしてですか?
(ゴールにいない場合は削除してください...)
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
if let cell: UITableViewCell = theTableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as? UITableViewCell {
// cell ok
}else{
// not ok
}
}
私はあなたのコードを調べましたが、おそらくクラッシュの理由は、割り当てられていないオプションの値を型キャストしようとしていることです
次のコード行を考えてみましょう
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
テーブルビューにセルがない場合、UITableViewとして型キャストしようとしています。コンパイラがnil値を型キャストしようとすると、この問題に直面します
正しいステートメントは
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell")
If elseステートメントを使用して、保持する値を型キャストできます
Playgroundを使用したUITableViewデモ
//: Playground - noun: a place where people can play
import UIKit
import PlaygroundSupport
class TableviewDemoDelegate:NSObject,UITableViewDataSource,UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell:UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath)
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
}
cell?.textLabel?.text = "Item \(indexPath.row+1)"
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You have selected cell #\(indexPath.row)!")
}
}
var tableView = UITableView(frame:CGRect(x: 0, y: 0, width: 320, height: 568), style: .plain)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
let delegate = TableviewDemoDelegate()
tableView.delegate = delegate
tableView.dataSource = delegate
PlaygroundPage.current.liveView = tableView