Skip to content

Instantly share code, notes, and snippets.

@wiiale
Last active July 22, 2020 08:32
Show Gist options
  • Save wiiale/43d0dda17d40abea48866403d4961213 to your computer and use it in GitHub Desktop.
Save wiiale/43d0dda17d40abea48866403d4961213 to your computer and use it in GitHub Desktop.
//: A UIKit based Playground for presenting user interface
import UIKit
import PlaygroundSupport
enum SkyBehavior: String {
case clickSky = "clickSky"
case clickSun = "clickSun"
case clickSunspot = "clickSunspot"
}
extension UIResponder {
@objc func routerEvent(name: String, userInfo: [AnyHashable: Any]?) {
next?.routerEvent(name: name, userInfo: userInfo)
}
}
class SkyView: UIView {
let sunView = SunView(frame: .sun)
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .blue
addSubview(sunView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
routerEvent(name: SkyBehavior.clickSky.rawValue, userInfo: nil)
}
}
class SunView: UIView {
let spotView = SunspotView(frame: .sunspot)
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .red
addSunlight()
addSubview(spotView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
routerEvent(name: SkyBehavior.clickSun.rawValue, userInfo: nil)
}
override func routerEvent(name: String, userInfo: [AnyHashable : Any]?) {
super.routerEvent(name: name, userInfo: userInfo)
if name == SkyBehavior.clickSunspot.rawValue {
routerEvent(name: SkyBehavior.clickSun.rawValue, userInfo: nil)
}
}
}
class SunspotView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .black
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
routerEvent(name: SkyBehavior.clickSunspot.rawValue, userInfo: ["sunspotId": 10])
}
}
class SkyViewController: UIViewController {
override func loadView() {
self.view = SkyView()
}
override func routerEvent(name: String, userInfo: [AnyHashable : Any]?) {
guard let event = SkyBehavior(rawValue: name) else { return }
switch event {
case .clickSky: print("[Sky] click sky")
case .clickSun: print("[Sky] click sun")
case .clickSunspot:
print("[Sky] click sun spot")
}
}
}
fileprivate extension SunView {
func addSunlight() {
layer.shadowColor = UIColor.red.cgColor
layer.shadowRadius = 10
layer.shadowOpacity = 0.8
layer.shadowPath = UIBezierPath(rect: .sunlight).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = UIScreen.main.scale
}
}
// Colors
fileprivate extension UIColor {
convenience init(r: UInt32, g: UInt32, b: UInt32) {
self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: 1.0)
}
static var red: UIColor { return .init(r: 236, g: 67, b: 84) }
static var blue: UIColor { return .init(r: 44, g: 110, b: 179) }
static var green: UIColor { return .init(r: 71, g: 180, b: 90) }
static var black: UIColor { return .init(r: 46, g: 36, b: 35) }
static var random: UIColor {
return .init(r: arc4random() % 255, g: arc4random() % 255, b: arc4random() % 255)
}
}
// LayoutConstants
fileprivate extension CGRect {
static var sun: CGRect {
return CGRect(x: 50, y: 50, width: 100, height: 100)
}
static var sunlight: CGRect {
return CGRect(x: -10, y: -10, width: 120, height: 120)
}
static var sunspot: CGRect {
return CGRect(x: 20, y: 20, width: 10, height: 10)
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = SkyViewController()
//: A UIKit based Playground for presenting user interface
import UIKit
import PlaygroundSupport
public protocol ResponderChainEventType {}
public protocol ResponderChainType {
func router<Event>(event: Event) where Event : ResponderChainEventType
}
extension ResponderChainType where Self: UIResponder {
public func router<Event>(event: Event) where Event : ResponderChainEventType {
// Responder handler
if let n = next as? SkyViewController {
n.router(event: event)
} else {
next?.router(event: event)
}
}
}
extension UIResponder: ResponderChainType {}
//: Custom Events
enum SkyBehavior: ResponderChainEventType {
case clickSky
case clickSun
case clickSunspot(id: Int)
}
//: Custom view
class SkyView: UIView {
let sunView = SunView(frame: .sun)
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .blue
addSubview(sunView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
router(event: SkyBehavior.clickSky)
}
}
class SunView: UIView {
let spotView = SunspotView(frame: .sunspot, id: 1)
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .red
addSunlight()
addSubview(spotView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
router(event: SkyBehavior.clickSun)
}
}
class SunspotView: UIView {
let id: Int
init(frame: CGRect, id: Int) {
self.id = id
super.init(frame: frame)
backgroundColor = .black
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
router(event: SkyBehavior.clickSunspot(id: id))
}
}
class SkyViewController: UIViewController {
override func loadView() {
self.view = SkyView()
}
func router<Event>(event: Event) where Event : ResponderChainEventType {
guard let e = event as? SkyBehavior else { return }
switch e {
case .clickSky: print("[Sky] click sky")
case .clickSun: print("[Sky] click sun")
case .clickSunspot(let sunspotId): print("[Sky] click sunspot - id: \(sunspotId)")
}
}
}
fileprivate extension SunView {
func addSunlight() {
layer.shadowColor = UIColor.red.cgColor
layer.shadowRadius = 10
layer.shadowOpacity = 0.8
layer.shadowPath = UIBezierPath(rect: .sunlight).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = UIScreen.main.scale
}
}
// Colors
fileprivate extension UIColor {
convenience init(r: UInt32, g: UInt32, b: UInt32) {
self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: 1.0)
}
static var red: UIColor { return .init(r: 236, g: 67, b: 84) }
static var blue: UIColor { return .init(r: 44, g: 110, b: 179) }
static var green: UIColor { return .init(r: 71, g: 180, b: 90) }
static var black: UIColor { return .init(r: 46, g: 36, b: 35) }
static var random: UIColor {
return .init(r: arc4random() % 255, g: arc4random() % 255, b: arc4random() % 255)
}
}
// LayoutConstants
fileprivate extension CGRect {
static var sun: CGRect {
return CGRect(x: 50, y: 50, width: 100, height: 100)
}
static var sunlight: CGRect {
return CGRect(x: -10, y: -10, width: 120, height: 120)
}
static var sunspot: CGRect {
return CGRect(x: 20, y: 20, width: 10, height: 10)
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = SkyViewController()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment