ใช้เมธอด didSelectRowAtIndexPath หรือเตรียมForSegueสำหรับ UITableView?


101

ฉันใช้สตอรี่บอร์ดและมี UITableView ฉันมีการตั้งค่าต่อที่ดึงจากตารางของฉันไปยัง VC รายละเอียด แต่ฉันควรใช้วิธีใดในการจัดการนี้ ฉันจะต้องส่งวัตถุสองสามชิ้นไปยังมุมมองรายละเอียด แต่ฉันใช้didSelectRowAtIndexหรือ-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender?

คำตอบ:


199

หากคุณใช้prepareForSegue:sender:คุณจะไม่มีการเปลี่ยนแปลงมากนักหากคุณตัดสินใจที่จะทริกเกอร์การทำตามในภายหลังจากการควบคุมบางอย่างนอกมุมมองตาราง

prepareForSegue:sender:ข้อความจะถูกส่งไปยังตัวควบคุมมุมมองปัจจุบันดังนั้นผมขอแนะนำบางอย่างเช่นนี้

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Assume self.view is the table view
    NSIndexPath *path = [self.tableView indexPathForSelectedRow];
    DetailObject *detail = [self detailForIndexPath:path];
    [segue.destinationViewController setDetail:detail];
}

ใน Swift:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    let path = self.tableView.indexPathForSelectedRow()!
    segue.destinationViewController.detail = self.detailForIndexPath(path)
}

1
โอเคคุณช่วยยกตัวอย่างวิธีการใช้งานโดยส่งผ่านวัตถุตาม indexPath ได้ไหม
จอน

4
ไม่ควรself.viewอยู่แค่senderนี้? ฉันไม่สามารถ[self.view indexPathForSelectedRow]ไปทำงานได้ฉันต้องทำ[sender indexPathForSelectedRow];
ladookie

คุณจะทำสิ่งนี้ใน Swift ได้อย่างไร?
ผู้ใช้

@robmayoff ขอบคุณสำหรับการอัปเดตสิ่งนี้สำหรับ Swift ฉันได้ทำการแก้ไขเล็กน้อยเพื่อแสดงการเปลี่ยนแปลงของภาษาล่าสุด หวังว่านี่จะช่วยคนอื่นได้บ้าง
Zack Shapiro

เป็นเรื่องแปลกที่tableView.indexPathForSelectedRow()มีค่าที่ถูกต้องเมื่อprepareFroSegue...ถูกเรียก: tableView(_:didSelectrowAtIndexPath:)จะไม่ถูกเรียกจนกว่าจะภายหลัง
Nicolas Miari

5

ฉันทำสิ่งนี้และได้ผล

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    NSLog(@"Row Selected = %i",indexPath.row);

    [self performSegueWithIdentifier:@"testID" sender:self.view];    
}

11
นั่นไม่สมเหตุสมผล คุณควรใช้ segue หรือ table view delegate เพียงแค่สร้างการต่อจากเซลล์และจะดำเนินการโดยอัตโนมัติเช่นเดียวกับที่คุณทำโดยไม่ต้องเขียนโค้ด
Yariv Nissim

3
คุณจะกำหนด segue ให้กับเซลล์โดยไม่ใช้ didSelectRow ได้อย่างไร
หมอกฤษณ์

3

เมื่อผู้ส่งเป็น UITableViewCell คุณอาจขอให้ UITableView สอบถาม indexPath ของเซลล์

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if let cell = sender as? UITableViewCell {
            let indexPath = self.tableView.indexPathForCell(cell)!
            assert(segue.destinationViewController.isKindOfClass(DetailViewController))
            let detailViewController = segue.destinationViewController as! DetailViewController
            detailViewController.item = self.items[indexPath.row] // like this
        }
    }

1

หากคุณสมบัติ tableView ของคุณอยู่ในคลาสอื่นและคุณมีเพียงส่วนเดียวคุณสามารถใช้tagคุณสมบัติเพื่อเก็บแถวของเซลล์เช่น:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];

     cell.tag = indexPath.row;

     return cell;
}

จากนั้นคุณสามารถเข้าถึงได้เนื่องจากsenderเป็นเซลล์เดียวกันกับค่าแถวในแท็ก:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    MyDestinationViewController *destinationViewController = segue.destinationViewController;
    destinationViewController.myProperty = [tableViewElementsArray objectAtIndex:[sender tag]]; // sender will be your cell 
}

1

self.tableView.indexPathForSelectedRowส่งคืนเซลล์ที่เลือก แต่ไม่ได้เลือกเซลล์ผู้ส่งเช่นไม่ได้เลือกเซลล์ผู้ส่ง (การดำเนินการเสริม) หรือในกรณีการเลือกหลาย ๆ วิธีที่ดีที่สุดคือการรับ indexPath สำหรับผู้ส่ง segue:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    __auto_type itemViewController = (id<ItemViewController>)segue.destinationViewController;
    itemViewController.senderIndexPath = [self.tableView indexPathForCell:sender];
}

ใน Swift:

protocol ItemViewController {
    var senderIndexPath : IndexPath? { get set }
    var selectedIndexPaths : [IndexPath]? { get set }
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if  let cell = sender as? UITableViewCell,
        var itemViewController = segue.destination as? ItemViewController {
        itemViewController.senderIndexPath = tableView.indexPath(for: cell)
        itemViewController.selectedIndexPaths = tableView.indexPathsForSelectedRows
    }
}

0

หากคุณใช้prepareForSegue:คุณสามารถตรวจสอบได้ว่าใครเป็นผู้ส่งและเรียกใช้รหัสอื่น

ตัวอย่างเช่นในรวดเร็ว

override func prepareForSegue(segue: UiStoryboardSegue, sender: AnyObject?)
{
   var senderIsTableviewCell:Bool! = sender?.isKindOfClass(UITableViewCell)

   if senderIsTableviewCell
   {
       //do something
   }
}

2
เพียงแค่ทำ: ถ้าให้ tableViewCell = ผู้ส่งเป็น? UITableViewCell {// ทำอะไรบางอย่าง} หากไม่สามารถส่งผู้ส่งไปยัง UITableViewCell "do something" จะไม่ดำเนินการ
mbeaty
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.