@IBInspectable为类设置Typealias

时间:2017-05-11 13:07:48

标签: ios swift3 realm type-alias ibinspectable

我正在尝试使用领域UITableViewController作为模型构建通用Results<Object>

这些是我的简化课程:

领域对象:

import RealmSwift

class Test: Object {

  dynamic var name = ""

}

TableViewCell:

import UIKit
import RealmSwift

class RealmCell: UITableViewCell {
  typealias Entity = Test // from above

  var object: Entity? {
    didSet {
      if let object = object {
        textLabel?.text = object.name
      }
    }
  }

}

TableViewController:

import UIKit
import RealmSwift

class RealmTableViewController: UITableViewController {

  typealias TableCell = RealmCell // From example above            
  var objects = try! Realm().objects(TableCell.Entity.self) {
    didSet { tableView.reloadData() }
  }

  // MARK: - UITableViewDataSource

  override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
  }

  override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return objects.count
  }

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

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

      cell.object = objects[indexPath.row]

      return cell
  }
}

我无法找到制作TableCell类型@IBInspectable的方法。我一直在尝试NSClassFromString(_:)但没有成功。

希望有人可以提供帮助。

1 个答案:

答案 0 :(得分:3)

如果我理解正确,你基本上希望能够在Interface Builder中指定实体名称,是吗?即您希望能够从检查器中基本选择自定义类吗?

如果是这样,那么遗憾的是不可能。 @IBInspectable只能用于特定类型,如here所述:

  

您可以将IBInspectable属性添加到类声明,类扩展或类型类别中的任何属性:boolean,integer或float point number,string,localized string,rectangle,point,size,color,range和nil

但是,您可以将字符串属性指定为IBInspectable(具有有意义的默认值),并在初始化程序中从中扣除该类。这将留下错误的可能性,即错字,但它仍然可以工作。

另见this答案。

评论后

修改: 在这种情况下我不可能害怕(至少据我所知,可能存在一些我不知道的深层次的hackery,但那可能是丑陋地狱)。 问题是IB中指定的内容只能在运行时进行评估,但是typealias是在编译时定义的。

我认为你基本上想要的只是一个协议,用于每个单元类应具有的功能(以及通用视图控制器所依赖的功能)。你甚至不需要一个类型,因为协议本身就是一种类型。

然后可以根据IBInspectable ed字符串选择具体的单元格类,协议甚至可以为此定义一个方法。

根据您的方案的详细信息,您甚至可以为所有单元格编写一个共同的超类。已经采用(部分)协议的协议(在这种情况下你甚至可以省略协议,但我建议使用一个协议以便于阅读)。

这显然假设您具有为通用单元格定义的视图控制器所需的所有功能,但这在任何情况下都是您遇到的问题(即使您可以使用在运行时定义的类型)。

在我查看示例代码后

第二次编辑

好的,我再次看了一遍,希望现在可以更好地解释一下。不幸的是,我无法直接添加到您的存储库,因为它没有编译(我错过了Realm框架/ pod,即使我添加了我可能也没有赢得任何因为我没有&#39;我知道你究竟用它做了什么。)

正如评论中所述,我说你不需要任何进一步的IBInspectable财产来设置课程。这应该在您的故事板中发生,即您应该将给定原型单元格的类值设置为您拥有的具体单元格类之一。但是,您的通用RealmTableViewController并不需要知道该类。如果我理解正确的话,您似乎想要了解它,可能要根据其具体特征正确准备单元格。不要这样做(我会在viewDidLoad过一会儿到达你想做的事情)。相反,定义所有单元格采用的协议以及RealmTableViewController知道的协议。在tableView(_:cellForRowAt:)方法中,当您将单元格出列时,在as! ...部分中使用此协议。协议应定义每个具体类应实现的准备方法,然后由RealmTableViewController 调用此方法。

通过这种方式,您的表视图控制器保持通用,它并不真正了解它所显示的单元格,这就是预期的方式。

现在问题你(我认为)面对:你想让控制器知道它使用哪种原型单元,这样它也可以准备特定的东西(你也可以将其外包到协议中,例)。这是有问题的,因为您基本上试图构建表视图控制器的核心方面:它能够同时处理不同类型的单元 。我从你的其他代码,viewDidLoadobjects属性中得出结论,这最终似乎也依赖于单元格的类。这与表架构本身的设计发生了冲突,它不仅仅是一个语法问题。但是,有一个解决方案:另一个协议,加上一个&#34;伴侣&#34;类到具体的单元类。

对于您拥有的每个单元格类,定义处理视图控制器需要执行的Realm内容的相应类。也许对于某些单元格,您具有相同的对象,然后相应地编写它们(新类应该具有定义它对应于哪个单元格的属性)。 定义一个所有人都采用的协议,并且至少有两种方法(可能使用更好的名称,这里很晚......):doControllerStuffgetCellIdentifier。< / strong>

然后您的RealmTableViewController终于 获得IBInspectable。如果设置了,则控制器将伴随对象实例化为单元格(使用哪个具体类显然取决于IBInspectable的值)。如果同一伴侣处理多个单元,则IBInspectable还必须定义将使用哪个单元,即必须正确配置伴随。您可以使用某种字符串约定,甚至可以编写一个工厂类来隐藏视图控制器中的具体类,然后只返回一个键入协议的正确对象。

无论如何,无论你在viewDidLoad基于该类到目前为止做什么,都要将其更改为doControllerStuff方法。你可能甚至有一些超级和子类,如果这在细胞/伴侣中很常见,那并不重要。 最后,在你的`tableView(_:cellForRowAt :)方法中,你不能直接使用标识符,而是向同伴对象询问标识符。

虽然有一点需要注意:您必须明确确保正确设置单元标识符的接口构建器值,即它与您在视图控制器实例中设置的IBInspectable相匹配。你可以写一个关于这个的问题,但是使用一个默认的单元格,只需抛出异常。

这已经很长了,我希望尽管如此也是可以理解的。我没有时间制作这个或类似的漂亮图形,所以如果你仍然有问题我建议我们这个聊天。 :)只要ping我,我们会(虽然我明天开始有点闲暇)。