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
}
832   17  

17 ответов:

см. Также Мэтт!--10-->, который содержит вторую половину раствора

давайте найдем решение без создания пользовательских подклассов или крупка

реальная проблема заключается в том, что 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:. Это имеет то преимущество, что никакие опционные не участвуют; вы гарантированный что ячейка будет возвращена. Все вопросительные и восклицательные знаки отпадают, вы можете использовать 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 находится на месте. Одной из возможных модификаций удобства было бы привести ячейку как 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
}

теперь вы можете изменить переменную ячейки без принудительного разворачивания ее каждый раз. Будьте осторожны при использовании неявно развернутых опций. Вы должны быть уверены, что значение, к которому вы обращаетесь, имеет значение.

для получения дополнительной информации обратитесь к разделу "неявно развернутые дополнительные"Свифт Язык Программирования.

попробуйте это:

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")

вот что я написал, чтобы заставить его работать...

сначала зарегистрируйте ячейку табличного представления с табличным представлением

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
}

затем я определил пользовательский подкласс ячейки write в нижней части файла (так как теперь это намного проще)

class MyTableViewCell : UITableViewCell {

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

}

здесь есть несколько ответов, но я не думаю, что любой из них идеален, потому что после объявления вы получаете дополнительный UITableViewCell, который затем нуждается в cell!... в любом толковании. Я думаю, что это лучший подход (я могу подтвердить, что это компилируется на Xcode 6.1):

var cell:UITableViewCell

if let c = tableView.dequeueReusableCellWithIdentifier("cell") as? UITableViewCell {
    cell = c
}
else {
    cell = UITableViewCell()
}

вот простой способ определить ячейку таблицы в 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
}

Ну, я сделал так:

шаги UITableView используя Свифт:

  • забрать UITableView на ViewController
  • дать Ссылки На Розетки на ViewController.Свифт класс
  • Дать Точках источник & делегат до ViewController

теперь Свифт код в ViewController.Свифт класс:

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", выполните следующие два шага:
1.создание необязательного значения, которое обертывает переменную UITableViewCell;
2.разворачивании необязательное значение.

Итак,делая это

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

вы получите "простую" переменную типа UITableViewCell: cell.Теоретически говоря,это нормально.Но следующая строка

if (cell == nil) {}

создает проблемы, потому что в swift только необязательное значение может быть назначено с нулем.

так, чтобы решите эту проблему, вы должны сделать ячейку переменной необязательного типа. вот так:

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

используя ключевое слово " как?"будет создана необязательная переменная, и это, несомненно, может быть присвоено нулю.

шаблон ячейки:

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
        let myCell : youCell =  youCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
        return myCell
    }

братан, пожалуйста, взгляните на образец https://github.com/brotchie/SwiftTableView

почему не этот?

(пожалуйста, удалите, если я не в цель...)

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

    if let cell: UITableViewCell = theTableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as? UITableViewCell {
        // cell ok
    }else{
       // not ok
    }
}

Я сделал следующим образом: чтобы показать 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

UITableView демо с помощью Playground

//: 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

Я прошел через ваши коды и, скорее всего, причина аварии заключается в том, что вы пытаетесь ввести необязательное значение, которое не назначено

теперь рассмотрим строку кода ниже

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

когда в tableview нет ячеек, вы все еще пытаетесь ввести как UITableView.Когда компилятор пытается ввести нулевое значение, вы сталкиваетесь с этой проблемой

правильное утверждение должно быть

var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") 

вы можете использовать оператор if else для typecast для значений, которые содержат

попробуйте этот код

var cell:CustomTableViewCell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell") as CustomTableViewCell
cell.cellTitle.text="vijay"

https://github.com/iappvk/TableView-Swift

Comments

    Ничего не найдено.