swift-tips
swift-tips copied to clipboard
Suggestions
#45 Getting rid of overabundant [weak self] and guard
Just a little bit another way with the same example
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
postfix operator ~
public postfix func ~ <T>(value: T) -> T.Type {
return T.self
}
extension NSObjectProtocol {
func weak<T>(_ closure: @escaping (Self) -> (T) -> Void) -> (T) -> Void {
return { [weak self] in
guard let self = self else { return }
return closure(self)($0)
}
}
}
class Producer: NSObject {
deinit {
print("deinit Producer")
}
private var handler: (Int) -> Void = { _ in }
func register(handler: @escaping (Int) -> Void) {
self.handler = handler
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: { self.handler(42) })
}
}
class Consumer: NSObject {
deinit {
print("deinit Consumer")
}
let producer = Producer()
func consume() {
producer.register(handler: weak(self~ .handle))
}
private func handle(_ result: Int) {
print("🎉 \(result)")
}
}
var consumer: Consumer? = Consumer()
consumer?.consume()
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0, execute: { consumer = nil })
// This code prints:
// 🎉 42
// deinit Consumer
// deinit Producer
However sometimes you need function to return value and weak will not work. You might want to use unowned:
extension NSObjectProtocol {
func unowned<T, U>(_ closure: @escaping (Self) -> (T) -> U) -> (T) -> U {
return { [ unowned self] in
return closure(self)($0)
}
}
}
#07 Implementing the builder pattern with keypaths
Not using keyPath allows to call functions:
import UIKit
extension NSObjectProtocol {
@discardableResult
func apply(_ closure: (Self) -> () ) -> Self {
{ closure(self) }()
return self
}
}
let view = UIView()
let label = UILabel().apply {
$0.textColor = .red
$0.text = "Foo \n Foo"
$0.textAlignment = .right
$0.layer.cornerRadius = 5
$0.sizeToFit()
}
view.addSubview(label)
It is safe because it nonescaping closure.
Hello, thank you for those suggestions!
I understand that the operator ~
can have value in the context of a project. However, custom operators are a controversial topic, so I wouldn't advise its use in the general case.
But I feel that it could alternatively implemented as a computed property on NSObject
, and you'd get to use it the same way than the operator.
The apply
function is indeed interesting! If I remember well, I think it's actually part of the standard library in Kotlin 🙂
Yes, but unfortunately in swift you can't get rid of "$0". At list I do not know how to do that =)