V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
banxi1988
V2EX  ›  iDev

使用 Swift 实现 简单的 UITableViewDataSource 泛型支持

  •  
  •   banxi1988 ·
    banxi1988 · 2015-06-05 23:40:44 +08:00 · 3975 次点击
    这是一个创建于 3462 天前的主题,其中的信息可能已经有所发展或是发生改变。

    UITableViewDataSource的简单泛型实现

    在日常的 iOS 开发中, UITableView是用得特别多的.

    也许使用的最多的是 UITableViewController 了,重写需要的几个方法就OK了.
    从 iOS 2.0 到 iOS 8 UITableView 本身也在不断的进化. 后来出现了 UICollectionView
    当我在 UITableViewController 重复做着类似的事情时,
    我遇到了 objc.io 它第一期中文章: Lighter View Controllers
    他让我认识到,我以前对 Apple 提供的这一套东西,接受却缺少反思(不过在我看这文章之前,我还没正式做 iOS 开发)
    但是,虽然篇文章,写我觉得写 UITableView的代码写得很漂亮的, 但是重复的代码还在不断的写,
    于是我想起了 Android 平台的 ArrayAdapter, 我知道很多人都是继承 BaseAdapter的, 但是继承ArrayAdapter却会有更多的好处.
    比如有泛型一些 Stub代码就不用了.
    那么在 iOS 中我要怎么做呢? 幸好 Swift 为我们也带来的泛型

    UITableViewDataSource 泛型 的使用

    先从一个使用实例说起, 例如我需要一个文章列表的 UITableViewDataSource
    那么我只需要写如下的代码即可:

    class ArticleItemTableViewDataSource<T:ArticleItem>:GenericDataSource<T>{
    
        init(articleItems:[T]){
            super.init(items:articleItems)
        }
    
        override func configureTableViewCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
            let itemCell = cell as! ArticleItemTableViewCell
            let item = itemAtIndexPath(indexPath)
            itemCell.bind(item)
        }
    
        override class var reuseIdentifier:String{
            return ArticleItemTableViewCell.reuseIdentifier
        }
    
    }
    

    然后就可以用了:

    tableView.registerNib(ArticleItemTableViewCell.nib, forCellReuseIdentifier: ArticleItemTableViewCell.reuseIdentifier)
            dataSource = ArticleItemTableViewDataSource(articleItems: [])
            tableView.dataSource = dataSource
    

    UITableViewDataSource 泛型的实现

    实现泛型的基类GenericDataSource 却是有一点曲折.
    因为 Swift 为了与 Objective-C的交互性,做了一些限制 不能直接在 UITableView的方法中使用泛型类型的参数 .

    所以必须再加一层包装, 这也就是我所实现的 GenericDataSource

    class GenericDataSource<T>:SimpleDataSourceBridge{
        private var items = [T]()
    
        init(items:[T]){
            self.items = items
        }
    
        func updateItems(items:[T]){
            self.items = items
        }
    
        func itemAtIndexPath(indexPath:NSIndexPath) -> T{
            return items[indexPath.row]
        }
    
        override func numberOfRows() -> Int {
            return self.items.count
        }
    
    }
    

    而让 SimpleDataSourceBridge 不直接调用泛型的方法,而是调用实现的另一个方法:
    即如此:

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

    注意上面方法的修饰 final 这是为了保证子类不再重写些方法了. 而应该去重写numberOfRows()方法.
    而这方法在泛型类中已经实现

    到此一个支持泛型的 UITableViewDataSource 基类这是这样样子了, 我使用起来觉得很开心
    两个类,全部源代码在这里:
    https://gist.github.com/banxi1988/cbd5953dea41d20c833e

    值得注意的地方

    1. 以我一贯的性格, 我的目的是让他减少我 80% 场景的代码编写, 所以,如果需要有变,需要自行修改代码
    2. 泛型的子类也得是泛型,所以注意我使用的子类的
      class ArticleItemTableViewDataSource<T:ArticleItem>:GenericDataSource<T>

    3. 可以看到代码,基于对于弱化的 UICollectionView 也提供了支持. 简单的情况也可使用.

    最后: 希望对大家有帮助.

    5 条回复    2015-06-07 17:50:29 +08:00
    Elethom
        1
    Elethom  
       2015-06-06 01:21:21 +08:00
    類似 view model?
    wezzard
        2
    wezzard  
       2015-06-06 01:30:03 +08:00 via iPhone
    如果樓主曾經接觸過 OS X 開發,應該會知道 NSController 及其子類。蘋果沒遷移到 iOS 上而已。
    banxi1988
        3
    banxi1988  
    OP
       2015-06-06 08:04:13 +08:00
    @wezzard 多谢指点. 我还没有接触 OS X 开发. 等我对 NSController 多些了解,也许就能明显你的想法了.
    ios
        4
    ios  
       2015-06-06 10:04:10 +08:00
    不错 之前使用Xamarin的时候我也用C# 泛型写这个 DataSource
    很方便使用
    mailworks
        5
    mailworks  
       2015-06-07 17:50:29 +08:00
    能不能放个Demo呢?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5547 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 08:00 · PVG 16:00 · LAX 00:00 · JFK 03:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.