I have an issue that causes multiple instances of the push provider to be initialized. And I'd like to ask you what could trigger the instantiation NEAppPushProvider subclass. It seems like it's being triggered excessively. If there's documentation that I have overlooked then just show it to me and I'll be on my way.
Here's the details. But really all I want to know is why is my subclass for NEAppPushProvider keeps getting initialized. If you can answer me that than maybe all these details don't really matter but here they are.
Here's why I believe there's multiple push provider. I see logs for my push provider initializing but I don't see it de-initializing. I also see redundant logs showing multiple instances trying to log into my server. Each time it initializes, an additional log is added for trying to log into my server.
In the app, the system saves it's configuration shortly after initialization, after saving and loading the push configuration, the app doesn't touch config.
Meanwhile in the extension, after 8 or so hours, the extension starts creating a new instance of the push provider. Then a few hours later it does it again. And again. Until the watch dog kills us for wasting too much CPU.
Normally on a fresh install, I'll observe turning off the wifi to call stop on the push provider and later have the push provider de-initialize.
The extension maintains a socket connection to the server, the server can send it messages to display push notifications. The software runs on hospital networks, which will not have access to the internet. It seems like the connection to the server is stable from the logs. I don't detect any disconnections. I'll check with the server to confirm.
In the app I call removeFromPreferences to clear out any extensions before logging in/saving push configurations. And I call saveToPreferences on the NEAppPushManager. I do this to make sure I don't have more than one push configuration saved at one time. I also have many logs looking out for this. I used the sample code from apple as the basis of the my own Push Manager. I can post code if you deem it necessary.
Hope to here from you soon. Thank you.
Post
Replies
Boosts
Views
Activity
Hello I'm a beginner to Swift Concurrency and have run into an issue with AsyncStream. I've run into a situation that causes an observing of a for loop to receiving a values from an AsyncStream.
At the bottom is the code that you can copy it into a Swift Playground and run.
The code is supposed to mock a system that has a service going through a filter to read and write to a connection.
Here is a log of the prints
🙈🫴 setupRTFAsyncWrites Start
⬅️ Pretend to write 0
➡️ Pretend to read 0
feed into filter 0
yield write data 1
🙈🫴 setupRTFAsyncWrites: write(1 bytes)
⬅️🙈🫴 Async Event: dataToDevice: 1 bytes
⬅️ Pretend to write 1
➡️ Pretend to read 1
feed into filter 1
yield write data 2
// here our for loop should have picked up the value sent down the continuation. But instead it just sits here.
Sample that can go into a playground
//: A UIKit based Playground for presenting user interface
import SwiftUI
import PlaygroundSupport
import Combine
import CommonCrypto
import Foundation
class TestConnection {
var didRead: ((Data) -> ()) = { _ in }
var count = 0
init() {
}
func write(data: Data) {
// pretend we sent this to the BT device
print("⬅️ Pretend to write \(count)")
Task {
try await Task.sleep(ms: 200)
print("➡️ Pretend to read \(self.count)")
self.count += 1
// pretend this is a response from the device
self.didRead(Data([0x00]))
}
}
}
enum TestEvent: Sendable {
/// ask some one to write this to the device
case write(Data)
/// the filter is done
case handshakeDone
}
class TestFilter {
var eventsStream: AsyncStream<TestEvent>
var continuation: AsyncStream<TestEvent>.Continuation
private var count = 0
init() {
(self.eventsStream, self.continuation) = AsyncStream<TestEvent>.makeStream(bufferingPolicy: .unbounded)
}
func feed(data: Data) {
print("\tfeed into filter \(count)")
count += 1
if count > 5 {
print("\t✅ handshake done")
self.continuation.yield(.handshakeDone)
return
}
Task {
// data delivered to us by a bluetooth device
// pretend it takes time to process this and then we return with a request to write back to the connection
try await Task.sleep(ms: 200)
print("\tyield write data \(self.count)")
// pretend this is a response from the device
let result = self.continuation.yield(.write(Data([0x11])))
}
}
/// gives the first request to fire to the device for the handshaking sequence
func start() -> Data {
return Data([0x00])
}
}
// Here we facilitate communication between the filter and the connection
class TestService {
private let filter: TestFilter
var task: Task<(), Never>?
let testConn: TestConnection
init(filter: TestFilter) {
self.filter = filter
self.testConn = TestConnection()
self.testConn.didRead = { [weak self] data in
self?.filter.feed(data: data)
}
self.task = Task { [weak self] () in
await self?.setupAsyncWrites()
}
}
func setupAsyncWrites() async {
print("🙈🫴 setupRTFAsyncWrites Start")
for await event in self.filter.eventsStream {
print("\t\t🙈🫴 setupRTFAsyncWrites: \(event)")
guard case .write(let data) = event else {
print("\t\t🙈🫴 NOT data to device: \(event)")
continue
}
print("\t\t⬅️🙈🫴 Async Event: dataToDevice: \(data)")
self.testConn.write(data: data)
} // for
// This shouldn't end
assertionFailure("This should not end")
}
public func handshake() async {
let data = self.filter.start()
self.testConn.write(data: data)
await self.waitForHandshakedone()
}
private func waitForHandshakedone() async {
for await event in self.filter.eventsStream {
if case .handshakeDone = event {
break
}
continue
}
}
}
Task {
let service = TestService(filter: TestFilter())
await service.handshake()
print("Done")
}
/*
This is what happens:
🙈🫴 setupRTFAsyncWrites Start
⬅️ Pretend to write 0
➡️ Pretend to read 0
feed into filter 0
yield write data 1
🙈🫴 setupRTFAsyncWrites: write(1 bytes)
⬅️🙈🫴 Async Event: dataToDevice: 1 bytes
⬅️ Pretend to write 1
➡️ Pretend to read 1
feed into filter 1
yield write data 2
// It just stops here, the `for` loop in setupAsyncWrites() should have picked up the event sent down the continuation after "yield write data 2"
// It should say
🙈🫴 setupRTFAsyncWrites: write(1 bytes)
⬅️🙈🫴 Async Event: dataToDevice: 1 bytes
*/
extension Task<Never, Never> {
public static func sleep(ms duration: UInt64) async throws {
try await Task.sleep(nanoseconds: 1_000_000 * duration)
}
}
Every time I press return/enter or space in the comments code completion suggests the expect() from the Nimble framework
https://stackoverflow.com/questions/69442228/xcode-13-autocompletes-text-in-comments
I tried installing XCode 13.1 over XCode 13.0 to no avail.
This really makes writing comments more of a chore than it has to be.