gpt4 book ai didi

cocoa - 自定义 View Controller 类未在 Storyboard的类菜单中列出

转载 作者:行者123 更新时间:2023-12-03 16:40:19 25 4
gpt4 key购买 nike

我的应用程序具有用于创建自定义 View Controller 的类层次结构。

第一个类是AppViewController。它扩展了 NSViewController 并包含所有 View Controller 通用的方法,例如显示警报、从数据库检索数据等等。它没有定义任何变量。

class AppViewController: NSViewController
{
...
}

下一个类是 ListViewController,它是我所有“列表” View 所共有的。这些 View 包含一个 NSTableView,其中包含关联数据库表中所有记录的列表。它扩展了 AppViewController 并符合常用协议(protocol)。

请注意,此类是通用的,因此它可以正确处理不同的 View 和数据模型。

class ListViewController<Model: RestModel>: AppViewController,
NSWindowDelegate,
NSTableViewDataSource,
NSTableViewDelegate
{
...
}

ListViewController 定义了许多变量,包括 NSTableView 的 IBOutlet。该 socket 未连接到 Storyboard中的任何内容。计划是在运行时设置它。

ListViewController还定义了各种函数,包括viewDidLoad()、viewWillAppear()、许多应用程序特定的函数等等。

最后一个类特定于数据库模型和 View ,在本例中为“客户” View 。它扩展了 ListViewController。

class Clv: ListViewController<CustomerMaster>
{
...
}

CustomerMaster是一个符合RestModel协议(protocol)的具体类。

问题:
奇怪的是,最后一个类 Clv 没有出现在 Storyboard 的“自定义类:类”下拉菜单中,这意味着我无法将其指定为我的 View 的自定义类。

我尝试只是输入它,但这会导致运行时错误

Unknown class _TtC9Inventory3Clv in Interface Builder file ...

如果我从 ListViewController 类定义中删除 并从 Clv 类定义中删除 ,则 Clv 类就会出现在“类”菜单中(当然这并没有真正的帮助,只是观察)。

AppViewController 和 ListViewController 都确实出现在该菜单中。

我很茫然。

最佳答案

今年早些时候,我为一个应用程序创建了一个类似的架构,我必须告诉你:它不能与 Storyboard一起使用,因为 Storyboard在实例化期间对泛型一无所知。

有效的方法是使用 nib,因为您仍然可以自己初始化 View Controller 。

示例:

import UIKit

class ViewController<Model: Any>: UIViewController {
var model:Model?
}

你可以像这样实例化这个 View Controller

let vc = ViewController<ListItem>(nibName: "ListViewController", bundle: nil)

或子类化它

class ListViewController: ViewController<ListItem> {
}

并像这样实例化它

let vc = ListViewController(nibName: "ListViewController", bundle: nil)

现在它可以编译并运行,但您还没有获得太多收获,因为您无法使用通用属性连接您的 Nib 。

但是你可以做的是在非通用基本 View Controller 中拥有一个 UIView 类型的 IBOutlet,将其子类化为具有两个通用契约的通用 View Controller :一个用于模型,一个用于 View ,ass you最有可能希望它适合您的模型。但现在您必须拥有一些知道如何将模型带入 View 的代码。我称之为渲染器,但您还会发现很多例子,这样的类称为 Presenter。

View Controller :

class BaseRenderViewController: UIViewController {
var renderer: RenderType?
@IBOutlet private weak var privateRenderView: UIView!

var renderView: UIView! {
get { return privateRenderView }
set { privateRenderView = newValue }
}
}


class RenderedContentViewController<Content, View: UIView>: BaseRenderViewController {

var contentRenderer: ContentRenderer<Content, View>? {
return renderer as? ContentRenderer<Content, View>
}

open
override func viewDidLoad() {
super.viewDidLoad()

guard let renderer = contentRenderer, let view = self.renderView as? View else {
return
}
do {
try renderer.render(on: view)

} catch (let error) {
print(error)
}
}
}

渲染器:

protocol RenderType {}

class Renderer<View: UIView>: RenderType {
func render(on view: View) throws {
throw RendererError.methodNotOverridden("\(#function) must be overridden")
}
}

class ContentRenderer<Content, View: UIView>: Renderer<View> {
init(contents: [Content]) {
self.contents = contents
}
let contents: [Content]

override func render(on view: View) throws {
throw RendererError.methodNotOverridden("\(#function) must be overridden")
}
}

您现在可以子类化 ContentRenderer 并覆盖渲染方法以在 View 上显示您的内容。

tl;博士

通过使用我刚刚演示的方法,您可以将任何通用 View Controller 与不同的模型、渲染器和 View 组合起来。您获得了令人难以置信的灵 active - 但您将无法使用 Storyboard。

关于cocoa - 自定义 View Controller 类未在 Storyboard的类菜单中列出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45947959/

25 4 0