Migration Guide
API Mapping
| Legacy API |
Network.framework |
socket() + connect() |
NWConnection |
send() / recv() |
connection.send() / receive() |
bind() + listen() |
NWListener |
getaddrinfo() |
Use hostname in NWEndpoint.Host() |
SCNetworkReachability |
.waiting state |
CFSocket / NSStream |
NWConnection |
NSNetService |
NWBrowser |
From BSD Sockets
// WRONG - Blocks main thread
int sock = socket(AF_INET, SOCK_STREAM, 0);
connect(sock, &addr, addrlen); // BLOCKS
// CORRECT
let connection = NWConnection(host: "example.com", port: 443, using: .tls)
connection.stateUpdateHandler = { [weak self] state in
if case .ready = state { self?.sendData() }
}
connection.start(queue: .main) // Non-blocking
From SCNetworkReachability
// WRONG - Race condition
if SCNetworkReachabilityGetFlags(reachability, &flags) {
if flags.contains(.reachable) {
connection.start() // Network may change!
}
}
// CORRECT - Use waiting state
connection.stateUpdateHandler = { state in
switch state {
case .waiting: showStatus("Waiting for network...")
case .ready: startCommunication()
case .failed: showError("Failed")
default: break
}
}
From getaddrinfo
// WRONG - Misses Happy Eyeballs, proxies
getaddrinfo("example.com", "443", &hints, &results);
// CORRECT - Framework handles DNS, IPv4/IPv6 racing
let connection = NWConnection(
host: NWEndpoint.Host("example.com"), // Hostname, not IP
port: 443, using: .tls
)
From URLSession StreamTask
// Before
let task = URLSession.shared.streamTask(withHostName: "example.com", port: 443)
task.write(data, timeout: 10) { _ in }
// After (iOS 26+)
let connection = NetworkConnection(to: .hostPort(host: "example.com", port: 443)) { TLS() }
try await connection.send(data)
From NWConnection to NetworkConnection
| NWConnection |
NetworkConnection |
stateUpdateHandler = {} |
for await state in states |
send(content:completion:) |
try await send() |
receive(min:max:completion:) |
try await receive() |
[weak self] everywhere |
No weak self needed |
| Manual JSON |
Coder(Type.self, using: .json) |
// Before
connection.stateUpdateHandler = { [weak self] state in
if case .ready = state { self?.sendData() }
}
// After
Task {
for await state in connection.states {
if case .ready = state {
try await connection.send(data)
}
}
}
Migration Checklist