Post

Replies

Boosts

Views

Activity

How to exit from `RunLoop`
I'm subclassing InputStream from iOS Foundation SDK for my needs. I need to implement functionality that worker thread can sleep until data appear in the stream. The test I'm using to cover the functionality is below: func testStreamWithRunLoop() { let inputStream = BLEInputStream() // custom input stream subclass inputStream.delegate = self let len = Int.random(in: 0..<100) let randomData = randData(length: len) // random data generation let tenSeconds = Double(10) let oneSecond = TimeInterval(1) runOnBackgroundQueueAfter(oneSecond) { inputStream.accept(randomData) // input stream receives the data } let dateInFuture = Date(timeIntervalSinceNow: tenSeconds) // time in 10 sec inputStream.schedule(in: .current, forMode: RunLoop.Mode.default) // RunLoop.current.run(until: dateInFuture) // wait for data appear in input stream XCTAssertTrue(dateInFuture.timeIntervalSinceNow > 0, "Timeout. RunLoop didn't exit in 1 sec. ") } Here it is the overriden methods of InputStream public override func schedule(in aRunLoop: RunLoop, forMode mode: RunLoop.Mode) { self.runLoop = aRunLoop // save RunLoop object var context = CFRunLoopSourceContext() // make context self.runLoopSource = CFRunLoopSourceCreate(nil, 0, &context) // version 0 CFRunLoopSource let cfloopMode: CFRunLoopMode = CFRunLoopMode(mode as CFString) CFRunLoopAddSource(aRunLoop.getCFRunLoop(), self.runLoopSource!, cfloopMode) } public func accept(_ data: Data) { guard data.count > 0 else { return } self.data += data delegate?.stream?(self, handle: .hasBytesAvailable) if let runLoopSource { CFRunLoopSourceSignal(runLoopSource) } if let runLoop { CFRunLoopWakeUp(runLoop.getCFRunLoop()) } } But calling CFRunLoopSourceSignal(runLoopSource) and CFRunLoopWakeUp(runLoop.getCFRunLoop()) not get exit from runLoop. Runloop exits after 10 seconds. [![Test is failing][1]][1] Does anybody know where I'm mistaking ? Thanks all! PS: [2]: Here the Xcode project on GitHub
1
0
928
Jan ’23