UITableView в Swift
Я изо всех сил пытаюсь понять, что случилось с этим фрагментом кода. В настоящее время это работает в 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
}
Ответы
Ответ 1
Также см. матовый ответ, который содержит вторую половину решения
Найти решение без создания пользовательских подклассов или nibs
Реальная проблема заключается в том, что Swift различает объекты, которые могут быть пустыми (nil
), и объекты, которые не могут быть пустыми. Если вы не зарегистрируете нить для своего идентификатора, тогда 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
Ответ 2
Ответ Sulthan умный, но реальное решение: не вызывайте dequeueReusableCellWithIdentifier
. Это была ваша ошибка с самого начала.
Этот метод полностью устарел, и я удивлен, что он официально не устарел; никакая система, которая может вместить Swift (iOS 7 или iOS 8), не нуждается ни в каких целях.
Вместо этого вызовите современный метод dequeueReusableCellWithIdentifier:forIndexPath:
. Это имеет то преимущество, что никакие опции не задействованы; вы гарантировали, что ячейка будет возвращена. Все вопросительные знаки и восклицательные знаки отпадают, вы можете использовать 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:
.
Ответ 3
@Ответ Sulthan - это место. Одна из возможных модификаций удобства заключается в том, чтобы скрыть ячейку как 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
}
Теперь вы можете изменить переменную ячейки без принудительной разворачивания ее каждый раз. Соблюдайте осторожность при использовании неявно развернутых опций. Вы должны быть уверены, что значение, к которому вы обращаетесь, имеет значение.
Для получения дополнительной информации см. раздел "Неявно отключенные опции" на языке Swift Programming.
Ответ 4
Попробуйте следующее:
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")
Ответ 5
Вот что я написал, чтобы заставить его работать...
Сначала зарегистрируйте ячейку таблицы со списком таблиц
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)
}
}
Ответ 6
Здесь несколько ответов, но я не думаю, что любой из них идеален, потому что после объявления вы получаете опциональный UITableViewCell, который тогда нуждается в cell!...
в любых объявлениях. Я думаю, что это лучший подход (я могу подтвердить этот компилятор на Xcode 6.1):
var cell:UITableViewCell
if let c = tableView.dequeueReusableCellWithIdentifier("cell") as? UITableViewCell {
cell = c
}
else {
cell = UITableViewCell()
}
Ответ 7
Вот простой способ определить ячейку таблицы в 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
}
Swift 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
}
Ответ 8
Ну, я сделал так:
Шаги для UITableView с помощью Swift:
- Возьмите UITableView в ViewController
- Дайте Referuting Outlets в классе ViewController.swift
- Выдать dataSource и делегировать на ViewController
Теперь Swift в классе ViewController.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)!")
}
}
Теперь пришло время Запустить программу.
Готово
Ответ 9
Фактически в документе Apple TableView Guide и в примере кода вы найдете следующее предложение:
Если метод 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
Ответ 10
Использование ключевого слова "as" выполняет следующие два действия:
1.Создание необязательного значения, которое обертывает переменную UITableViewCell;
2.unupping необязательное значение.
Итак, сделав это
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Component") as UITableViewCell
вы получили бы "обычную" переменную типа UITableViewCell: cell. Теоретически это нормально делать. Но следующая строка
if (cell == nil) {}
создает проблемы, потому что в swift может быть назначено только необязательное значение с помощью nil.
Итак, чтобы решить эту проблему, вы должны сделать ячейку переменной необязательного типа. просто так:
var cell = tableView.dequeueReusableCellWithIdentifier("Component") as? UITableViewCell
используя ключевое слово "as?" создаст необязательную переменную, и это, без сомнения, может быть назначено с помощью nil.
Ответ 11
Для шаблона ячейки:
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let myCell : youCell = youCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
return myCell
}
Ответ 12
bro, пожалуйста, взгляните на образец https://github.com/brotchie/SwiftTableView
Ответ 13
Почему не это?
(пожалуйста, удалите, если я не в цель...)
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
if let cell: UITableViewCell = theTableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as? UITableViewCell {
// cell ok
}else{
// not ok
}
}
Ответ 14
Я сделал следующее: чтобы показать 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
Ответ 15
UITableView Demo с использованием игровой площадки
//: 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
Ответ 16
Я просмотрел ваши коды и, скорее всего, причина сбоя в том, что вы пытаетесь придумать необязательное значение, которое не назначено
Теперь рассмотрим строку кода ниже
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
Когда в представлении таблицы нет ячеек, вы все еще пытаетесь ввести тип в качестве UITableView. Когда компилятор пытается определить значение nil, которое вы сталкиваетесь с этой проблемой
Правильный оператор должен быть
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell")
Вы можете использовать if else для typecast для значений, которые содержат
Ответ 17
Попробуйте этот код
var cell:CustomTableViewCell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell") as CustomTableViewCell
cell.cellTitle.text="vijay"
https://github.com/iappvk/TableView-Swift