sag*_*its 24 generics storyboard ios swift swift2
我试图为我的应用程序创建一个GenericListController.
我有一个ProductListController,它扩展了这个扩展UIViewController的通用控制器.我已将ProductListController连接到故事板并制作了2个插座,但我总是收到此错误:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIViewController 0x7c158ca0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key searchBar.'
Run Code Online (Sandbox Code Playgroud)
我收到这个错误的所有我的网点,如果我从GenericListController删除通用T它的工作原理.我猜一个故事板不能用泛型加载超级.我怎样才能使它工作?
我的代码:
class GenericListController<T> : UIViewController {
var list : [T] = [T]()
var filteredlist : [T] = [T]()
func getData(tableView : UITableView) {
.....
}
func setData(list : [T], tableView : UITableView) {
.....
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
class ProductListController : GenericListController<ProductModel> {
@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
getData(tableView)
}
}
Run Code Online (Sandbox Code Playgroud)
- 编辑 -
我发现如果我扩展一个泛型类并尝试将类添加到一个故事板xcode不会自动完成类名(可能因为它无法检测到类)
R M*_*nke 15
这就解释了为什么不可能:在通用接口构建器中使用泛型类作为自定义视图
Interface Builder通过ObjC运行时"与"代码"对话".因此,IB只能访问代码中可在ObjC运行时中表示的功能.ObjC不做泛型
这个暗示可能的解决方法:obj-c中的泛型 也许你可以在obj-c中创建一个通用的ViewController然后IB会接受它吗?
你考虑过使用协议吗?这不会扰乱故事板.更改了一些代码以使其易于测试.这样做的缺点是您不能在协议中存储属性.所以你仍然需要复制粘贴那些.好处是它有效.
protocol GenericListProtocol {
typealias T
var list : [T] { get set }
var filteredlist : [T] { get set }
func setData(list : [T])
}
extension GenericListProtocol {
func setData(list: [T]) {
list.forEach { item in print(item) }
}
}
class ProductModel {
var productID : Int = 0
init(id:Int) {
productID = id
}
}
class ProductListController: UIViewController, GenericListProtocol {
var list : [ProductModel] = [ProductModel(id: 1),ProductModel(id: 2),ProductModel(id: 3),ProductModel(id: 4)]
var filteredlist : [ProductModel] = []
override func viewDidLoad() {
super.viewDidLoad()
setData(list)
}
}
Run Code Online (Sandbox Code Playgroud)
更新:允许对泛型类的属性进行一些访问.将其更改为基本类,以便在Playground中轻松测试.UIViewController的东西在上面的代码中.
class ProductModel {
var productID : Int = 0
init(id:Int) {
productID = id
}
}
class ProductA : ProductModel {
var aSpecificStuff : Float = 0
}
class ProductB : ProductModel {
var bSpecificStuff : String = ""
}
protocol GenericListProtocol {
typealias T = ProductModel
var list : [T] { get set }
var filteredlist : [T] { get set }
func setData(list : [T])
}
extension GenericListProtocol {
func setData(list: [T]) {
list.forEach { item in
guard let productItem = item as? ProductModel else {
return
}
print(productItem.productID)
}
}
}
class ProductListController: GenericListProtocol {
var list : [ProductA] = [ProductA(id: 1),ProductA(id: 2),ProductA(id: 3),ProductA(id: 4)]
var filteredlist : [ProductA] = []
init() {
setData(list)
}
}
var test = ProductListController()
Run Code Online (Sandbox Code Playgroud)
正如@ r-menke所述:
Interface Builder通过ObjC运行时"与"代码"对话".因此,IB只能访问代码中可在ObjC运行时中表示的功能.ObjC不做泛型
这是真的,
然而,根据我的经验,我们可以解决以下问题(YMMV).
我们可以在这里做一个人为的例子,看看它是如何失败的:
class C<T> {}
class D: C<String> {}
print(NSClassFromString("main.D"))
Run Code Online (Sandbox Code Playgroud)
在这里运行示例:
http://swiftstub.com/878703680
你可以看到它打印出来 nil
现在让我们稍微调整一遍,然后再试一次:
http://swiftstub.com/346544378
class C<T> {}
class D: C<String> {}
print(NSClassFromString("main.D"))
let _ = D()
print(NSClassFromString("main.D"))
Run Code Online (Sandbox Code Playgroud)
我们得到这个:
nil
Optional(main.D)
嘿-O!它是在第一次初始化之后发现的.
让我们将它应用于故事板.我现在在一个应用程序中这样做(正确或错误)
// do the initial throw away load
let _ = CanvasController(nibName: "", bundle: nil)
// Now lets load the storyboard
let sb = NSStoryboard(name: "Canvas", bundle: nil)
let canvas = sb.instantiateInitialController() as! CanvasController
myView.addSubView(canvas.view)
Run Code Online (Sandbox Code Playgroud)
像你期望的那样工作.在我的情况下,我CanvasController的声明如下:
class CanvasController: MyNSViewController<SomeGeneric1, SomeGeneric2>
Run Code Online (Sandbox Code Playgroud)
现在,我在iOS上遇到了一些问题,使用这种技术和一个通用的UITableView子类.我没有在iOS 9下试过它,所以YMMV.但我目前正在10.11下为我正在开发的应用程序执行此操作,并且没有遇到任何重大问题.这并不是说我将来不会遇到任何问题,或者说这甚至是适当的,我不能声称知道这一点的全部后果.我只能说,就目前而言,它似乎解决了这个问题.
我在8月4日在这个背面提交了一个radr:#22133133我没有在开放的RADR中看到它,但在bugreport.apple.com下它至少列在我的账户下,无论那个价值多少.