Created
May 24, 2016 05:29
-
-
Save JRHeaton/331ec5b0e03c2b6d9140ff5825c173ae to your computer and use it in GitHub Desktop.
Swift bug w/ generic class initializer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
enum X: ErrorType {} | |
/** | |
error: declared closure result 'UICollectionView' is incompatible with contextual type '_' | |
createItemView: { () -> UICollectionView in | |
(it should be inferring LoadStateView.ItemView as the return type of this closure) | |
*/ | |
let vc = LoadStateView<Int, X, UICollectionView, UIView>( | |
createItemView: { () -> UICollectionView in | |
return UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) | |
}, | |
createErrorView: .init, | |
displayItem: { view, item in | |
}, | |
displayError: { view, error in | |
}) | |
public protocol LoadStateDisplayable { | |
associatedtype StateItem | |
associatedtype StateError: ErrorType | |
func displayLoadState(state: LoadState<StateItem, StateError>) | |
} | |
public class LoadStateView< | |
Item, | |
Error: ErrorType, | |
ItemView: UIView, | |
ErrorView: UIView>: UIView, LoadStateDisplayable { | |
// Types | |
public typealias DisplayItemClosure = (ItemView, Item) -> () | |
public typealias DisplayErrorClosure = (ErrorView, Error) -> () | |
// Views | |
public let itemView: ItemView | |
public let loadingView: UIActivityIndicatorView | |
public let errorView: ErrorView | |
// Closures | |
public let displayItemClosure: DisplayItemClosure | |
public let displayErrorClosure: DisplayErrorClosure | |
public init( | |
@noescape createItemView: () -> ItemView, | |
@noescape createErrorView: () -> ErrorView, | |
displayItem: DisplayItemClosure, | |
displayError: DisplayErrorClosure) { | |
itemView = createItemView() | |
errorView = createErrorView() | |
displayItemClosure = displayItem | |
displayErrorClosure = displayError | |
loadingView = UIActivityIndicatorView() | |
super.init(frame: .zero) | |
addSubview(itemView) | |
addSubview(loadingView) | |
addSubview(errorView) | |
} | |
public func displayLoadState(state: LoadState<Item, Error>) { | |
if state.isLoading { | |
loadingView.startAnimating() | |
} else { | |
loadingView.stopAnimating() | |
} | |
itemView.hidden = !state.isLoaded | |
errorView.hidden = state.error == nil | |
switch state { | |
case .NotLoaded: | |
() | |
case .Loading: | |
() | |
case .Loaded(let item): | |
displayItemClosure(itemView, item) | |
case .Failure(let error): | |
displayErrorClosure(errorView, error) | |
} | |
} | |
} | |
public enum LoadState<Item, Error: ErrorType> { | |
case NotLoaded | |
case Loading | |
case Loaded(Item) | |
case Failure(Error) | |
public var item: Item? { | |
if case .Loaded(let item) = self { | |
return item | |
} | |
return nil | |
} | |
public var error: Error? { | |
if case .Failure(let error) = self { | |
return error | |
} | |
return nil | |
} | |
public var isLoading: Bool { | |
if case .Loading = self { | |
return true | |
} | |
return false | |
} | |
public var isLoaded: Bool { | |
if case .Loaded = self { | |
return true | |
} | |
return false | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment