2016-02-15 3 views
4

Я хочу расширение для двух классов UITextField и UITextView, а код идентичен, но у меня возникли проблемы с расширением, которое будет работать для них обоих.Быстрое предложение о расширении, где та или иная

Я использую 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: "") } 
    } 
} 

Как я хотел бы написать расширение, которое будет работать для обоих? Я пытался сделать что-то вроде

protocol TextSignalProducer {} 

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

, но я понятия не имею, как указать Self в либоUITextField или UITextView. Что-то вроде where Self == UITextField || Self == UITextView, вероятно, сделает это возможным.

Есть ли хороший способ выполнить то, что я хочу попробовать? Действительно ли это необходимо (я не знаю, соглашения об именах для протоколов/расширений)

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: "") } 
    } 
} 

Я использую Swift 2.1, Xcode 7.2 и ReactiveCocoa 4.0.1

ответ

0

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() 
+0

Хорошая идея с 'UITextInput', к сожалению, она не работает. Я думаю, что они реализованы один за другим, вот для 'UITextField' https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/ReactiveCocoa/Objective-C/UITextField%2BRACSignalSupport.h Я не уверен, что такое' RACSignalSupport 'здесь означает, что он имеет незаявленный тип, если я пытаюсь использовать его как' Self: RACSignalSupport' – Filuren

1

Вы можете сократить предложенное свое решение на один манекен протокол:

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 {} 

Я не думаю, что есть более краткий путь, чем это. UITextField и UITextViewrac_textSignal() реализации не имеют ничего общего.

Смежные вопросы