有没有办法让以下工作在Swift 3中?
let button = UIButton().apply {
$0.setImage(UIImage(named: "UserLocation"), for: .normal)
$0.addTarget(self, action: #selector(focusUserLocation),
for: .touchUpInside)
$0.translatesAutoresizingMaskIntoConstraints = false
$0.backgroundColor = UIColor.black.withAlphaComponent(0.5)
$0.layer.cornerRadius = 5
}
apply<T>
函数应该使用(T)->Void
类型的闭包,运行它将self
传递给它,然后只返回self
。
另一种选择是使用运算符,如“=>
”
(借用了Kotlin和Xtend种语言的想法)。
尝试像这样扩展NSObject
:
extension NSObject {
func apply<T>(_ block: (T)->Void) -> T
{
block(self as! T)
return self as! T
}
}
但它需要在闭包中明确声明参数类型:
let button = UIButton().apply { (it: UIButton) in
it.setImage(UIImage(named: "UserLocation"), for: .normal)
it.addTarget(self, action: #selector(focusUserLocation),
for: .touchUpInside)
...
这不方便,使整个想法不值得努力。该类型已在创建对象时指定,应该可以不显式重复。
谢谢!
答案 0 :(得分:21)
首先让我们定义HasApply
协议
protocol HasApply { }
及相关扩展
extension HasApply {
func apply(closure:(Self) -> ()) -> Self {
closure(self)
return self
}
}
接下来让make NSObject
符合HasApply
。
extension NSObject: HasApply { }
让我们测试一下
let button = UIButton().apply {
$0.titleLabel?.text = "Tap me"
}
print(button.titleLabel?.text) // Optional("Tap me")
我不会使用
NSObject
(它是Objective-C做事方式的一部分,我认为它将在未来的某个时候删除)。我更喜欢UIView
之类的东西。
extension UIView: HasApply { }
答案 1 :(得分:5)
我遇到了同样的问题,最后用操作员解决了这个问题:
infix operator <-< : AssignmentPrecedence
func <-<<T:AnyObject>(left:T, right:(T)->()) -> T
{
right(left)
return left
}
let myObject = UIButton() <-< { $0.isHidden = false }
答案 2 :(得分:5)
有一个名为Then
的{{3}}就是这样做的。只是它使用then
而不是apply
。只需导入Then
和然后,您可以按OP要求:
import Then
myObject.then {
$0.objectMethod()
}
let label = UILabel().then {
$0.color = ...
}
以下是协议的实施方式:very good and simple Cocoapods library
extension Then where Self: Any {
public func then(_ block: (Self) throws -> Void) rethrows -> Self {
try block(self)
return self
}
答案 3 :(得分:1)
String containerString = ....;
Data data = .....;
....
....
List<Command> commands = Arrays.asList(new ServerAdminCommand() ,
new DocumentRootCommand() /* etc...... */ );
commands.forEach(com -> com.execute(data,containerString));
然后允许您使用:
@discardableResult func apply<T>(_ it:T, f:(T)->()) -> T {
f(it)
return it
}
它并不完全相同,但总的来说效果非常好,并且具有T完全无拘无束的优势。这是一个明显做作的例子,但是:
let button = apply(UIButton()) { $0.setTitleText("Button") }
甚至允许:
func apply<T,R>(_ it:T, f:(T)->R) -> R {
return f(it)
}
答案 4 :(得分:-1)
这是通用协议和扩展的示例。 我希望你能帮助你
protocol Container {
associatedtype ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }}
class Stack<S>: Container {
// original Stack<T> implementation
var items = [S]()
func push(item: S) {
items.append(item)}
func pop() -> S {
return items.removeLast()
}
// conformance to the Container protocol
func append(item: S) {
self.push(item: item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> S {
return items[i]
}}
extension Stack {
var topItem: S? {
return items.isEmpty ? nil : items[items.count - 1]
}}
var stringStack = Stack<String>()
var intStack = Stack<Int>()