[ios] dequeueReusableCellWithIdentifier와 dequeueReusableCellWithIdentifier를 사용하는 경우 : forIndexPath

dequeueReusableCellWithIdentifier에 대한 두 가지 과부하가 있으며 한 대를 사용해야하는 시점을 결정하려고합니까?

forIndexPath 함수와 관련된 Apple 문서에는 “이 메소드는 인덱스 경로를 사용하여 테이블보기에서 셀의 위치에 따라 추가 구성을 수행합니다.”

그래도 어떻게 해석 해야할지 모르겠습니다.



답변

가장 중요한 차이점은 forIndexPath:식별자에 클래스 또는 펜촉을 등록하지 않은 경우 버전이 주장하는 것입니다. 이 경우 이전 forIndexPath:버전이 아닌 버전이 반환 nil됩니다.

registerClass:forCellReuseIdentifier:테이블 뷰로 보내 식별자에 대한 클래스를 등록합니다 . registerNib:forCellReuseIdentifier:테이블 뷰로 보내 식별자에 대한 펜촉을 등록합니다 .

스토리 보드에서 테이블보기 및 셀 프로토 타입을 작성하는 경우 스토리 보드 로더는 스토리 보드에서 정의한 셀 프로토 타입을 등록합니다.

세션 200-WWDC 2012의 Cocoa Touch의 새로운 기능은forIndexPath: 약 8m30에서 시작 하는 (새로운) 버전에 대해 설명합니다 . “언제나 초기화 된 셀을 얻게 될 것입니다”라고 말합니다 (클래스 나 펜촉을 등록하지 않으면 충돌이 발생하지는 않습니다).

비디오는 또한 “해당 인덱스 경로에 적합한 크기가 될 것”이라고 말합니다. 아마도 이것은 테이블 뷰의 자체 너비를보고 델리게이트의 tableView:heightForRowAtIndexPath:메소드를 정의 하여 셀을 반환하기 전에 셀의 크기를 설정한다는 것을 의미합니다 (정의 된 경우). 이것이 인덱스 경로가 필요한 이유입니다.


답변

dequeueReusableCellWithIdentifier:forIndexPath:것입니다 항상 셀을 반환합니다. 기존 셀을 재사용하거나 새 셀을 작성하고 셀이 없으면 리턴합니다.

반면, 전통 dequeueReusableCellWithIdentifier:은 셀이 존재하는 경우, 즉 재사용 할 수있는 셀이있는 경우 셀을 반환하고, 그렇지 않으면 nil을 반환합니다. 따라서 nil가치 를 확인하기위한 조건을 작성해야합니다 .

iOS 6 이상에서만 사용할 수 dequeueReusableCellWithIdentifier:있으므로 iOS 5 이하 버전을 지원하려는 경우 사용에 대한 질문에 답변dequeueReusableCellWithIdentifier:forIndexPath

참조 : https://developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.html#//apple_ref/occ/instm/UITableView/dequeueReusableCellWithIdentifier:forIndexPath :


답변

Apple이 왜 새로운 메소드 dequeueReusableCellWithIdentifier : forIndexPath :를 생성했는지 이해하지 못했습니다. 그들에 대한 문서는 완전하지 않으며 다소 오도합니다. 두 가지 방법을 구별 할 수있는 유일한 차이점은 이전 메소드가 식별자가 전달 된 셀을 찾지 못하면 nil을 반환 할 수 있다는 것입니다. 새로운 메소드는 반환 할 수없는 경우 충돌합니다. 세포. 식별자를 올바르게 설정하고 스토리 보드에서 셀을 만들면 두 방법 모두 셀을 반환합니다. 클래스 또는 xib를 등록하고 셀을 코드 또는 xib 파일로 만들면 두 메소드 모두 셀을 반환합니다.


답변

요약하자면 :

dequeueReusableCell(withIdentifier, for)프로토 타입 셀에서만 작동합니다. 프로토 타입 셀이 없을 때 사용하려고하면 앱이 중단됩니다.

Hollemans M. 2016, 2 장 점검표, IOS Apprentice (5 판). pp : 156.


답변

동적으로 생성 된 콘텐츠를 사용하는 경우 두 가지를 모두 사용하는 것이 좋습니다. 그렇지 않으면 앱이 예기치 않게 중단 될 수 있습니다. 선택적 재사용 가능 셀을 검색하기 위해 고유 한 기능을 구현할 수 있습니다. 그렇다면 nil보이지 않는 빈 셀을 반환해야합니다.

스위프트 3

// Extensions to UITableView
extension UITableView
{
    // returns nil, if identifier does not exist. 
    // Otherwise it returns a configured cell for the given index path
    open func tryDequeueReusableCell (
        withIdentifier identifier: String, 
        for indexPath: IndexPath) -> UITableViewCell?
    {
        let cell = self.dequeueReusableCell(withIdentifier: identifier)
        if cell != nil {
            return self.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
        }  
        return nil
    }
}

그리고 빈 셀을 반환하는 확장 프로그램 :

// Extension to UITableViewCell
extension UITableViewCell
{
    // Generates an empty table cell that is not visible
    class func empty() -> UITableViewCell
    {
        let emptyCell = UITableViewCell(frame:CGRect(x:0, y:0, width:0, height:0))
        emptyCell.backgroundColor = UIColor.clear
        return emptyCell
    }
}

그것을 사용하는 방법의 완전한 예 :

import Foundation
import UIKit

// A protocol is used to identify if we can configure
// a cell with CellData
protocol ConfigureAbleWithCellData
{
    func configure(_ data: CellData)
}

class MyCustomTableViewCell :
    UITableViewCell,
    ConfigureAbleWithCellData
{
    @IBOutlet weak var title:UILabel! = nil
    func configure(_ data: CellData)
    {
        self.title.text = data.title
    }
}

// This actually holds the data for one cell
struct CellData
{
    var title:String = ""
    var reusableId:String = ""
}

class CosmoConverterUnitTableViewController:
    UIViewController,
    UITableViewDelegate,
    UITableViewDataSource
{
    // Storage
    var data = Array<Array<CellData>>()

    func loadData()
    {
        var section1:[CellData] = []
        var section2:[CellData] = []

        section1.append(CellData(title:"Foo", reusableId:"cellType1"))
        section2.append(CellData(title:"Bar", reusableId:"cellType2"))

        data.append(section1)
        data.append(section2)
    }

    func tableView(_ tableView: UITableView,
                   numberOfRowsInSection section: Int) -> Int
    {
        return data[section].count
    }

    public func numberOfSections(in tableView: UITableView) -> Int
    {
        return data.count
    }

    func tableView(
        _ tableView: UITableView,
        cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        guard
            indexPath.row < data[indexPath.section].count
            else
        {
            fatalError("this can't be")
        }

        let cellData = data[indexPath.section][indexPath.row]

        if let cell = tableView.tryDequeueReusableCell(
            withIdentifier: cellData.reusableId,
            for: indexPath)
        {
            if let configurableCell = cell as? ConfigureAbleWithCellData
            {
                configurableCell.configure(cellData)
            }
            else
            {
                // cell is not of type ConfigureAbleWithCellData
                // so we cant configure it.
            }
            return cell
        }
        // id does not exist
        return UITableViewCell.empty()
    }
}


답변