Instantly share code, notes, and snippets.
Last active
May 25, 2018 07:01
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save bcse/aa0063f05d9053bfd01783ec6dc12182 to your computer and use it in GitHub Desktop.
Generics class with delegate
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 Foundation | |
import UIKit | |
public protocol MenuItem {} | |
public protocol MenuDelegate: AnyObject { | |
associatedtype Item: MenuItem | |
func menu(_ menu: Menu<Item, Self>, didSelect item: Item) | |
} | |
open class Menu<Item, Delegate>: UIView where Delegate: MenuDelegate, Delegate.Item == Item { | |
public weak var delegate: Delegate? | |
func tap(item: Item) { | |
delegate?.menu(self, didSelect: item) | |
} | |
} | |
// It's very strange that this class must be final. This is a no-go. | |
final class MyViewController: UIViewController, MenuDelegate { | |
enum MyItem: String, MenuItem { | |
case one = "one" | |
case two = "two" | |
case three = "three" | |
} | |
typealias Item = MyItem | |
// It's strange that user have to put its own class here, but this can be "fixed" by using typealias | |
var menu: Menu<Item, MyViewController>? | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
menu = Menu<Item, MyViewController>(frame: view.bounds) | |
menu?.delegate = self | |
} | |
// MARK: MenuDelegate | |
func menu(_ menu: Menu<Item, MyViewController>, didSelect item: Item) { | |
switch item { | |
case .one: | |
break | |
case .two: | |
break | |
case .three: | |
break | |
} | |
} | |
} |
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 Foundation | |
import UIKit | |
public protocol MenuItem {} | |
public protocol MenuDelegate: AnyObject { | |
func menu<T>(_ menu: Menu<T>, didSelect item: T) | |
} | |
open class Menu<Item: MenuItem>: UIView { | |
public weak var delegate: MenuDelegate? | |
func tap(item: Item) { | |
delegate?.menu(self, didSelect: item) | |
} | |
} | |
class MyViewController: UIViewController { | |
enum MyItem: String, MenuItem { | |
case one = "one" | |
case two = "two" | |
case three = "three" | |
} | |
var menu: Menu<MyItem>? | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
menu = Menu<MyItem>(frame: view.bounds) | |
menu?.delegate = self | |
} | |
} | |
extension MyViewController: MenuDelegate { | |
// It's a little strange that user have to use where clause to declare type of MenuItem | |
func menu<T>(_ menu: Menu<T>, didSelect item: T) where T: MenuItem { | |
// It's very strange that user have to cast item in every delegate function, not | |
// just declare the correct type in previous line. | |
guard let item = item as? MyItem else { return } | |
switch item { | |
case .one: | |
break | |
case .two: | |
break | |
case .three: | |
break | |
} | |
} | |
} |
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
// No generics, but it feels more natural than MyMenu2 | |
import Foundation | |
import UIKit | |
public protocol MenuItem {} | |
public protocol MenuDelegate: AnyObject { | |
func menu(_ menu: Menu, didSelect item: MenuItem) | |
} | |
open class Menu: UIView { | |
public weak var delegate: MenuDelegate? | |
func tap(item: MenuItem) { | |
delegate?.menu(self, didSelect: item) | |
} | |
} | |
class MyViewController: UIViewController { | |
enum MyItem: String, MenuItem { | |
case one = "one" | |
case two = "two" | |
case three = "three" | |
} | |
var menu: Menu? | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
menu = Menu(frame: view.bounds) | |
menu?.delegate = self | |
} | |
} | |
extension MyViewController: MenuDelegate { | |
func menu(_ menu: Menu, didSelect item: MenuItem) { | |
// It's very strange that user have to cast item in every delegate function | |
guard let item = item as? MyItem else { return } | |
switch item { | |
case .one: | |
break | |
case .two: | |
break | |
case .three: | |
break | |
} | |
} | |
} |
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
// No generics | |
import Foundation | |
import UIKit | |
public struct MenuItem: ExpressibleByStringLiteral, Equatable, Hashable { | |
public typealias StringLiteralType = String | |
let rawValue: StringLiteralType | |
public init(stringLiteral value: StringLiteralType) { | |
rawValue = value | |
} | |
} | |
public protocol MenuDelegate: AnyObject { | |
func menu(_ menu: Menu, didSelect item: MenuItem) | |
} | |
open class Menu: UIView { | |
public weak var delegate: MenuDelegate? | |
func tap(item: MenuItem) { | |
delegate?.menu(self, didSelect: item) | |
} | |
} | |
// It's strange to use extension for enum. It might cause confusion when creating multiple Menu. | |
extension MenuItem { | |
static let one: MenuItem = "one" | |
static let two: MenuItem = "two" | |
static let three: MenuItem = "three" | |
} | |
class MyViewController: UIViewController { | |
var menu: Menu? | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
menu = Menu(frame: view.bounds) | |
menu?.delegate = self | |
} | |
} | |
extension MyViewController: MenuDelegate { | |
func menu(_ menu: Menu, didSelect item: MenuItem) { | |
switch item { | |
case .one: | |
break | |
case .two: | |
break | |
case .three: | |
break | |
default: | |
// It's a little strange that user always need to handle default case | |
break | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment