Slim UITableview

1. Tản mạn

Cách đơn giản nhất để giảm bớt bug là viết code ít đi. Chân lý đó đã được đưa vào một định luật nổi tiếng, hồi phổ thông ai cũng từng kinh qua.

e = mc2

alt text

Dịch một cách chân phương là error = more code (càng nhiều code càng gây lỗi). Khoảng cách giữa coder và tester phụ thuộc vào việc có bao nhiêu bug sinh ra. Einstein khi đưa ra định luật đó, chắc không ngờ rằng nó có thể dịu dàng đúng (theo một cách mới) với cả ngành IT này. Thế nên viết ngắn đi mà vẫn dễ hiểu luôn luôn được những lười biếng coder coi là tôn chỉ.

Khi sử dụng tableview chúng ta luôn đi theo một format chung, thậm chí gõ đến thuộc lòng, không cần autocomplete.

self.listTbl.register( UINib( nibName: String(describing: GGArtistryCell.self), bundle: nil), forCellReuseIdentifier: "cell")

Cả những khi dequeue nữa

let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

Những đoạn code này hơi dài, vậy nên chúng ta, những lười biếng coder, nên làm ngắn nó đi tí. Mình sẽ sử dụng protocolgenerics để việc đăng kí và dequeue cell ngắn gọn hơn.

2. Make up

Làm việc với objc, mình hay tạo baseCell có 2 hàm getNibgetNibName (cho identifier) để việc đăng kí cell trở nên ngắn gọn hơn. Tuy nhiên ở swift, mình sẽ sử dụng protocol.

/**
    cell protocol for uicollectionview, uitableview
 */
protocol GGBaseCellProtocol {
    static func getNibName() -> String // return nibname of cell
    static func getNib() -> UINib // return nib of cell
}


/**
    default implement for cell
 */
extension GGBaseCellProtocol where Self : UIView {
    /// collectionView get nibname
    static func getNibName() -> String {
        return String(describing: self)
    }
    
    /// collectionView get nib
    static func getNib() -> UINib {
        return UINib.init(nibName: self.getNibName(), bundle: nil)
    }
}

Tạo extension cho protocol để ta không phải khai báo đi, khai báo lại 2 hàm getNibgetNibName ở mỗi class implement lại protocol này. Khi đó ta chỉ cần cho custom cell của mình kế thừa lại protocol. Khá là linh động. Code lúc đó sẽ ngắn đi chút ít nhưng nhìn clear hơn.

Ví dụ như thế này

self.listTbl.register(GGArtistryCell.getNib(), 
	forCellReuseIdentifier: GGArtistryCell.getNibName())

Khá là đẹp rồi phải không? tuy nhiên ta có thể code ngắn hơn nữa bằng cách sử dụng generics.

extension UITableView {
    func on_register< T : GGBaseCellProtocol>(type: T.Type)  {
        self.register(T.getNib(), forCellReuseIdentifier: T.getNibName())
    }

    func on_dequeue< T : GGBaseCellProtocol>(idxPath : IndexPath) -> T {
        guard let cell = self.dequeueReusableCell(withIdentifier: T.getNibName(), for: idxPath) as? T else {
            fatalError("couldnt dequeue cell with identifier \(T.getNibName())")
        }

        return cell
    }
}

Để cho gọn, mình tạo extension cho UITableView, với 2 hàm on_registeron_dequeue làm 2 việc mà ai cũng biết là việc gì rồi.

Khi đó bước đăng kí cell sẽ ngắn đi như sau:

self.listTbl.on_register(type: GGArtistryCell.self)

So với trước thì ngắn gọn đi khá nhiều, coder không phải viết dài dòng nữa.

Tiếp đến là dequeue cũng ngắn không kém phần

Thay vì:

if let cell = self.listTbl.dequeueReusableCell(withIdentifier: GGArtistryCell.getNibName(), for: indexPath) as? GGArtistryCell {
	// your code
}

Ta chỉ cần

let cell : GGArtistryCell = self.listTbl.on_dequeue(idxPath: indexPath)

Bây giờ mình đã có thể lười đi tí :smile:

Ta có thể áp dụng phương pháp này cho cả collectionView

3. Kết

Lời cuối sẽ là một siêu tip để code ngắn gọn

MVC = Most Viable Cocoapod.

Bài viết trên blog

1 Like

Klq nhưng E=mc^2 là của Einstein :cow:

1 Like

(y) ok để sửa lại :))

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?