Hello,i want to find all open mDNS services with the new NWBrowser. With the NetServiceBrowser i got all Services by searching for this type: "_services._dns-sd._udp." but with the NWBrowser i dont get anything. if i search for a specific type like http or companion link i find some devices. How can i get all services with the NWBrowser ? Or is this not possible due to new data collection guidelines ? I tried it in a Playgroundimport Network
let parameter = NWParameters()
parameter.includePeerToPeer = true
let browser = NWBrowser(for: .bonjour(type: "_services._dns-sd._udp.", domain: nil), using: parameter)
browser.stateUpdateHandler = { state in
switch state {
case .ready:
print("ready")
case .failed(let error):
print("error:", error.localizedDescription)
default:
break
}
}
browser.browseResultsChangedHandler = { result, changed in
result.forEach { device in
print(device.endpoint)
print(device.metadata)
}
}
browser.start(queue: .main)
PlaygroundPage.current.needsIndefiniteExecution = true
Post
Replies
Boosts
Views
Activity
Hi Guys,i tried with the final Xcode 11 Version to generate a .xcframework from my framework but it will not work. I successfully generated the .xcframework like apple showed us on WWDC. But when i import the framework in a sample projekt, it throws the error: "Failed to load module ..." if i try to import it. And there are lot of errors from "arm64-apple-ios.swiftinterface". It's the same error for all public protocols, enums, structs-> "... is not a member type of..."This is the interface file where the errors appear and for every FastSocket.Struct, FastSocket.Protocol.. -> for example: "MessageProtocol is not a member type of FastSocket". I dont have any idea why this happen 😟. The Things are all public and the module works like expected. but not as xcframework 😟// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.1 (swiftlang-1100.0.270.13 clang-1100.0.33.7)
// swift-module-flags: -target arm64-apple-ios13.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name FastSocket
import CryptoKit
import Foundation
import Network
import Swift
extension Data : FastSocket.MessageProtocol {
}
public protocol FastSocketProtocol : AnyObject {
var on: FastSocket.FastSocketCallback { get set }
var parameters: FastSocket.TransferParameters { get set }
init(host: Swift.String, port: Swift.UInt16, type: FastSocket.TransferType)
func connect()
func disconnect()
func send<T>(message: T) where T : FastSocket.MessageProtocol
}
public struct FastSocketCallback {
public var ready: () -> Swift.Void
public var close: () -> Swift.Void
public var message: (FastSocket.MessageProtocol) -> Swift.Void
public var bytes: (FastSocket.ByteCountResult) -> Swift.Void
public var error: (Swift.Error?) -> Swift.Void
}
public protocol MessageTypeProtocol {
}
public protocol MessageProtocol {
}
public enum ByteCountResult {
case input(Swift.Int)
case output(Swift.Int)
}
extension String : FastSocket.MessageProtocol {
}
public enum TransferType {
case tcp
case tls
public static func == (a: FastSocket.TransferType, b: FastSocket.TransferType) -> Swift.Bool
public var hashValue: Swift.Int {
get
}
public func hash(into hasher: inout Swift.Hasher)
}
public class FastSocket : FastSocket.FastSocketProtocol {
public var on: FastSocket.FastSocketCallback
public var parameters: FastSocket.TransferParameters
required public init(host: Swift.String, port: Swift.UInt16, type: FastSocket.TransferType = .tcp)
public func connect()
public func disconnect()
public func send<T>(message: T) where T : FastSocket.MessageProtocol
@objc deinit
}
public struct TransferParameters {
public var acceptLocalOnly: Swift.Bool
public var allowFastOpen: Swift.Bool
public var preferNoProxies: Swift.Bool
public var prohibitedInterfaceTypes: [Network.NWInterface.InterfaceType]
public var prohibitExpensivePaths: Swift.Bool
public var requiredInterfaceType: Network.NWInterface.InterfaceType
public var serviceClass: Network.NWParameters.ServiceClass
public var multipathServiceType: Network.NWParameters.MultipathServiceType
}
public enum FastSocketError : Swift.Int, Swift.Error {
case none
case emptyHost
case handshakeInitializationFailed
case handshakeVerificationFailed
case timeoutError
case networkUnreachable
case sendFailed
case sendToEarly
case socketClosed
case socketUnexpectedClosed
case writeBeforeClear
case parsingFailure
case zeroData
case readBufferIssue
case readBufferOverflow
case writeBufferOverflow
case unknownOpcode
public typealias RawValue = Swift.Int
public init?(rawValue: Swift.Int)
public var rawValue: Swift.Int {
get
}
}
extension FastSocketError {
public static var errorDomain: Swift.String {
get
}
public var errorCode: Swift.Int {
get
}
public var errorUserInfo: [Swift.String : Swift.String] {
get
}
}
extension FastSocket.TransferType : Swift.Equatable {}
extension FastSocket.TransferType : Swift.Hashable {}
extension FastSocket.FastSocketError : Swift.Equatable {}
extension FastSocket.FastSocketError : Swift.Hashable {}
extension FastSocket.FastSocketError : Swift.RawRepresentable {}i generated it with the following commands and i also set the Build Library for Distribution to Yesxcodebuild archive -scheme FastSocket -destination generic/platform=iOS -archivePath ./FastSocket.xcarchive SKIP_INSTALL=NO BUILD_LIBRARIES_FOR_DISTRIBUTION=YESxcodebuild -create-xcframework -framework FastSocket.xcarchive/Products/Library/Frameworks/FastSocket.framework -output FastSocket.xcframework
Hi Guy's
I have trouble creating a WebSocket based Connection by using direct Network.framework's NWConnection.
And I don't want to use URLSessions Way!
I Watched the Apple Keynote and it's not working for me.
I'm trying to connect to a public WebSocket Echo Server.
I put the code in a simple playground. Maybe some of you can light me up and explain what is wrong here 'cause i'm not seeing any issue ?!
Thanks and best regards
Vinz
import UIKit
import Network
import PlaygroundSupport
let parameters = NWParameters.tls
let options = NWProtocolWebSocket.Options()
parameters.defaultProtocolStack.applicationProtocols.insert(options, at: 0)
let connection = NWConnection(host: .init("wss://echo.websocket.org/"), port: .https, using: parameters)
connection.stateUpdateHandler = { state in
switch state {
case .ready:
print("connection ready")
case .failed(let error):
print("connection failed with:", error)
default:
break
}
}
print("start")
connection.start(queue: .main)
PlaygroundPage.current.needsIndefiniteExecution = true
Dear Girls, Guys and Engineers.
I'm currently building a Home Network Scanner App for People which want to know which Bonjour Devices are in her/his Home Network environment. From an older Question I got the answer, that I need an Entitlement to do this.
I started to work on the App and requested the Multicast Entitlement from Apple. They gave me the Entitlement for my App and now I'm trying to discover all devices in my Home Network but I got stuck and need Help.
I only test direct on device, like the recommendation. I also verified that my app is build with the multicast entitlement there where no problems. My problem is now, that is still not possible to discover all Bonjour services in my Home Network with the Help of the NWBrowser.
Can you please help me to make it work ?
I tried to scan for the generic service type:
let browser = NWBrowser(for: .bonjour(type: "_services._dns-sd._udp.", domain: nil), using: .init())
but this is still not working even tough I have the entitlement and the app was verified that the entitlement is correctly enabled
if I scan for this service type, I got the following error:
[browser] nw_browser_fail_on_dns_error_locked [B1] Invalid meta query type specified. nw_browser_start_dns_browser_locked failed: BadParam(-65540)
So what's the correct way now to find all devices in the home network ?
Thank you and best regards
Vinz
Hello
I'm currently working on a new gui in my App and I wanted to use the new Swift Charts Framework. It's very beautiful but I'm struggling with performance here. I want to draw a LineMark in realtime. I have code that create me a point every 25ms over a runtime of about 10 seconds. So I have round about 400 Samples which should drawn in realtime to the Chart so I can see the LineMark being drawn.
On a first try I used a Binding to the Chart to update the Chart and after 2-3 seconds the ui becomes unresponsive and started lagging. I'm currently using an ObservableObject and the .drawingGroup modifier to improve the Performance. This Helps but it's not perfect.
Is there a better way to increase the Performance or what's the way to have a realtime drawing line graph?
Here's the Code I use:
struct ChartView: View {
@ObservedObject public var model = FNMeasurementModel()
private let gradient = LinearGradient(gradient: Gradient (colors: [.mint.opacity(0.1),.mint.opacity(0.0)]), startPoint: .top, endPoint: .bottom)
var body: some View {
Chart() {
ForEach(model.data) { item in
LineMark(
x: .value("Ratio", item.ratio ?? .zero),
y: .value("Speed", item.speed ?? .zero)
)
.interpolationMethod(.catmullRom)
.foregroundStyle(.mint)
AreaMark(
x: .value("Ratio", item.ratio ?? .zero),
y: .value("Speed", item.speed ?? .zero)
)
.foregroundStyle(gradient)
}
}
.chartXAxis{
AxisMarks(position: .bottom, values: stride(from: 0, to: 1.0, by: 0.2).map { $0 })
}
.chartXScale(domain: 0...1.0)
.chartYScale(domain: 0...100)
.frame(height: 100)
.padding(.vertical, 5)
}
}
The ObservableObject
class FNMeasurementModel: ObservableObject {
@Published public var data: [FNMeasurementResult] = []
func append(_ sample: FNMeasurementResult) -> Void { data.append(sample) }
func reset() -> Void { data.removeAll() }
}
My Result Type
public class FNMeasurementResult: Identifiable {
public var id: UUID = UUID()
public var ratio: Double?
public var speed: Double?
public init(speed: Double? = nil, ratio: Double? = nil) {
self.ratio = ratio
self.speed = speed
}
}
I have built an application to measure network throughput using Network.framework. Since the Sonoma Update, I've encountered some strange performance issues with this framework. I use the Loopback Channel by running the server on my Mac itself, which is written in Golang. Before the update, performance was not an issue. After the update, however, the throughput fluctuates significantly.
I started to investigate, I use the following function to parse the data:
connection.receive(minimumIncompleteLength: 1, maximumLength: 32768) {
// My frame parsing code
}
When I use a higher maximumLength, for example, 65536 bytes, it starts to fluctuate, and the received message size for parsing varies between 2.6 Mbytes and 7 Mbytes. However, if the maximumLength is 32768 or lower, and the message size is smaller or larger than this range, then the performance is as expected.
To further isolate the issue, I forced the server to just send messages and removed my frame parsing code, ensuring that the problem is not related to this. This behavior is very peculiar, and I'm unsure how to fix it. Are there others who have experienced similar performance problems? It's worth noting that this issue occurs only with downstream performance, not with upstream.
I've encountered a weird issue with the new Map for iOS 17. In my list, which includes a MapView among other elements, I've observed that with the new initializer, the top and bottom bars are persistently displayed. They don't hide and only appear when scrolling, as they should. This problem doesn't occur with the old, now-deprecated initializer. To illustrate this, I have two screenshots: one with the map enabled and the other with the map disabled, demonstrating the issue.
Here is also my new Map code:
struct MapListRowView: View {
@Binding internal var location: LocationModel
@State internal var user: Bool = true
private var position: CLLocationCoordinate2D { .init(latitude: location.latitude, longitude: location.longitude) }
private var isPad: Bool { UIDevice.current.userInterfaceIdiom == .pad ? true : false }
var body: some View {
Map(bounds: .init(minimumDistance: 1250)) {
if user { UserAnnotation() }
Annotation("", coordinate: position) {
ZStack {
Circle().fill().foregroundColor(.white).padding(1)
Image(systemName: "mappin.circle.fill")
.resizable()
.foregroundColor(.indigo)
}.frame(width: 20, height: 20).opacity(user ? .zero : 1.0)
}
}
.frame(height: isPad ? 200 : 100)
.cornerRadius(8)
.listRowInsets(.init(top: -5, leading: .zero, bottom: -5, trailing: .zero))
.padding(.vertical, 5)
.disabled(true)
}
}
Hello,
im currently rewriting my entire network stuff to swift concurrency. I have a Swift Package which contains the NWConnection with my custom framing protocol. So Network framework does not support itself concurrency so I build an api around that. To receive messages I used an AsyncThrowingStream and it works like that:
let connection = MyNetworkFramework(host: "example.org")
Task {
await connection.start()
for try await result in connection.receive() {
// do something with result
}
}
that's pretty neat and I like it a lot but now things got tricky. in my application I have up to 10 different tcp streams I open up to handle connection stuff. so with my api change every tcp connection runs in it's own task like above and I have no idea how to handle the possible errors from the .receive() func inside the tasks.
First my idea was to use a ThrowingTaskGroup for that and I think that will work but biggest problem is that I initially start with let's say 4 tcp connections and I need the ability to add additional ones later if I need them. so it seems not possible to add a Task afterwards to the ThrowingTaskGroup.
So what's a good way to handle a case like that?
i have an actor which handles everything in it's isolated context and basically I just need let the start func throw if any of the Tasks throw I open up. Here is a basic sample of how it's structured.
Thanks Vinz
internal actor MultiConnector {
internal var count: Int { connections.count }
private var connections: [ConnectionsModel] = []
private let host: String
private let port: UInt16
private let parameters: NWParameters
internal init(host: String, port: UInt16, parameters: NWParameters) {
self.host = host
self.port = port
self.parameters = parameters
}
internal func start(count: Int) async throws -> Void {
guard connections.isEmpty else { return }
guard count > .zero else { return }
try await sockets(from: count)
}
internal func cancel() -> Void {
guard !connections.isEmpty else { return }
for connection in connections { connection.connection.cancel() }
connections.removeAll()
}
internal func sockets(from count: Int) async throws -> Void {
while connections.count < count { try await connect() }
}
}
// MARK: - Private API -
private extension MultiConnector {
private func connect() async throws -> Void {
let uuid = UUID(), connection = MyNetworkFramework(host: host, port: port, parameters: parameters)
connections.append(.init(id: uuid, connection: connection))
let task = Task { [weak self] in guard let self else { return }; try await stream(connection: connection, id: uuid) }
try await connection.start(); await connection.send(message: "Sample Message")
// try await task.value <-- this does not work because stream runs infinite until i cancel it (that's expected and intended but it need to handle if the stream throws an error)
}
private func stream(connection: MyNetworkFramework, id: UUID) async throws -> Void {
for try await result in connection.receive() {
if case .message(_) = result { await connection.send(message: "Sample Message") }
// ... more to handle
}
}
}