1

私が理解していることから、RACSubjectReactiveCocoa 4 に相当するのはObserverクラスです。信号とオブザーバーをリンクして、信号がイベントを送信し、オブザーバーに送信されたイベントにマップ操作を適用したいと考えています。Obj-C では、次のようになります。

// ViewModel.h

@interface ViewModel

@property (readonly) RACSubject *someAction; //expects e.g. int values
@property (readonly) RACSignal *someSignal; //sends e.g. string values

@end

// ViewModel.m

//redeclaring the signal and action as readwrite

@implementation

- (id)init {
  _someAction = [RACSubject subject];
  _someSignal = [_someAction map:^id(NSNumber *index) {
     return "Some string based on index passed in";
  }];
}

@end

誰かが に値をプッシュするとsomeActionsomeSignalは派生値を含むイベントを発生させます。Swiftで同じ効果を得るにはどうすればよいですか?

私がこれまでにできたことは、次のようなものです。

public class ViewModel: NSObject {
    public let (internalSignal, someAction) = Signal<Int, NoError>.pipe()
    public var someSignal: Signal<String, NoError> {
        get {
            return self.internalSignal.map({ [unowned self](index: Int) -> String in
                return "Some string value based on \(self.someArray[index])"
            })
        }
    }
    public let someArray = [1, 2, 3, 4, 5]
}

これは悪い解決策のように見えます。

  1. internalSignalプライベートにする必要がありますが、Signal のパイプと一致させるためにパブリックとして宣言する必要があります
  2. someSignalしたがって、同じ信号を何度も再利用できる場合でも、必要になるたびに計算されます。letまた、定数として宣言することはできません。
4

1 に答える 1

2

initObjC と同じようにメンバーを初期化できます...

public class ViewModel: NSObject {
    private let internalSignal: Signal<Int, NoError>
    public let someAction: Observer<Int, NoError>
    public let someSignal: Signal<String, NoError>

    override init() {
        (internalSignal, someAction) = Signal<Int, NoError>.pipe()
        someSignal = internalSignal.map { index in
            "Some string value based on \(index)"
        }
        super.init()
    }
}

メンバーが参照できるようにするため、遅延初期化someSignalを使用することもできます。self

public class ViewModel: NSObject {
    private let internalSignal: Signal<Int, NoError>
    public let someAction: Observer<Int, NoError>
    public private(set) lazy var someSignal: Signal<String, NoError> =
        self.internalSignal.map { [unowned self] index in
            "Some string value based on \(self.someArray[index])"
        }

    override init() {
        (internalSignal, someAction) = Signal<Int, NoError>.pipe()
        super.init()
    }
}

最初のコードとは異なり、lazy-var はsomeSignalViewModel の初期化時ではなく、使用前にのみ初期化されます。

また、それは であるためvar、Swift ではその値を mutate することができます ( のようなものはありませんlazy let)。を使用して許可を制限できprivate(set)ますが、これは誤ってself.someSignal = ...どこかに書き込むことを防ぐことはできません。


someSignalまたは、暗黙的にラップ解除されたオプションを作成し、手動で初期化することもできます。

public class ViewModel: NSObject {
    private let internalSignal: Signal<Int, NoError>
    public let someAction: Observer<Int, NoError>
    public private(set) var someSignal: Signal<String, NoError>!

    override init() {
        (internalSignal, someAction) = Signal<Int, NoError>.pipe()
        super.init()
        someSignal = internalSignal.map { [unowned self] index in
            "Some string value based on \(self.someArray[index])"
        }
    }
}
于 2016-05-19T13:05:04.570 に答える