源码

首页 » 归档 » 源码 » Swift标配开源库:Reusable-让你放肆的dequeueReusableCell-ios学习从入门到精通尽在姬长信

Swift标配开源库:Reusable-让你放肆的dequeueReusableCell-ios学习从入门到精通尽在姬长信

分享最热门的ios资讯

225849-5bcdce638d7e4038.png

投稿文章,作者:@没故事的卓同学

Reusable

Reusable是一个在swift下使用的开源库。倒霉用protocol extension结合泛型提供了一个优雅的方案来dequeueReusableCell。

使用

凭据类型获取cell

让你的cell声明Reusable或NibReusable协议

//如果cell界说在xib中,声明NibReusable
class MyCustomCell: UITableViewCell, NibReusable { }
//如果cell是基于纯代码的,声明Reusable
class MyCustomCell: UITableViewCell, Reusable { }

接着在tableview或者collectionView中register

tableView.registerReusableCell(MyCustomCell)

粗暴的直接获取cell就可以啦:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  let cell: MyCustomCell = tableView.dequeueReusableCell(indexPath: indexPath)
  … // configure the cell, which is already of the expected MyCustomCell type
  return cell
}

是的。你没有看错,这样就能获取到这个类型的reuse cell,不需要传入reuseIdentifiers,不需要UITableViewCell类型强转。

凭据类型获取xib中的UIView工具

UIView工具声明NibLoadable协议。

倒霉用MyCustomView.loadFromNib()就可以从“MyCustomView.xib”中实例化返回MyCustomView的实例工具

凭据类型获取Storyboards中的UIViewController工具

UIViewController工具声明StoryboardBased或者StoryboardSceneBased协议。

倒霉用YourCustomViewController.instantiate()就可以从Storyboard中实例化返回实例工具

实现

核心的思路其实很简单,就是倒霉用自己的类名做为重用标识符。

我们就来界说一个协议,声明一个静态变量reuseIdentifier,并实现extension,默认标识符返回当前类名:

protocol Reusable: class {
  static var reuseIdentifier: String { get }
}
extension Reusable {
  static var reuseIdentifier: String {
    // I like to use the class's name as an identifier
    // so this makes a decent default value.
    return String(Self)
  }
}

接着我们给tableview的写一个自界说获取reuse cell的扩展要领:

func dequeueReusableCell(indexPath indexPath: NSIndexPath) -> T {
  return self.dequeueReusableCellWithIdentifier(T.reuseIdentifier, forIndexPath: indexPath) as! T
}

注意这个泛型参数,这个泛型是凭据返回值的类型来确定的。所以返回的cell必须实现Reusable协议。我们将这类型里的那个静态变量T.reuseIdentifier作为Identifier。

我们当然还要同时革新register要领。

public extension UITableView {
  final func registerReusableCell(cellType: T.Type) {
    self.registerClass(cellType.self, forCellReuseIdentifier: cellType.reuseIdentifier)
  }
}

这个时候我们忽然意识到,还有registerNib没有解决。

思路也是相似的,给协议再增加一个返回nib工具的静态变量呗。就像这样:

protocol Reusable: class {
 static var reuseIdentifier: String { get }
 static var nib: UINib? { get }
}

实现是这样:

static var nib: UINib {
    return UINib(nibName: String(self), bundle: NSBundle(forClass: self))
  }

但是这里再往深一点想,其实载入nib和reuseIdentifier是两件事,因为我们有时也会从xib获取其他UIView的工具。protocol也提供了组合的特性。所以我们可以把获取nib单独拆出来。

public protocol NibLoadable: class {
  /// The nib file to use to load a new instance of the View designed in a XIB
  static var nib: UINib { get }
}
public protocol NibReusable: Reusable, NibLoadable {}

这样最后一块拼图就有了:

final func registerReusableCell(cellType: T.Type) {
    self.registerNib(cellType.nib, forCellReuseIdentifier: cellType.reuseIdentifier)
  }

接着再顺手给UIView写一个凭据类型获取实例的扩展要领:

public extension NibLoadable where Self: UIView {
  static func loadFromNib() -> Self {
    guard let view = nib.instantiateWithOwner(nil, options: nil).first as? Self else {
      fatalError("The nib \(nib) expected its root view to be of type \(self)")
    }
    return view
  }
}

相关链接:Using Generics to improve TableView cells

用意志战胜身体的惰性!

(0)

本文由 姬長信 创作,文章地址:https://blog.isoyu.com/archives/827.html
采用知识共享署名4.0 国际许可协议进行许可。除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为:7 月 25, 2016 at 08:00 下午

关键词:

热评文章

发表回复

[必填]

我是人?

提交后请等待三秒以免造成未提交成功和重复