Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios NSNotificationCenter与ReactiveCocoa 3和Swift的正确用法是什么?_Ios_Swift_Nsnotificationcenter_Reactive Cocoa - Fatal编程技术网

Ios NSNotificationCenter与ReactiveCocoa 3和Swift的正确用法是什么?

Ios NSNotificationCenter与ReactiveCocoa 3和Swift的正确用法是什么?,ios,swift,nsnotificationcenter,reactive-cocoa,Ios,Swift,Nsnotificationcenter,Reactive Cocoa,我正在玩ReactiveCocoa3和Swift,我决定做一个简单的玩具应用程序来测试如何使用ReactiveCocoa3设计一个实现MVVM模式的应用程序 基本工作人员工作得很好,但我不确定处理通知中心发出的信号的最佳方式是什么 假设有人在应用程序的某个地方触发了通知。通知名为TimerNotification,在用户信息字典中有一个时间对象Int,可通过键TimerCount访问。现在让我们假设我有一个控制器,它希望在每次触发TimerNotification时打印消息 在旧的ObjC/RA

我正在玩ReactiveCocoa3和Swift,我决定做一个简单的玩具应用程序来测试如何使用ReactiveCocoa3设计一个实现MVVM模式的应用程序

基本工作人员工作得很好,但我不确定处理通知中心发出的信号的最佳方式是什么

假设有人在应用程序的某个地方触发了通知。通知名为
TimerNotification
,在用户信息字典中有一个时间对象
Int
,可通过键
TimerCount
访问。现在让我们假设我有一个控制器,它希望在每次触发
TimerNotification
时打印消息

在旧的ObjC/RAC 2天中,我会这样做

- (void)viewDidLoad {
  NSNotificationCenter * notificationCenter = [NSNotificationCenter defaultCenter];
  RACSignal * timerSignal = [[notificationCenter rac_addObserverForNotificationName:@"TimerNotification" object:nil] 
    takeUntil:self.rac_willDeallocSignal];
  [timerSignal subscribeNext:^(NSNotification * notification){
    NSValue * timerCount = notification.userInfo[@"TimerCount"];
    NSLog(@"Timer count is %@", timerCount);
  }];
}
这将确保当控制器被释放时,订阅将被释放

我第一次尝试在Swift/RAC 3世界中做类似的事情是

private func createTimerSignalProducer() -> SignalProducer<Int, NoError> {
  let notificationCenter = NSNotificationCenter.defaultCenter()
  let deallocSignalProducer = self.rac_willDeallocSignal().toSignalProducer()
      |> map { _ in () }
      |> catch { _ in SignalProducer.empty as SignalProducer<(), NoError> }

  return notificationCenter.rac_notifications(name: "TimerNotification")
      |> map { $0.userInfo!["TimerCount"] as! Int }
      |> takeUntil(deallocSignalProducer)
}
这实际上是可行的,但如果您想在一个不从NSObject继承的对象中执行类似的操作,该怎么办呢。因为在一个普通的Swift对象中,你不会得到
rac\u willDeallocSignal()

一种可能的解决方案是将一次性数据存储在实例变量中,然后在
deinit
中进行处理,但我希望避免手动处理一次性数据

更新

我最后做的事情(因为Swift对象没有根对象)是

公共协议视图模型{ } 公共类BaseViewModel:ViewModel{ 私有let denitSignalProducerSinkPair=SignalProducer.buffer() 公共var脱硝生产商:信号生产商{ 返回DenitSignalProducerSinkPair.0 } 脱硝{ sendNext(DenitSignalProducerSinkPair.1,()) } } 然后在我的视图模型中

public class DetailViewModel: BaseViewModel {

    let title: String
    let subtitle: String
    let author: String
    let createdAt: NSDate
    let timerCounter = MutableProperty<Int>(0)
    let inputText = MutableProperty<String>("")
    let reverseInputText = MutableProperty<String>("")

    var formattedCreatedAt: String {
        let formatter = NSDateFormatter()
        formatter.dateFormat = "dd/MM/yy"
        return formatter.stringFromDate(createdAt)
    }

    public required init(title: String, subtitle: String, author: String, createdAt: NSDate) {
        self.title = title
        self.subtitle = subtitle
        self.author = author
        self.createdAt = createdAt
        super.init()

        timerCounter <~ createTimerSignalProducer()
        reverseInputText <~ (inputText.producer |> map { String(reverse($0)) })
    }

    // MARK - Private methods

    private func createTimerSignalProducer() -> SignalProducer<Int, NoError> {
        return NSNotificationCenter.defaultCenter().rac_notifications(name: "TimerNotification")
            |> map { $0.userInfo!["TimerCount"] as! Int }
            |> takeUntil(deinitSingalProducer)
    }
}
public类DetailViewModel:BaseViewModel{
标题:字符串
让字幕:字符串
让作者:字符串
让createdAt:NSDate
let timerCounter=MutableProperty(0)
让inputText=MutableProperty(“”)
让reverseInputText=MutableProperty(“”)
var formattedCreatedAt:字符串{
let formatter=NSDateFormatter()
formatter.dateFormat=“dd/MM/yy”
返回格式化程序stringFromDate(createdAt)
}
公共必需的init(标题:String,副标题:String,作者:String,createdAt:NSDate){
self.title=标题
self.subtitle=副标题
self.author=作者
self.createdAt=createdAt
super.init()
计时器信号发生器{
返回NSNotificationCenter.defaultCenter().rac\U通知(名称:“TimerNotification”)
|>映射{$0.userInfo![“TimerCount”]as!Int}
|>TAKETILL(脱硝生产商)
}
}

我也遇到了同样的问题。我写了一篇关于我提出的解决方案的文章(在RAC4中)
public protocol ViewModel {

}

public class BaseViewModel: ViewModel {

    private let deinitSignalProducerSinkPair = SignalProducer<(), NoError>.buffer()

    public var deinitSingalProducer: SignalProducer<(), NoError> {
        return deinitSignalProducerSinkPair.0
    }

    deinit {
        sendNext(deinitSignalProducerSinkPair.1, ())
    }

}
public class DetailViewModel: BaseViewModel {

    let title: String
    let subtitle: String
    let author: String
    let createdAt: NSDate
    let timerCounter = MutableProperty<Int>(0)
    let inputText = MutableProperty<String>("")
    let reverseInputText = MutableProperty<String>("")

    var formattedCreatedAt: String {
        let formatter = NSDateFormatter()
        formatter.dateFormat = "dd/MM/yy"
        return formatter.stringFromDate(createdAt)
    }

    public required init(title: String, subtitle: String, author: String, createdAt: NSDate) {
        self.title = title
        self.subtitle = subtitle
        self.author = author
        self.createdAt = createdAt
        super.init()

        timerCounter <~ createTimerSignalProducer()
        reverseInputText <~ (inputText.producer |> map { String(reverse($0)) })
    }

    // MARK - Private methods

    private func createTimerSignalProducer() -> SignalProducer<Int, NoError> {
        return NSNotificationCenter.defaultCenter().rac_notifications(name: "TimerNotification")
            |> map { $0.userInfo!["TimerCount"] as! Int }
            |> takeUntil(deinitSingalProducer)
    }
}