Swift扩展子句在哪里或那个

时间:2021-04-30 08:18:15

I want an extension for two classes UITextField and UITextView and the code is identical, but I have trouble coming up with an extension that will work for them both.

我想要一个UITextField和UITextView两个类的扩展,代码是相同的,但我很难想出一个适合他们的扩展。

I am using ReactiveCocoa and I currently have this

我正在使用ReactiveCocoa,我现在有这个

import UIKit
import ReactiveCocoa
import enum Result.NoError

typealias NoError = Result.NoError

// How to DRY up this code?
extension UITextField {
  func textSignalProducer() -> SignalProducer<String, NoError> {
    return self.rac_textSignal()
      .toSignalProducer()
      .map { $0 as! String }
      .flatMapError { error in SignalProducer<String, NoError>(value:  "") }
  }
}

extension UITextView {
  func textSignalProducer() -> SignalProducer<String, NoError> {
    return self.rac_textSignal()
      .toSignalProducer()
      .map { $0 as! String }
      .flatMapError { error in SignalProducer<String, NoError>(value:  "") }
  }
}

How would I write an extension that would work for both? I was trying to do something like

我如何编写一个适合两者的扩展?我想做点什么

protocol TextSignalProducer {}

extension TextSignalProducer where Self: ???? {
  // Same code as is duplicated in both current extensions...
}

but I have no idea how to specify Self as either UITextField or UITextView. Something like where Self == UITextField || Self == UITextView would probably make this possible.

但我不知道如何将Self指定为UITextField或UITextView。像Self == UITextField ||的地方自我== UITextView可能会使这成为可能。

Is there a nice way to accomplish what I want to try? Is this really necessary (I don't know the naming conventions for protocols/extensions)

有没有一种很好的方法来实现我想要尝试的东西?这是否真的有必要(我不知道协议/扩展的命名约定)

import UIKit
import ReactiveCocoa
import enum Result.NoError

typealias NoError = Result.NoError

protocol TextSignal {
  func rac_textSignal() -> RACSignal!
}

extension UITextField: TextSignal, TextSignalProducer {}
extension UITextView: TextSignal, TextSignalProducer {}

protocol TextSignalProducer {}

extension TextSignalProducer where Self: TextSignal {
  func textSignalProducer() -> SignalProducer<String, NoError> {
    return self.rac_textSignal()
      .toSignalProducer()
      .map { $0 as! String }
      .flatMapError { error in SignalProducer<String, NoError>(value:  "") }
  }
}

I am using Swift 2.1, Xcode 7.2 and ReactiveCocoa 4.0.1

我使用的是Swift 2.1,Xcode 7.2和ReactiveCocoa 4.0.1

2 个解决方案

#1


1  

You can cut down your proposed solution to a single dummy protocol:

您可以将建议的解决方案减少为单个虚拟协议:

protocol TextSignalProducer {
    func rac_textSignal() -> RACSignal!
}

extension TextSignalProducer {
    func textSignalProducer() -> SignalProducer<String, NoError> {
        return self.rac_textSignal()
            .toSignalProducer()
            .map { $0 as! String }
            .flatMapError { error in SignalProducer<String, NoError>(value:  "") }
    }
}

extension UITextField: TextSignalProducer {}
extension UITextView: TextSignalProducer {}

I don't think there's a more concise way than that, though. UITextField and UITextView's rac_textSignal() implementations have nothing in common.

不过,我认为没有比这更简洁的方法了。 UITextField和UITextView的rac_textSignal()实现没有任何共同之处。

#2


0  

UITextView and UITextField conform to UITextInput protocol. If rac_textSignal base on this protocol (I'm not sure because I don't have any project with RactiveCocoa at hand :) ) you can do this:

UITextView和UITextField符合UITextInput协议。如果rac_textSignal基于这个协议(我不确定,因为我手头没有任何RactiveCocoa项目:))你可以这样做:

protocol Cos {
    func textSignalProducer() -> String
}

extension UITextView: Cos {

}

extension UITextField: Cos {

}

extension Cos where Self: UITextInput {
    func textSignalProducer() -> String {
        return "dsfsdf"
    }
}

let cos = UITextView()
cos.textSignalProducer()

let cos2 = UITextField()
cos2.textSignalProducer()

#1


1  

You can cut down your proposed solution to a single dummy protocol:

您可以将建议的解决方案减少为单个虚拟协议:

protocol TextSignalProducer {
    func rac_textSignal() -> RACSignal!
}

extension TextSignalProducer {
    func textSignalProducer() -> SignalProducer<String, NoError> {
        return self.rac_textSignal()
            .toSignalProducer()
            .map { $0 as! String }
            .flatMapError { error in SignalProducer<String, NoError>(value:  "") }
    }
}

extension UITextField: TextSignalProducer {}
extension UITextView: TextSignalProducer {}

I don't think there's a more concise way than that, though. UITextField and UITextView's rac_textSignal() implementations have nothing in common.

不过,我认为没有比这更简洁的方法了。 UITextField和UITextView的rac_textSignal()实现没有任何共同之处。

#2


0  

UITextView and UITextField conform to UITextInput protocol. If rac_textSignal base on this protocol (I'm not sure because I don't have any project with RactiveCocoa at hand :) ) you can do this:

UITextView和UITextField符合UITextInput协议。如果rac_textSignal基于这个协议(我不确定,因为我手头没有任何RactiveCocoa项目:))你可以这样做:

protocol Cos {
    func textSignalProducer() -> String
}

extension UITextView: Cos {

}

extension UITextField: Cos {

}

extension Cos where Self: UITextInput {
    func textSignalProducer() -> String {
        return "dsfsdf"
    }
}

let cos = UITextView()
cos.textSignalProducer()

let cos2 = UITextField()
cos2.textSignalProducer()