I want to have an array of different page (HTML and PDF pages, may add more later on).
I thought this is a good chance to practice programming with protocols.
This is what I came up with:
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 )
}
}
Everything seems fine, but as in my print statements there is an obvious problem.
Edit: I don't claim the code to be perfect above. But in answer to a question below pageArray is optional as before downloading from an API there may be no pages, but that is different from no pages pulled from the API.
There is no point in storing the enum, as I have to cast to the correct type in any case.
The idea behind doing this is so I can store the pages in the single array, get them as needed and then display in my view controller (formatted by my view model) rather than drawing from 2+ arrays with different types in them.
I imagined writing a nice case statement to be able to display the information properly (there will be other fields in my finished structs) but this seems impossible with my implementation.
How can I refactor the code to be able to switch on the type of pages as declared above?
pageArrayoptional? That just seems to add unnecessary unwrapping.pageTypein your example not match the class type. Are you just trying to confuse us?