ObjectiveCBridging.swift 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. //
  2. // ObjectiveCBridging.swift
  3. // ReactiveCocoa
  4. //
  5. // Created by Justin Spahr-Summers on 2014-07-02.
  6. // Copyright (c) 2014 GitHub, Inc. All rights reserved.
  7. //
  8. import Result
  9. extension RACDisposable: Disposable {}
  10. extension RACScheduler: DateSchedulerType {
  11. /// The current date, as determined by this scheduler.
  12. public var currentDate: NSDate {
  13. return NSDate()
  14. }
  15. /// Schedule an action for immediate execution.
  16. ///
  17. /// - note: This method calls the Objective-C implementation of `schedule:`
  18. /// method.
  19. ///
  20. /// - parameters:
  21. /// - action: Closure to perform.
  22. ///
  23. /// - returns: Disposable that can be used to cancel the work before it
  24. /// begins.
  25. public func schedule(action: () -> Void) -> Disposable? {
  26. let disposable: RACDisposable = self.schedule(action) // Call the Objective-C implementation
  27. return disposable as Disposable?
  28. }
  29. /// Schedule an action for execution at or after the given date.
  30. ///
  31. /// - parameters:
  32. /// - date: Starting date.
  33. /// - action: Closure to perform.
  34. ///
  35. /// - returns: Optional disposable that can be used to cancel the work
  36. /// before it begins.
  37. public func scheduleAfter(date: NSDate, action: () -> Void) -> Disposable? {
  38. return self.after(date, schedule: action)
  39. }
  40. /// Schedule a recurring action at the given interval, beginning at the
  41. /// given start time.
  42. ///
  43. /// - parameters:
  44. /// - date: Starting date.
  45. /// - repeatingEvery: Repetition interval.
  46. /// - withLeeway: Some delta for repetition.
  47. /// - action: Closure of the action to perform.
  48. ///
  49. /// - returns: Optional `Disposable` that can be used to cancel the work
  50. /// before it begins.
  51. public func scheduleAfter(date: NSDate, repeatingEvery: NSTimeInterval, withLeeway: NSTimeInterval, action: () -> Void) -> Disposable? {
  52. return self.after(date, repeatingEvery: repeatingEvery, withLeeway: withLeeway, schedule: action)
  53. }
  54. }
  55. extension ImmediateScheduler {
  56. /// Create `RACScheduler` that performs actions instantly.
  57. ///
  58. /// - returns: `RACScheduler` that instantly performs actions.
  59. public func toRACScheduler() -> RACScheduler {
  60. return RACScheduler.immediateScheduler()
  61. }
  62. }
  63. extension UIScheduler {
  64. /// Create `RACScheduler` for `UIScheduler`
  65. ///
  66. /// - returns: `RACScheduler` instance that queues events on main thread.
  67. public func toRACScheduler() -> RACScheduler {
  68. return RACScheduler.mainThreadScheduler()
  69. }
  70. }
  71. extension QueueScheduler {
  72. /// Create `RACScheduler` backed with own queue
  73. ///
  74. /// - returns: Instance `RACScheduler` that queues events on
  75. /// `QueueScheduler`'s queue.
  76. public func toRACScheduler() -> RACScheduler {
  77. return RACTargetQueueScheduler(name: "org.reactivecocoa.ReactiveCocoa.QueueScheduler.toRACScheduler()", targetQueue: queue)
  78. }
  79. }
  80. private func defaultNSError(message: String, file: String, line: Int) -> NSError {
  81. return Result<(), NSError>.error(message, file: file, line: line)
  82. }
  83. extension RACSignal {
  84. /// Create a `SignalProducer` which will subscribe to the receiver once for
  85. /// each invocation of `start()`.
  86. ///
  87. /// - parameters:
  88. /// - file: Current file name.
  89. /// - line: Current line in file.
  90. ///
  91. /// - returns: Signal producer created from `self`.
  92. public func toSignalProducer(file: String = #file, line: Int = #line) -> SignalProducer<AnyObject?, NSError> {
  93. return SignalProducer { observer, disposable in
  94. let next = { obj in
  95. observer.sendNext(obj)
  96. }
  97. let failed = { nsError in
  98. observer.sendFailed(nsError ?? defaultNSError("Nil RACSignal error", file: file, line: line))
  99. }
  100. let completed = {
  101. observer.sendCompleted()
  102. }
  103. disposable += self.subscribeNext(next, error: failed, completed: completed)
  104. }
  105. }
  106. }
  107. extension SignalType {
  108. /// Turn each value into an Optional.
  109. private func optionalize() -> Signal<Value?, Error> {
  110. return signal.map(Optional.init)
  111. }
  112. }
  113. // MARK: - toRACSignal
  114. extension SignalProducerType where Value: AnyObject {
  115. /// Create a `RACSignal` that will `start()` the producer once for each
  116. /// subscription.
  117. ///
  118. /// - note: Any `Interrupted` events will be silently discarded.
  119. ///
  120. /// - returns: `RACSignal` instantiated from `self`.
  121. public func toRACSignal() -> RACSignal {
  122. return self
  123. .lift { $0.optionalize() }
  124. .toRACSignal()
  125. }
  126. }
  127. extension SignalProducerType where Value: OptionalType, Value.Wrapped: AnyObject {
  128. /// Create a `RACSignal` that will `start()` the producer once for each
  129. /// subscription.
  130. ///
  131. /// - note: Any `Interrupted` events will be silently discarded.
  132. ///
  133. /// - returns: `RACSignal` instantiated from `self`.
  134. public func toRACSignal() -> RACSignal {
  135. return self
  136. .mapError { $0 as NSError }
  137. .toRACSignal()
  138. }
  139. }
  140. extension SignalProducerType where Value: AnyObject, Error: NSError {
  141. /// Create a `RACSignal` that will `start()` the producer once for each
  142. /// subscription.
  143. ///
  144. /// - note: Any `Interrupted` events will be silently discarded.
  145. ///
  146. /// - returns: `RACSignal` instantiated from `self`.
  147. public func toRACSignal() -> RACSignal {
  148. return self
  149. .lift { $0.optionalize() }
  150. .toRACSignal()
  151. }
  152. }
  153. extension SignalProducerType where Value: OptionalType, Value.Wrapped: AnyObject, Error: NSError {
  154. /// Create a `RACSignal` that will `start()` the producer once for each
  155. /// subscription.
  156. ///
  157. /// - note: Any `Interrupted` events will be silently discarded.
  158. ///
  159. /// - returns: `RACSignal` instantiated from `self`.
  160. public func toRACSignal() -> RACSignal {
  161. // This special casing of `Error: NSError` is a workaround for
  162. // rdar://22708537 which causes an NSError's UserInfo dictionary to get
  163. // discarded during a cast from ErrorType to NSError in a generic
  164. // function
  165. return RACSignal.createSignal { subscriber in
  166. let selfDisposable = self.start { event in
  167. switch event {
  168. case let .Next(value):
  169. subscriber.sendNext(value.optional)
  170. case let .Failed(error):
  171. subscriber.sendError(error)
  172. case .Completed:
  173. subscriber.sendCompleted()
  174. case .Interrupted:
  175. break
  176. }
  177. }
  178. return RACDisposable {
  179. selfDisposable.dispose()
  180. }
  181. }
  182. }
  183. }
  184. extension SignalType where Value: AnyObject {
  185. /// Create a `RACSignal` that will observe the given signal.
  186. ///
  187. /// - note: Any `Interrupted` events will be silently discarded.
  188. ///
  189. /// - returns: `RACSignal` instantiated from `self`.
  190. public func toRACSignal() -> RACSignal {
  191. return self
  192. .optionalize()
  193. .toRACSignal()
  194. }
  195. }
  196. extension SignalType where Value: AnyObject, Error: NSError {
  197. /// Create a `RACSignal` that will observe the given signal.
  198. ///
  199. /// - note: Any `Interrupted` events will be silently discarded.
  200. ///
  201. /// - returns: `RACSignal` instantiated from `self`.
  202. public func toRACSignal() -> RACSignal {
  203. return self
  204. .optionalize()
  205. .toRACSignal()
  206. }
  207. }
  208. extension SignalType where Value: OptionalType, Value.Wrapped: AnyObject {
  209. /// Create a `RACSignal` that will observe the given signal.
  210. ///
  211. /// - note: Any `Interrupted` events will be silently discarded.
  212. ///
  213. /// - returns: `RACSignal` instantiated from `self`.
  214. public func toRACSignal() -> RACSignal {
  215. return self
  216. .mapError { $0 as NSError }
  217. .toRACSignal()
  218. }
  219. }
  220. extension SignalType where Value: OptionalType, Value.Wrapped: AnyObject, Error: NSError {
  221. /// Create a `RACSignal` that will observe the given signal.
  222. ///
  223. /// - note: Any `Interrupted` events will be silently discarded.
  224. ///
  225. /// - returns: `RACSignal` instantiated from `self`.
  226. public func toRACSignal() -> RACSignal {
  227. // This special casing of `Error: NSError` is a workaround for
  228. // rdar://22708537 which causes an NSError's UserInfo dictionary to get
  229. // discarded during a cast from ErrorType to NSError in a generic
  230. // function
  231. return RACSignal.createSignal { subscriber in
  232. let selfDisposable = self.observe { event in
  233. switch event {
  234. case let .Next(value):
  235. subscriber.sendNext(value.optional)
  236. case let .Failed(error):
  237. subscriber.sendError(error)
  238. case .Completed:
  239. subscriber.sendCompleted()
  240. case .Interrupted:
  241. break
  242. }
  243. }
  244. return RACDisposable {
  245. selfDisposable?.dispose()
  246. }
  247. }
  248. }
  249. }
  250. // MARK: -
  251. extension RACCommand {
  252. /// Creates an Action that will execute the receiver.
  253. ///
  254. /// - note: The returned Action will not necessarily be marked as executing
  255. /// when the command is. However, the reverse is always true: the
  256. /// RACCommand will always be marked as executing when the action
  257. /// is.
  258. ///
  259. /// - parameters:
  260. /// - file: Current file name.
  261. /// - line: Current line in file.
  262. ///
  263. /// - returns: Action created from `self`.
  264. public func toAction(file: String = #file, line: Int = #line) -> Action<AnyObject?, AnyObject?, NSError> {
  265. let enabledProperty = MutableProperty(true)
  266. enabledProperty <~ self.enabled.toSignalProducer()
  267. .map { $0 as! Bool }
  268. .flatMapError { _ in SignalProducer<Bool, NoError>(value: false) }
  269. return Action(enabledIf: enabledProperty) { input -> SignalProducer<AnyObject?, NSError> in
  270. let executionSignal = RACSignal.`defer` {
  271. return self.execute(input)
  272. }
  273. return executionSignal.toSignalProducer(file, line: line)
  274. }
  275. }
  276. }
  277. extension ActionType {
  278. private var commandEnabled: RACSignal {
  279. return self.enabled.producer
  280. .map { $0 as NSNumber }
  281. .toRACSignal()
  282. }
  283. }
  284. /// Create a `RACCommand` that will execute the action.
  285. ///
  286. /// - note: The returned command will not necessarily be marked as executing
  287. /// when the action is. However, the reverse is always true: the Action
  288. /// will always be marked as executing when the RACCommand is.
  289. ///
  290. /// - returns: `RACCommand` with bound action.
  291. public func toRACCommand<Output: AnyObject, Error>(action: Action<AnyObject?, Output, Error>) -> RACCommand {
  292. return RACCommand(enabled: action.commandEnabled) { input -> RACSignal in
  293. return action
  294. .apply(input)
  295. .toRACSignal()
  296. }
  297. }
  298. /// Creates a RACCommand that will execute the action.
  299. ///
  300. /// - note: The returned command will not necessarily be marked as executing
  301. /// when the action is. However, the reverse is always true: the Action
  302. /// will always be marked as executing when the RACCommand is.
  303. ///
  304. /// - returns: `RACCommand` with bound action.
  305. public func toRACCommand<Output: AnyObject, Error>(action: Action<AnyObject?, Output?, Error>) -> RACCommand {
  306. return RACCommand(enabled: action.commandEnabled) { input -> RACSignal in
  307. return action
  308. .apply(input)
  309. .toRACSignal()
  310. }
  311. }