我想拥有一系列不同的页面(HTML和PDF页面,以后可能会添加更多页面)。
我认为这是练习协议编程的好机会。
这是我想出的:
protocol PageDataProtocol {
var data: String? {get}
}
protocol PageTitleProtocol {
var title: String {get}
var pageType: Page {get}
}
struct PDFData: PageTitleProtocol {
var title: String
var pageType: Page
}
struct HTMLData: PageDataProtocol, PageTitleProtocol {
var title: String
var data: String?
var pageType: Page
}
enum Page {
case html
case pdf
case links
}
var pageArray : [PageTitleProtocol]? = []
let test = PDFData(title: "title1", pageType: .html)
pageArray?.append(test)
let testtwo = HTMLData(title: "title2", data: "hello", pageType: .pdf)
pageArray?.append(testtwo)
for page in pageArray! {
print (page.title)
if let pg = page as? HTMLData {
print (pg.data)
}
if page.pageType == .pdf {
print ( (page as? HTMLData)?.data )
}
}
一切似乎都很好,但是就像我的打印声明中那样,有一个明显的问题。
编辑:我并不认为上面的代码是完美的。但是,在回答下面的问题时,pageArray是可选的,因为从API下载之前可能没有页面,但这与从API中提取的页面不同。
存储枚举毫无意义,因为无论如何我都必须转换为正确的类型。
这样做的想法是,我可以将页面存储在单个数组中,按需获取它们,然后显示在我的视图控制器中(由我的视图模型设置格式),而不是从其中包含不同类型的2个以上数组中绘制
我曾想过编写一个很好的case语句能够正确显示信息(在我完成的结构中还会有其他字段),但是对于我的实现来说,这似乎是不可能的。
如何重构代码以能够打开上面声明的页面类型?
答案 0 :(得分:1)
如果您的页面数据是预定义的并且从头开始进行密封,那么您甚至根本不需要protocol
(甚至会适得其反),只需扩展enum
:
enum Page {
case html(title: String, data: String?)
case pdf(title: String)
case links(title: String, array: [URL]) // or something else, it wasn't used in the example
var title: String {
switch(self) {
case .html(let title, _), .pdf(let title), .links(let title, _):
return title
}
}
}
var pageArray : [Page] = [] // no need to make it optional, btw
let test = Page.pdf(title: "title1")
pageArray.append(test)
let testtwo = Page.html(title: "title2", data: "hello")
pageArray.append(testtwo)
for page in pageArray {
print (page.title)
if case .html(_, let data) = page {
print(data)
}
}
答案 1 :(得分:0)
好吧,我不知道您要做什么,但是如果您要寻找的是这里,这里有个提示
protocol PageDataProtocol {
var data: String? {get}
}
protocol PageTitleProtocol {
var title: String {get}
}
struct PDFData: PageTitleProtocol {
var title: String
}
struct HTMLData: PageDataProtocol, PageTitleProtocol {
var title: String
var data: String?
}
var pageArray : [Any]? = []
let test = PDFData(title: "title1")
pageArray?.append(test)
let testtwo = HTMLData(title: "title2", data: "hello")
pageArray?.append(testtwo)
for page in pageArray! {
if let page = page as? PageDataProtocol {
print(page.data)
}
if let page = page as? PageTitleProtocol {
print(page.title)
}
}
检查一下,不需要枚举,并且强制转换为类型协议以使用该属性总是更好,因为您可以拥有100个符合标准的struct和class,但是您并不关心它们,而是关心内部属性(如果它们属于此特定协议的类型),这是对协议的正确使用。