UITableview ที่มีเซลล์ที่กำหนดเองมากกว่าหนึ่งเซลล์ด้วย Swift


111

ฉันต้องการใช้ UITableview กับ tableViewCells แบบกำหนดเองที่แตกต่างกัน เซลล์ 3 เซลล์ของฉันมีดังนี้:

  • Cell1: ควรมีรูปภาพและป้ายกำกับ
  • Cell2: ควรมีป้ายกำกับสองป้าย
  • Cell3: ควรมี dayPicker

ฉันไม่ต้องการโค้ดแท็กสำหรับเซลล์ ฉันจะจัดการสิ่งนี้ใน Swift ได้อย่างไร ฉันต้องเขียนโค้ดคลาสของตัวเองสำหรับทุกเซลล์หรือไม่ ฉันสามารถใช้ tableviewController หนึ่งตัวได้หรือไม่ ฉันจะเติมข้อมูลในเซลล์ต่างๆได้อย่างไร

ฉันต้องการสร้าง tableView เช่นแอปติดต่อของอุปกรณ์ iOS



คำตอบ:


270

ให้ฉันเริ่มด้วยการตอบคำถามของคุณก่อน

ฉันต้องเขียนโค้ดคลาสของตัวเองสำหรับทุกเซลล์หรือไม่ => ใช่ฉันเชื่ออย่างนั้น อย่างน้อยฉันก็จะทำแบบนั้น

ฉันสามารถใช้ tableviewController หนึ่งตัวได้หรือไม่ => ได้คุณทำได้ อย่างไรก็ตามคุณยังสามารถมีมุมมองตารางภายใน View Controller ของคุณได้อีกด้วย

ฉันจะเติมข้อมูลในเซลล์ต่างๆได้อย่างไร => ขึ้นอยู่กับเงื่อนไขคุณสามารถเติมข้อมูลในเซลล์ต่างๆ ตัวอย่างเช่นสมมติว่าคุณต้องการให้สองแถวแรกเป็นเหมือนเซลล์ประเภทแรก ดังนั้นคุณเพียงแค่สร้าง / ใช้เซลล์ประเภทแรกและตั้งค่าเป็นข้อมูล มันจะชัดเจนมากขึ้นเมื่อฉันแสดงภาพหน้าจอฉันเดา

ผมขอยกตัวอย่างด้วย TableView ภายใน ViewController เมื่อคุณเข้าใจแนวคิดหลักแล้วคุณสามารถลองแก้ไขได้ตามต้องการ

ขั้นตอนที่ 1: สร้าง 3 TableViewCells ที่กำหนดเอง ฉันตั้งชื่อมันว่า FirstCustomTableViewCell, SecondCustomTableViewCell, ThirdCustomTableViewCell คุณควรใช้ชื่อที่มีความหมายมากกว่านี้

ใส่คำอธิบายภาพที่นี่

ขั้นตอนที่ 2: ไปที่ Main.storyboard แล้วลากและวาง TableView ภายใน View Controller ของคุณ ตอนนี้เลือกมุมมองตารางและไปที่ตัวตรวจสอบข้อมูลประจำตัว ตั้งค่า "เซลล์ต้นแบบ" เป็น 3 ที่นี่คุณเพิ่งบอก TableView ของคุณว่าคุณอาจมีเซลล์ 3 ชนิดที่แตกต่างกัน

ใส่คำอธิบายภาพที่นี่

ขั้นตอนที่ 3: ตอนนี้เลือกเซลล์ที่ 1 ใน TableView ของคุณและในตัวตรวจสอบข้อมูลประจำตัวใส่ "FirstCustomTableViewCell" ในฟิลด์คลาสที่กำหนดเองจากนั้นตั้งค่าตัวระบุเป็น "firstCustomCell" ในตัวตรวจสอบแอตทริบิวต์

ใส่คำอธิบายภาพที่นี่

ใส่คำอธิบายภาพที่นี่

ทำเช่นเดียวกันกับคนอื่น ๆ ทั้งหมด - ตั้งค่าคลาสที่กำหนดเองเป็น "SecondCustomTableViewCell" และ "ThirdCustomTableViewCell" ตามลำดับ ตั้งค่าตัวระบุเป็น secondCustomCell และ thirdCustomCell ติดต่อกัน

ขั้นตอนที่ 4: แก้ไขคลาสเซลล์แบบกำหนดเองและเพิ่มร้านตามความต้องการของคุณ ฉันแก้ไขตามคำถามของคุณ

PS: คุณต้องวางร้านค้าภายใต้การกำหนดคลาส

ดังนั้นใน FirstCustomTableViewCell.swift ภายใต้ไฟล์

class FirstCustomTableViewCell: UITableViewCell {

คุณจะใส่ป้ายกำกับและช่องดูภาพของคุณ

 @IBOutlet weak var myImageView: UIImageView!
 @IBOutlet weak var myLabel: UILabel!

และใน SecondCustomTableViewCell.swift เพิ่มสองป้ายกำกับเช่น -

import UIKit

class SecondCustomTableViewCell: UITableViewCell {

    @IBOutlet weak var myLabel_1: UILabel!
    @IBOutlet weak var myLabel_2: UILabel!

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

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

และ ThirdCustomTableViewCell.swift ควรมีลักษณะดังนี้ -

import UIKit

class ThirdCustomTableViewCell: UITableViewCell {

    @IBOutlet weak var dayPicker: UIDatePicker!

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

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

ขั้นตอนที่ 5: ใน ViewController ของคุณสร้าง Outlet สำหรับ TableView ของคุณและตั้งค่าการเชื่อมต่อจากสตอรี่บอร์ด นอกจากนี้คุณต้องเพิ่ม UITableViewDelegate และ UITableViewDataSource ในนิยามคลาสเป็นรายการโปรโตคอล ดังนั้นนิยามชั้นเรียนของคุณควรมีลักษณะดังนี้ -

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

หลังจากนั้นแนบ UITableViewDelegate และ UITableViewDatasource ของมุมมองตารางของคุณเข้ากับคอนโทรลเลอร์ของคุณ ณ จุดนี้ viewController.swift ของคุณควรมีลักษณะดังนี้ -

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

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

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

ปล: หากคุณจะใช้ TableViewController แทนที่จะเป็น TableView ภายใน ViewController คุณสามารถข้ามขั้นตอนนี้ไปได้

ขั้นตอนที่ 6: ลากและวางมุมมองภาพและป้ายกำกับในเซลล์ของคุณตามคลาสเซลล์ จากนั้นให้เชื่อมต่อกับร้านค้าของพวกเขาจากสตอรี่บอร์ด

ขั้นตอนที่ 7: ตอนนี้เขียนวิธีการที่จำเป็นของ UITableViewDatasource ในตัวควบคุมมุมมอง

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

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

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

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

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        if indexPath.row == 0 {
            let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "firstCustomCell")
            //set the data here
            return cell
        }
        else if indexPath.row == 1 {
            let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "secondCustomCell")
            //set the data here
            return cell
        }
        else {
            let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "thirdCustomCell")
            //set the data here
            return cell
        }
    }

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

1
ฉันได้รับข้อความ: "ไม่สามารถแคสต์ค่าประเภท" UITableViewCell "(0x1dfbfdc) เป็น" Projekt.TitelTableViewCell "(0x89568)" ในเซลล์ funcForRowAtIndexPath ฉันใช้ UITableViewController และฉันมีคลาส "TitelTableViewCell" สำหรับเซลล์ที่กำหนดเองของฉัน "TitelZelle" ซึ่งฉันได้ตั้งค่าไว้ในตัวตรวจสอบข้อมูลประจำตัวของเซลล์ "TitelZelle" ฉันต้องทำอะไร?
Easyglider

ฉันหล่อเซลล์ของฉันเป็น! TitelTableViewCell เพื่อเติมองค์ประกอบ UI ที่กำหนดเองของฉันในเซลล์นี้
Easyglider

7
ลองใช้สิ่งนี้ => ให้ cell = tableView.dequeueReusableCellWithIdentifier ("TitelZelle", forIndexPath: indexPath) เป็น TitelTableViewCell
Natasha

2
@PradipKumar ปัญหาคืออะไร? ข้อผิดพลาดของคุณคืออะไร? Btw คุณควรถามคำถามหากคุณมีข้อสงสัยใด ๆ ความคิดเห็นที่ควรจะช่วยทำความเข้าใจหรือชี้แจงเกี่ยวกับปัญหานี้ผู้เขียนได้โพสต์ หากคุณมีปัญหาคุณควรไปที่คำถามและเริ่มโพสต์ของคุณเอง
Natasha

1
numberOfRowsInSection ช่วยให้ tableview กำหนดจำนวนแถวที่เราต้องการ ดังนั้นคุณควรระบุเฉพาะประโยคที่จะช่วยในการกำหนดจำนวนแถว indexpath.row == 0 หมายความว่าคุณมีแถวอยู่แล้ว แต่ในขณะนั้นตารางของคุณไม่ทราบว่ามีแถวหรือไม่ ดังนั้นคุณควรทำเช่นนั้น
Natasha

32

อัปเดต Swift 3.0 + พร้อมรหัสขั้นต่ำ

แนวคิดพื้นฐาน: สร้างมุมมองตารางด้วยต้นแบบเซลล์แบบไดนามิก กำหนดตัวระบุและสร้างคลาสเซลล์มุมมองตารางที่กำหนดเองสำหรับแต่ละเซลล์ต้นแบบ เริ่มต้นและแสดงเซลล์แบบกำหนดเองในวิธีการมอบหมายของมุมมองตาราง

1. สร้างเซลล์บนกระดานเรื่องราว

ลาก tableView ไปยังตัวควบคุมมุมมองของคุณเพิ่มเซลล์ต้นแบบลงไปจากนั้นวางองค์ประกอบ UI ลงในเซลล์มุมมองตารางของคุณเพิ่มข้อ จำกัด อย่างเหมาะสมหากจำเป็น

ใส่คำอธิบายภาพที่นี่

2. สร้างUITableViewCellคลาสที่กำหนดเอง

เพิ่มรหัสต่อไปนี้ในโครงการของคุณ ฉันวางไว้เหนือคลาสตัวควบคุมมุมมอง

class FirstTableCell: UITableViewCell {
}

class SecondTableCell: UITableViewCell {
}

class ThirdTableCell: UITableViewCell {   
}

3. กำหนดคลาสและตัวระบุที่กำหนดเองให้กับเซลล์ต้นแบบ

สำหรับแต่ละเซลล์ต้นแบบในสตอรีบอร์ดให้กำหนดคลาสแบบกำหนดเองที่สร้างขึ้นจากขั้นตอนที่ 2 จากนั้นป้อนตัวระบุที่ไม่ซ้ำกัน

ใส่คำอธิบายภาพที่นี่

4. เชื่อมต่อองค์ประกอบ UI กับรหัสที่รวดเร็ว

ควบคุมการลากมุมมองตารางและเชื่อมต่อกับคลาสตัวควบคุมมุมมอง ควบคุมลากองค์ประกอบ UI ที่เพิ่มลงในเซลล์ต้นแบบในขั้นตอนที่ 1 และเชื่อมต่อกับคลาสเซลล์มุมมองตารางที่เกี่ยวข้อง

ใส่คำอธิบายภาพที่นี่

5. เพิ่มรหัสเพื่อดูตัวควบคุมและควบคุมมุมมองตาราง

ทำให้ตัวควบคุมมุมมองของคุณสอดคล้องกับผู้รับมอบสิทธิ์มุมมองตาราง

class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate

ในviewDidLoadตั้งค่าผู้รับมอบสิทธิ์และแหล่งข้อมูลของมุมมองตาราง

override func viewDidLoad() {
    super.viewDidLoad()

    self.tableView.dataSource = self
    self.tableView.delegate = self

}

สุดท้ายเพิ่มวิธีการมอบหมายสองวิธีเพื่อควบคุมมุมมองตารางของคุณตามข้อกำหนดขั้นต่ำ

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.row == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "firstTableCell") as! FirstTableCell
        // Set up cell.label
        return cell
    } else if indexPath.row == 1 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "secondTableCell") as! SecondTableCell
        // Set up cell.button
        return cell
    } else {
        let cell = tableView.dequeueReusableCell(withIdentifier: "thirdTableCell") as! ThirdTableCell
        // Set up cell.textField
        return cell
    }
}

6. ลองดูสิ :)

ใส่คำอธิบายภาพที่นี่


สุดยอด! ฉันชอบภาพเคลื่อนไหวของคุณ
iphaaw

คุณช่วยบอกฉันได้ไหมว่าสามารถใส่ส่วนหัวสำหรับแต่ละเซลล์ได้หรือไม่? ถ้าเป็นอย่างไร
Pruthvi Hariharan

@PruthviHariharan หากคุณต้องการมี“ ส่วนหัว” สำหรับทุกเซลล์หรือส่วนใหญ่คุณไม่ควรติดตั้งเซลล์ส่วนหัวหรือส่วนหัวซึ่งต้องใช้โค้ดเพิ่มเติมในการจัดการและจะส่งผลต่อประสิทธิภาพ คำแนะนำของฉันคือให้วางมุมมองไว้ที่ด้านบนของเซลล์ต้นแบบของคุณและทำให้ดูเหมือนเป็น“ ส่วนหัว”
Fangming

@FangmingNing คุณช่วยอธิบายด้วยตัวอย่างเล็กน้อย ขอบคุณ
Pruthvi Hariharan

คุณไม่จำเป็นต้องมีขั้นตอนที่ 5 หากคุณใช้ UITableViewController แทน UIViewController
Deepak Thakur

0

คำตอบข้างต้นเป็นคำตอบที่ดีที่สุด แต่มีเหตุผลมากมายที่จะทำให้เกิดปัญหานี้ นี่เป็นอีกวิธีหนึ่งที่เป็นไปได้สำหรับทุกคนที่มีปัญหานี้:

ปัญหาของฉันคือฉันกำลังเชื่อมต่อกับคลาส ViewController ไม่ใช่มุมมองสตอรีบอร์ด ดังนั้นการอ้างอิงถึงเซลล์สตอรี่บอร์ดจึงไม่มีความหมายเนื่องจากไม่ได้ใช้สตอรี่บอร์ด

ฉันกำลังทำสิ่งนี้:

let viewControllerB = SubViewController()
viewControllerB.passedData = diseases[indexPath.row].name
navigationController?.pushViewController(viewControllerB, animated: true)

และฉันต้องทำสิ่งนี้:

let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "SubViewStoryboardController") as! SubViewController
nextViewController.passedData = diseases[indexPath.row].name
self.present(nextViewController, animated:true, completion:nil)

หวังว่านี่จะช่วยใครบางคนได้


-22

UITableViewControllerกำลังรับช่วงUIViewControllerที่มีUITableviewDataSourceและUITableviewDelegateแมปอยู่แล้ว

คุณอาจคลาสย่อยUITableViewControllerหรือใช้TableViewภายในViewControllerไฟล์. หลังจากนั้นคุณต้องใช้เมธอดที่จำเป็น ( cellForRowAtIndexPath and numberOfRowsInSection) ซึ่งประกาศไว้ในไฟล์UITableviewDataSource.

นอกจากนี้ในสตอรีบอร์ดคุณต้องสร้างต้นแบบเซลล์ที่มีรหัสเฉพาะ

มีเซลล์ประเภทพื้นฐานที่มี (ชื่อเรื่องคำบรรยายเป็นต้น) คุณสามารถใช้เซลล์เหล่านี้ได้เช่นกันหากคุณไม่ต้องการการกำหนดค่าพิเศษ

ดังนั้นสำหรับตัวเลือกใช่คุณต้องสร้างเซลล์ที่กำหนดเอง สร้างUITableViewCellตัวเลือกวันที่ถือคลาสแบบกำหนดเองที่จำเป็นและตรวจสอบให้แน่ใจว่าได้ใช้ delegate เพื่อส่งผลลัพธ์ที่ต้องการกลับไปยังViewControllerไฟล์.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.