@@ -78,6 +78,7 @@ open class RunLoop: NSObject {
78
78
}
79
79
}
80
80
81
+ @available ( * , deprecated, message: " Directly accessing the run loop may cause your code to not become portable in the future. " )
81
82
open func getCFRunLoop( ) -> CFRunLoop {
82
83
return _cfRunLoop
83
84
}
@@ -208,12 +209,178 @@ extension RunLoop {
208
209
}
209
210
}
210
211
211
- // SPI for XCTest
212
- #if os(Windows)
212
+ // These exist as SPI for XCTest for now. Do not rely on their contracts or continued existence.
213
+
213
214
extension RunLoop {
214
- public func _stop( ) {
215
- CFRunLoopStop ( getCFRunLoop ( ) )
216
- }
215
+ @available ( * , deprecated, message: " For XCTest use only. " )
216
+ public func _stop( ) {
217
+ CFRunLoopStop ( getCFRunLoop ( ) )
218
+ }
219
+
220
+ @available ( * , deprecated, message: " For XCTest use only. " )
221
+ public func _observe( _ activities: _Activities , in mode: RunLoop . Mode = . default, repeats: Bool = true , order: Int = 0 , handler: @escaping ( _Activity ) -> Void ) -> _Observer {
222
+ let observer = _Observer ( activities: activities, repeats: repeats, order: order, handler: handler)
223
+ CFRunLoopAddObserver ( self . getCFRunLoop ( ) , observer. cfObserver, mode. _cfStringUniquingKnown)
224
+ return observer
225
+ }
226
+
227
+ @available ( * , deprecated, message: " For XCTest use only. " )
228
+ public func _observe( _ activity: _Activity , in mode: RunLoop . Mode = . default, repeats: Bool = true , order: Int = 0 , handler: @escaping ( _Activity ) -> Void ) -> _Observer {
229
+ return _observe ( _Activities ( activity) , in: mode, repeats: repeats, order: order, handler: handler)
230
+ }
231
+
232
+ @available ( * , deprecated, message: " For XCTest use only. " )
233
+ public func _add( _ source: _Source , forMode mode: RunLoop . Mode ) {
234
+ CFRunLoopAddSource ( _cfRunLoop, source. cfSource, mode. _cfStringUniquingKnown)
235
+ }
236
+
237
+ @available ( * , deprecated, message: " For XCTest use only. " )
238
+ open func _remove( _ source: _Source , for mode: RunLoop . Mode ) {
239
+ CFRunLoopRemoveSource ( _cfRunLoop, source. cfSource, mode. _cfStringUniquingKnown)
240
+ }
217
241
}
218
- #endif
219
242
243
+ extension RunLoop {
244
+ @available ( * , deprecated, message: " For XCTest use only. " )
245
+ public enum _Activity : UInt {
246
+ // These must match CFRunLoopActivity.
247
+ case entry = 0
248
+ case beforeTimers = 1
249
+ case beforeSources = 2
250
+ case beforeWaiting = 32
251
+ case afterWaiting = 64
252
+ case exit = 128
253
+ }
254
+
255
+ @available ( * , deprecated, message: " For XCTest use only. " )
256
+ public struct _Activities : OptionSet {
257
+ public var rawValue : UInt
258
+ public init ( rawValue: UInt ) {
259
+ self . rawValue = rawValue
260
+ }
261
+
262
+ public init ( _ activity: _Activity ) {
263
+ self . rawValue = activity. rawValue
264
+ }
265
+
266
+ public static let entry = _Activities ( rawValue: _Activity. entry. rawValue)
267
+ public static let beforeTimers = _Activities ( rawValue: _Activity. beforeTimers. rawValue)
268
+ public static let beforeSources = _Activities ( rawValue: _Activity. beforeSources. rawValue)
269
+ public static let beforeWaiting = _Activities ( rawValue: _Activity. beforeWaiting. rawValue)
270
+ public static let afterWaiting = _Activities ( rawValue: _Activity. afterWaiting. rawValue)
271
+ public static let exit = _Activities ( rawValue: _Activity. exit. rawValue)
272
+ public static let allActivities = _Activities ( rawValue: 0x0FFFFFFF )
273
+ }
274
+
275
+ @available ( * , deprecated, message: " For XCTest use only. " )
276
+ public class _Observer {
277
+ fileprivate let cfObserver : CFRunLoopObserver
278
+
279
+ fileprivate init ( activities: _Activities , repeats: Bool , order: Int , handler: @escaping ( _Activity ) -> Void ) {
280
+ self . cfObserver = CFRunLoopObserverCreateWithHandler ( kCFAllocatorSystemDefault, CFOptionFlags ( activities. rawValue) , repeats, CFIndex ( order) , { ( cfObserver, cfActivity) in
281
+ guard let activity = _Activity ( rawValue: UInt ( cfActivity. rawValue) ) else { return }
282
+ handler ( activity)
283
+ } )
284
+ }
285
+
286
+ public func invalidate( ) {
287
+ CFRunLoopObserverInvalidate ( cfObserver)
288
+ }
289
+
290
+ public var order : Int {
291
+ Int ( CFRunLoopObserverGetOrder ( cfObserver) )
292
+ }
293
+
294
+ public var isValid : Bool {
295
+ CFRunLoopObserverIsValid ( cfObserver)
296
+ }
297
+
298
+ deinit {
299
+ invalidate ( )
300
+ }
301
+ }
302
+
303
+ @available ( * , deprecated, message: " For XCTest use only. " )
304
+ open class _Source : NSObject {
305
+ fileprivate var cfSource : CFRunLoopSource !
306
+
307
+ public init ( order: Int = 0 ) {
308
+ super. init ( )
309
+
310
+ var context = CFRunLoopSourceContext (
311
+ version: 0 ,
312
+ info: Unmanaged . passUnretained ( self ) . toOpaque ( ) ,
313
+ retain: nil ,
314
+ release: nil ,
315
+ copyDescription: { ( info) -> Unmanaged < CFString > ? in
316
+ let me = Unmanaged < _Source > . fromOpaque ( info!) . takeUnretainedValue ( )
317
+ return . passRetained( String ( describing: me) . _cfObject)
318
+ } ,
319
+ equal: { ( infoA, infoB) in
320
+ let a = Unmanaged < _Source > . fromOpaque ( infoA!) . takeUnretainedValue ( )
321
+ let b = Unmanaged < _Source > . fromOpaque ( infoB!) . takeUnretainedValue ( )
322
+ return a == b ? true : false
323
+ } ,
324
+ hash: { ( info) -> CFHashCode in
325
+ let me = Unmanaged < _Source > . fromOpaque ( info!) . takeUnretainedValue ( )
326
+ return CFHashCode ( me. hashValue)
327
+ } ,
328
+ schedule: { ( info, cfRunLoop, cfRunLoopMode) in
329
+ let me = Unmanaged < _Source > . fromOpaque ( info!) . takeUnretainedValue ( )
330
+ var mode : RunLoop . Mode = . default
331
+ if let cfRunLoopMode = cfRunLoopMode {
332
+ mode = RunLoop . Mode ( rawValue: cfRunLoopMode. _swiftObject)
333
+ }
334
+
335
+ me. didSchedule ( in: mode)
336
+ } ,
337
+ cancel: { ( info, cfRunLoop, cfRunLoopMode) in
338
+ let me = Unmanaged < _Source > . fromOpaque ( info!) . takeUnretainedValue ( )
339
+ var mode : RunLoop . Mode = . default
340
+ if let cfRunLoopMode = cfRunLoopMode {
341
+ mode = RunLoop . Mode ( rawValue: cfRunLoopMode. _swiftObject)
342
+ }
343
+
344
+ me. didCancel ( in: mode)
345
+ } ,
346
+ perform: { ( info) in
347
+ let me = Unmanaged < _Source > . fromOpaque ( info!) . takeUnretainedValue ( )
348
+ me. perform ( )
349
+ } )
350
+
351
+ self . cfSource = CFRunLoopSourceCreate ( kCFAllocatorSystemDefault, CFIndex ( order) , & context)
352
+ }
353
+
354
+ open func didSchedule( in mode: RunLoop . Mode ) {
355
+ // Override me.
356
+ }
357
+
358
+ open func didCancel( in mode: RunLoop . Mode ) {
359
+ // Override me.
360
+ }
361
+
362
+ open func perform( ) {
363
+ // Override me.
364
+ }
365
+
366
+ open func invalidate( ) {
367
+ CFRunLoopSourceInvalidate ( cfSource)
368
+ }
369
+
370
+ open var order : Int {
371
+ Int ( CFRunLoopSourceGetOrder ( cfSource) )
372
+ }
373
+
374
+ open var isValid : Bool {
375
+ CFRunLoopSourceIsValid ( cfSource)
376
+ }
377
+
378
+ open func signal( ) {
379
+ CFRunLoopSourceSignal ( cfSource)
380
+ }
381
+
382
+ deinit {
383
+ invalidate ( )
384
+ }
385
+ }
386
+ }
0 commit comments