When creating a folder in the code, it prompts that the file creation is successful, but when the folder does not exist in the "Download Container" file, do you have any permissions when creating the folder in VisionOS?
static func getFileManager() -> URL {
let documentsDirectory = FileManager.default.urls(
for: .documentDirectory,
in: .userDomainMask
).first!
return documentsDirectory.appendingPathComponent("SGKJ_LIBRARY")
}
static func createFileLibrary() {
let folderUrl = getFileManager()
let fileManager = FileManager.default
do {
try fileManager.createDirectory(
at: folderUrl,
withIntermediateDirectories: true,
attributes: nil
)
print("Folder created successfully: \(folderUrl.path)")
} catch {
print("Failed to create folder: \(error.localizedDescription)")
}
}
Foundation
RSS for tagAccess essential data types, collections, and operating-system services to define the base layer of functionality for your app using Foundation.
Posts under Foundation tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hey there! I faced issue in iOS 18 and newer when Spotlight search doesn't show my App in results. In older versions it works. Here is my code:
func configureUserActivitity(with id: String, keywords: [String]) {
let activity = NSUserActivity(activityType: id)
activity.contentAttributeSet = self.defaultAttributeSet
activity.isEligibleForSearch = true
activity.keywords = Set(keywords)
activity.becomeCurrent()
self.userActivity = activity
}
I didn't find any reasons why it doesn't work now. Maybe I should report a bug?
I am using a URLSessionWebSocketTask. When trying to receive messages while the app is backgrounded, the receive() method fails with an NSError where the domain is NSPOSIXErrorDomain and the code is ECONNABORTED. That behavior is good. However, when this happens, the URLSessionWebSocketTask reports a closeCode of invalid, which is supposed to denote that the connection is still open. However, the connection state property is reporting completed. I feel that the closeCode property should be reporting something like abnormalClosure in this case. Either way, this seems like a bug or the documentation is incorrect.
Hi there,
I uploaded an update bundle for the posted app, but I got a rejection message.
ITMS-90048: This bundle is invalid - Your archive contains paths that are not allowed: [._Symbols]
The XCode version I'm using is 16.2, and I've been trying to find a route using Run Script and Finder, but I don't know what the hell it is about.
Does anybody know what could cause this issue?
Any help would be appreciated.
Thanks.
We have an enterprise mac OS X application which uses the UserDefaults to store the onboarding states. The strange part here is that the newly installed mac OS X app is still be able to access the UserDefalus data of removed application. Because of this, the application never becomes as a freshly installed app. Is it any limitation to Enterprise mac OS X apps? Could you please provide us the resolution for this issue.
We are getting a crash _dispatch_assert_queue_fail when the cancellationHandler on NSProgress is called.
We do not see this with iOS 17.x, only on iOS 18. We are building in Swift 6 language mode and do not have any compiler warnings.
We have a type whose init looks something like this:
init(
request: URLRequest,
destinationURL: URL,
session: URLSession
) {
progress = Progress()
progress.kind = .file
progress.fileOperationKind = .downloading
progress.fileURL = destinationURL
progress.pausingHandler = { [weak self] in
self?.setIsPaused(true)
}
progress.resumingHandler = { [weak self] in
self?.setIsPaused(false)
}
progress.cancellationHandler = { [weak self] in
self?.cancel()
}
When the progress is cancelled, and the cancellation handler is invoked. We get the crash. The crash is not reproducible 100% of the time, but it happens significantly often. Especially after cleaning and rebuilding and running our tests.
* thread #4, queue = 'com.apple.root.default-qos', stop reason = EXC_BREAKPOINT (code=1, subcode=0x18017b0e8)
* frame #0: 0x000000018017b0e8 libdispatch.dylib`_dispatch_assert_queue_fail + 116
frame #1: 0x000000018017b074 libdispatch.dylib`dispatch_assert_queue + 188
frame #2: 0x00000002444c63e0 libswift_Concurrency.dylib`swift_task_isCurrentExecutorImpl(swift::SerialExecutorRef) + 284
frame #3: 0x000000010b80bd84 MyTests`closure #3 in MyController.init() at MyController.swift:0
frame #4: 0x000000010b80bb04 MyTests`thunk for @escaping @callee_guaranteed @Sendable () -> () at <compiler-generated>:0
frame #5: 0x00000001810276b0 Foundation`__20-[NSProgress cancel]_block_invoke_3 + 28
frame #6: 0x00000001801774ec libdispatch.dylib`_dispatch_call_block_and_release + 24
frame #7: 0x0000000180178de0 libdispatch.dylib`_dispatch_client_callout + 16
frame #8: 0x000000018018b7dc libdispatch.dylib`_dispatch_root_queue_drain + 1072
frame #9: 0x000000018018bf60 libdispatch.dylib`_dispatch_worker_thread2 + 232
frame #10: 0x00000001012a77d8 libsystem_pthread.dylib`_pthread_wqthread + 224
Any thoughts on why this is crashing and what we can do to work-around it? I have not been able to extract our code into a simple reproducible case yet. And I mostly see it when running our code in a testing environment (XCTest). Although I have been able to reproduce it running an app a few times, it's just less common.
Hi Dev Forums and Quinn "The Eskimo!",
Short version
Is there sample NWConnection code available that behaves in a similar way to the higher level URLSession and URLRequest APIs?
Long version
I have not been able to make this question get past the "sensitive language filter" on the dev forums. I figured it might be 'fool' or 'heck', or the X link, but removing each of those still triggers the sensitive language filter.
Please see this gist:
https://gist.github.com/lzell/8672c26ecb6ee1bb26d3aa3c7d67dd62
Thank you!
Lou Zell
We have identified an issue when using NumberFormatter with the locale set to it_IT. Specifically, when formatting numbers with exactly four integer digits, the grouping separator is not applied: for example, the number is displayed as 4000,00 instead of the expected 4.000,00. This behavior occurs only with four-digit integers; for instance, 40.000,00 is formatted correctly. The issue appears to affect only iOS 18.4 and later versions.
I want decoded my base64 string and want to create image from it.
NSData *data = [NSData dataWithBytes:bpData.rt_wav.data length:sizeof(bpData.rt_wav.data)];
NSMutableString *baseString = [data base64Encoding];
UIImage *image = [UIImage imageWithData:data];
Hi, I work at OneSignal, a third-party SDK, and have the following two crash reports submitted by a client for the same issue. Because the crash originates from our SDK, even if the root cause may be elsewhere, the onus is on our team to try to resolve this crash. Additionally, my information is limited as this is not our own crash report.
I'm trying to figure out why this crash happens and how we can address it within our SDK.
Crash Reported:
Fatal Exception: NSInvalidArgumentException
[NSMutableDictionary __addObject:forKey:]: object cannot be nil
Context:
Our SDK makes a call to [NSUserDefaults(NSUserDefaults) objectForKey:] on the standardUserDefaults and passes in a non-null key. It appears further up the call stack, a null value is being added to a dictionary. I assume this is the innards of how the search list is generated.
Additional Information:
The client states that it seems to happen only once per user and the scale is not extremely high but it is increasing. They are unsure what happened and when. They don't have much information about the devices except it has happened on iOS 18.
Log 1:
0 CoreFoundation 0x2d5fc __exceptionPreprocess
1 libobjc.A.dylib 0x31244 objc_exception_throw
2 CoreFoundation 0x15548 -[NSMutableDictionary __addObject:forKey:]
3 CoreFoundation 0x20850 -[__NSDictionaryM __apply:context:]
4 CoreFoundation 0x54700 ___CFPrefsDeliverPendingKVONotificationsGuts_block_invoke
5 CoreFoundation 0x52988 __CFDictionaryApplyFunction_block_invoke
6 CoreFoundation 0x52524 CFBasicHashApply
7 CoreFoundation 0x21040 CFDictionaryApplyFunction
8 CoreFoundation 0x7a6b0 _CFPrefsDeliverPendingKVONotificationsGuts
9 CoreFoundation 0x777d0 -[_CFXPreferences _deliverPendingKVONotifications]
10 CoreFoundation 0x776ac __108-[_CFXPreferences(SearchListAdditions) withSearchListForIdentifier:container:cloudConfigurationURL:perform:]_block_invoke
11 CoreFoundation 0x5cf24 normalizeQuintuplet
12 CoreFoundation 0x5cd60 -[_CFXPreferences withSearchListForIdentifier:container:cloudConfigurationURL:perform:]
13 CoreFoundation 0x5cc60 -[_CFXPreferences copyAppValueForKey:identifier:container:configurationURL:]
14 CoreFoundation 0x5c8bc _CFPreferencesCopyAppValueWithContainerAndConfiguration
15 Foundation 0xf0dcc -[NSUserDefaults(NSUserDefaults) objectForKey:]
16 OneSignalCore 0xc7c8 -[OneSignalUserDefaults keyExists:] + 61 (OneSignalUserDefaults.m:61)
17 OneSignalCore 0xc8b0 -[OneSignalUserDefaults getSavedBoolForKey:defaultValue:] + 70 (OneSignalUserDefaults.m:70)
18 OneSignalCore 0xbb10 +[OSPrivacyConsentController requiresUserPrivacyConsent] + 59 (OSPrivacyConsentController.m:59)
19 OneSignalCore 0xbc30 +[OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:] + 75 (OSPrivacyConsentController.m:75)
20 OneSignalCore 0x4418 +[OneSignalConfigManager shouldAwaitAppIdAndLogMissingPrivacyConsentForMethod:] + 50 (OneSignalConfigManager.m:50)
21 OneSignalOSCore 0x537c OSOperationRepo.flushDeltaQueue(inBackground:) + 140 (OSOperationRepo.swift:140)
22 OneSignalOSCore 0x4868 closure #1 in OSOperationRepo.pollFlushQueue() + 84 (OSOperationRepo.swift:84)
23 OneSignalOSCore 0x5078 thunk for @escaping @callee_guaranteed @Sendable () -> ()
24 libdispatch.dylib 0x3fa8 _dispatch_client_callout
25 libdispatch.dylib 0x745c _dispatch_continuation_pop
26 libdispatch.dylib 0x1b620 _dispatch_source_latch_and_call
27 libdispatch.dylib 0x1a1e8 _dispatch_source_invoke
28 libdispatch.dylib 0xb42c _dispatch_lane_serial_drain
29 libdispatch.dylib 0xc124 _dispatch_lane_invoke
30 libdispatch.dylib 0x1738c _dispatch_root_queue_drain_deferred_wlh
31 libdispatch.dylib 0x16bd8 _dispatch_workloop_worker_thread
32 libsystem_pthread.dylib 0x3680 _pthread_wqthread
33 libsystem_pthread.dylib 0x1474 start_wqthread
Log 2:
Fatal Exception: NSInvalidArgumentException
0 CoreFoundation 0x2d5fc __exceptionPreprocess
1 libobjc.A.dylib 0x31244 objc_exception_throw
2 CoreFoundation 0x15548 -[NSMutableDictionary __addObject:forKey:]
3 CoreFoundation 0x168f0 __72-[CFPrefsSource mergeIntoDictionary:sourceDictionary:cloudKeyEvaluator:]_block_invoke
4 CoreFoundation 0x23ecc -[__NSFrozenDictionaryM __apply:context:]
5 CoreFoundation 0x4f82c -[CFPrefsSource mergeIntoDictionary:sourceDictionary:cloudKeyEvaluator:]
6 CoreFoundation 0x783b8 -[CFPrefsSearchListSource alreadylocked_getDictionary:]
7 CoreFoundation 0x77dfc -[CFPrefsSearchListSource alreadylocked_copyValueForKey:]
8 CoreFoundation 0x77d30 -[CFPrefsSource copyValueForKey:]
9 CoreFoundation 0x77ce4 __76-[_CFXPreferences copyAppValueForKey:identifier:container:configurationURL:]_block_invoke
10 CoreFoundation 0x77690 __108-[_CFXPreferences(SearchListAdditions) withSearchListForIdentifier:container:cloudConfigurationURL:perform:]_block_invoke
11 CoreFoundation 0x5cf24 normalizeQuintuplet
12 CoreFoundation 0x5cd60 -[_CFXPreferences withSearchListForIdentifier:container:cloudConfigurationURL:perform:]
13 CoreFoundation 0x5cc60 -[_CFXPreferences copyAppValueForKey:identifier:container:configurationURL:]
14 CoreFoundation 0x5c8bc _CFPreferencesCopyAppValueWithContainerAndConfiguration
15 Foundation 0xf0dcc -[NSUserDefaults(NSUserDefaults) objectForKey:]
16 OneSignalCore 0xc7c8 -[OneSignalUserDefaults keyExists:] + 61 (OneSignalUserDefaults.m:61)
17 OneSignalCore 0xcbd8 -[OneSignalUserDefaults getSavedDoubleForKey:defaultValue:] + 107 (OneSignalUserDefaults.m:107)
18 OneSignalFramework 0x8964 +[OneSignal shouldStartNewSession] + 350 (OneSignal.m:350)
19 OneSignalFramework 0xc968 +[OneSignalTracker applicationBecameActive] + 83 (OneSignalTracker.m:83)
20 OneSignalFramework 0xb894 -[OneSignalLifecycleObserver didBecomeActive] + 84 (OneSignalLifecycleObserver.m:84)
......
55 UIKitCore 0x3ee674 -[UIApplication _run]
56 UIKitCore 0x14e88 UIApplicationMain
57 UnityFramework 0x399aef0 -[UnityFramework runUIApplicationMainWithArgc:argv:] + 96 (main.mm:96)
58 ClientsApp 0x412c main + 28 (main.mm:28)
Let’s try calculating one day after "2023/11/04 12:00 New York time".
let timeZone = TimeZone(identifier: "America/New_York")!
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = timeZone
var dateFormatter = DateFormatter()
dateFormatter.timeZone = timeZone
dateFormatter.locale = .init(identifier: "ja_JP")
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .short
var dateComponents = DateComponents()
dateComponents.year = 2023
dateComponents.month = 11
dateComponents.day = 4
dateComponents.hour = 12
// At New York 2023/11/04 12:00
let date1 = calendar.date(from: dateComponents)!
print(dateFormatter.string(from: date1))
// Add 1 day
let date2 = calendar.date(byAdding: .day, value: 1, to: date1)!
print(dateFormatter.string(from: date2))```
The output is:
2023/11/04 12:00
2023/11/05 12:00
Now, let’s try the following—also to get the time one day later:
let date2 = calendar.date(byAdding: .minute, value: 24 * 60, to: date1)!
print(dateFormatter.string(from: date2))
This outputs:
2023/11/04 12:00
2023/11/05 11:00
What's Causing This Difference?
It’s likely due to Daylight Saving Time (DST). But why do we get different results between the first and second examples?
My app started crashing since iOS 18.4 update. Crashes started happening in 18.4 beta and are still happening in the official 18.4 RTM build (22E240). Crash is happening randomly and I cannot reproduce it, but it affects a few percent of users.
As you can see in log, crash happen when NSAttributedString is loading HTML with init(data:options:documentAttributes:) with .html documentType.
Crash-2025-04-02-154720.ips
The current live version of my app is 1.1.0, and I intended to create a new submission version, 1.1.1. However, I accidentally entered it as 1.0.8. In App Store Connect, I couldn't find any button to delete or modify the 1.0.8 version, nor could I add another submission version. As a result, I tried to upload the build for version 1.0.8 via Xcode, but an even worse issue occurred—Xcode displayed an error: "A version 1.1.0 already exists, which is higher than 1.0.8, so the upload path is closed."
I can't update my app now or later, what should I do to fix it?
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
App Store
xcselect
Foundation
I'm trying to schedule a background task that will run on an iPhone and I'm looking into creating a task request using BGProcessingTaskRequest and scheduled it using BGTaskScheduler.shared.submit().
Per earliestBeginDate documentation, this property can be used to specify the earliest time a background task will be launched by OS. All clear here.
However, the question is: how is the value interpreted with respect to timezone ? Is the specified date in device timezone ? Is GMT ? Is something else ?
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags:
iOS
Background Tasks
Foundation
Hello everyone,
I’m experiencing a crash in my iOS application that’s occurring predominantly on devices running iOS 16.6.0. The crash seems to happen on the main thread during a UI operation, specifically within the UIKitCore framework.
Crash Log Summary
Thread 0 Crashed:
0 libsystem_kernel.dylib 0xca4 mach_msg2_trap + 8
1 libsystem_kernel.dylib 0x13b74 mach_msg2_internal + 80
2 libsystem_kernel.dylib 0x13e4c mach_msg_overwrite + 540
3 libsystem_kernel.dylib 0x11e8 mach_msg + 24
4 CoreFoundation 0x79024 __CFRunLoopServiceMachPort + 160
5 CoreFoundation 0x7a250 __CFRunLoopRun + 1208
6 CoreFoundation 0x7f3ec CFRunLoopRunSpecific + 612
7 GraphicsServices 0x135c GSEventRunModal + 164
8 UIKitCore 0x39cf58 -[UIApplication _run] + 888
9 UIKitCore 0x39cbbc UIApplicationMain + 340
10 MyApp 0x24050 main + 51 (AppDelegate.swift:51)
11 ??? 0x1d3594dec (Missing)
I’ve attached the full crash
crashlog.txt
and would appreciate any insights or recommendations on how to resolve this issue.
Hi! I was wondering if anyone else encountered similar issues and what the solution ended up being.
We're encountering weird sign-in issues on our iOS version of our app. It seems like an uninstall and reinstall solves it, but the issue seems to only impact users who underwent the transfer process from one iOS device to another. What I am curious about:
What is copied over from one device to another in this process?
Is there a way outside of owning multiple test devices to replicate this flow?
Our current suspicion is that NSUserDefaults is not being cleared by our app on first start, and that stale data is copied over during this transfer process, breaking the sign-in until a re-install wipes everything properly.
Does it seem like we're on the right track with this assumption, or completely out to lunch?
When I try to implement the new Background Task options in the same way as they show in the WWDC video (on watchOS) likes this:
let config = URLSessionConfiguration.background(withIdentifier: "SESSION_ID")
config.sessionSendsLaunchEvents = true
let session = URLSession(configuration: config)
let response = await withTaskCancellationHandler {
try? await session.data(for: request)
} onCancel: {
let task = session.downloadTask(with: request))
task.resume()
}
I'm receiving the following error:
Terminating app due to uncaught exception 'NSGenericException', reason: 'Completion handler blocks are not supported in background sessions. Use a delegate instead.'
Did I forget something?
We have used ::gethostname to retrieve hostname in our tunnel provider extension and found it returns "localhost" on iOS 17+. So we changed to use [[NSProcessInfo processInfo] hostName]. However it often caused 30+ delay in the extension process on a few devices and always returns "localhost".
The sysdiagnose shows a lot of DNS query logs as below:
default mDNSResponder 2025-03-19 17:15:12.453769 +0800 75281: 0x11ad501 [R80937] DNSServiceCreateConnection START PID[79767](ACExtension)
default mDNSResponder 2025-03-19 17:15:12.453892 +0800 75281: 0x11ad501 [R80938] DNSServiceQueryRecord START -- qname: <mask.hash: 'fNnSAdyuhKXqCny8+neXvw=='>, qtype: PTR, flags: 0x15000, interface index: -1, client pid: 79767 (ACExtension), name hash: 84de01e1
default mDNSResponder 2025-03-19 17:15:12.458395 +0800 75281: 0x11ad501 [R80939] DNSServiceQueryRecord START -- qname: <mask.hash: '2X6qN/YT0yh2psKwrGWokg=='>, qtype: PTR, flags: 0x15000, interface index: 0, client pid: 79767 (ACExtension), name hash: f25c923e
default mDNSResponder 2025-03-19 17:15:12.462924 +0800 75281: 0x11ad501 [R80940] DNSServiceQueryRecord START -- qname: <mask.hash: 'peyRWEblLKbNvcOXPjSeMQ=='>, qtype: PTR, flags: 0x15000, interface index: 0, client pid: 79767 (ACExtension), name hash: 83323cc4
My assumption has always been that [NSApp runModalForWindow:] runs a modal window in NSModalPanelRunLoopMode.
However, while -[NSApplication _doModalLoop:peek:] seems to use NSModalPanelRunLoopMode when pulling out the next event to process via nextEventMatchingMask:untilDate:inMode:dequeue:, the current runloop doesn't seem to be running in that mode, so during -[NSApplication(NSEventRouting) sendEvent:] of the modal-specific event, NSRunLoop.currentRunLoop.currentMode returns kCFRunLoopDefaultMode.
From what I can tell, this means that any event processing code that e.g. uses [NSTimer addTimer:forMode:] based on the current mode will register a timer that will not fire until the modal session ends.
Is this a bug? Or if not, is the correct way to run a modal session something like this?
[NSRunLoop.currentRunLoop performInModes:@[NSModalPanelRunLoopMode] block:^{
[NSApp runModalForWindow:window];
}];
[NSRunLoop.currentRunLoop limitDateForMode:NSModalPanelRunLoopMode];
Alternatively, if the mode of the runloop should stay the same, I've seen suggestions to run modal sessions like this:
NSModalSession session = [NSApp beginModalSessionForWindow:theWindow];
for (;;) {
if ([NSApp runModalSession:session] != NSModalResponseContinue)
break;
[NSRunLoop.currentRunLoop limitDateForMode:NSModalPanelRunLoopMode];
}
[NSApp endModalSession:session];
Which would work around the fact that the timer/callbacks were scheduled in the "wrong" mode. But running NSModalPanelRunLoopMode during a modal session seems a bit scary. Won't that potentially break the modality?
I am trying to convert a simple URLSession request in Swift to using NWConnection. This is because I want to make the request using a Proxy that requires Authentication. I posted this SO Question about using a proxy with URLSession. Unfortunately no one answered it but I found a fix by using NWConnection instead.
Working Request
func updateOrderStatus(completion: @escaping (Bool) -> Void) {
let orderLink = "https://shop.ccs.com/51913883831/orders/f3ef2745f2b06c6b410e2aa8a6135847"
guard let url = URL(string: orderLink) else {
completion(true)
return
}
let cookieStorage = HTTPCookieStorage.shared
let config = URLSessionConfiguration.default
config.httpCookieStorage = cookieStorage
config.httpCookieAcceptPolicy = .always
let session = URLSession(configuration: config)
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", forHTTPHeaderField: "Accept")
request.setValue("none", forHTTPHeaderField: "Sec-Fetch-Site")
request.setValue("navigate", forHTTPHeaderField: "Sec-Fetch-Mode")
request.setValue("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0.1 Safari/605.1.15", forHTTPHeaderField: "User-Agent")
request.setValue("en-US,en;q=0.9", forHTTPHeaderField: "Accept-Language")
request.setValue("gzip, deflate, br", forHTTPHeaderField: "Accept-Encoding")
request.setValue("document", forHTTPHeaderField: "Sec-Fetch-Dest")
request.setValue("u=0, i", forHTTPHeaderField: "Priority")
// make the request
}
Attempted Conversion
func updateOrderStatusProxy(completion: @escaping (Bool) -> Void) {
let orderLink = "https://shop.ccs.com/51913883831/orders/f3ef2745f2b06c6b410e2aa8a6135847"
guard let url = URL(string: orderLink) else {
completion(true)
return
}
let proxy = "resi.wealthproxies.com:8000:akzaidan:x0if46jo-country-US-session-7cz6bpzy-duration-60"
let proxyDetails = proxy.split(separator: ":").map(String.init)
guard proxyDetails.count == 4, let port = UInt16(proxyDetails[1]) else {
print("Invalid proxy format")
completion(false)
return
}
let proxyEndpoint = NWEndpoint.hostPort(host: .init(proxyDetails[0]),
port: NWEndpoint.Port(integerLiteral: port))
let proxyConfig = ProxyConfiguration(httpCONNECTProxy: proxyEndpoint, tlsOptions: nil)
proxyConfig.applyCredential(username: proxyDetails[2], password: proxyDetails[3])
let parameters = NWParameters.tcp
let privacyContext = NWParameters.PrivacyContext(description: "ProxyConfig")
privacyContext.proxyConfigurations = [proxyConfig]
parameters.setPrivacyContext(privacyContext)
let host = url.host ?? ""
let path = url.path.isEmpty ? "/" : url.path
let query = url.query ?? ""
let fullPath = query.isEmpty ? path : "\(path)?\(query)"
let connection = NWConnection(
to: .hostPort(
host: .init(host),
port: .init(integerLiteral: UInt16(url.port ?? 80))
),
using: parameters
)
connection.stateUpdateHandler = { state in
switch state {
case .ready:
print("Connected to proxy: \(proxyDetails[0])")
let httpRequest = """
GET \(fullPath) HTTP/1.1\r
Host: \(host)\r
Connection: close\r
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0.1 Safari/605.1.15\r
Accept-Language: en-US,en;q=0.9\r
Accept-Encoding: gzip, deflate, br\r
Sec-Fetch-Dest: document\r
Sec-Fetch-Mode: navigate\r
Sec-Fetch-Site: none\r
Priority: u=0, i\r
\r
"""
connection.send(content: httpRequest.data(using: .utf8), completion: .contentProcessed({ error in
if let error = error {
print("Failed to send request: \(error)")
completion(false)
return
}
// Read data until the connection is complete
self.readAllData(connection: connection) { finalData, readError in
if let readError = readError {
print("Failed to receive response: \(readError)")
completion(false)
return
}
guard let data = finalData else {
print("No data received or unable to read data.")
completion(false)
return
}
if let body = String(data: data, encoding: .utf8) {
print("Received \(data.count) bytes")
print("\n\nBody is \(body)")
completion(true)
} else {
print("Unable to decode response body.")
completion(false)
}
}
}))
case .failed(let error):
print("Connection failed for proxy \(proxyDetails[0]): \(error)")
completion(false)
case .cancelled:
print("Connection cancelled for proxy \(proxyDetails[0])")
completion(false)
case .waiting(let error):
print("Connection waiting for proxy \(proxyDetails[0]): \(error)")
completion(false)
default:
break
}
}
connection.start(queue: .global())
}
private func readAllData(connection: NWConnection,
accumulatedData: Data = Data(),
completion: @escaping (Data?, Error?) -> Void) {
connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { data, context, isComplete, error in
if let error = error {
completion(nil, error)
return
}
// Append newly received data to what's been accumulated so far
let newAccumulatedData = accumulatedData + (data ?? Data())
if isComplete {
// If isComplete is true, the server closed the connection or ended the stream
completion(newAccumulatedData, nil)
} else {
// Still more data to read, so keep calling receive
self.readAllData(connection: connection,
accumulatedData: newAccumulatedData,
completion: completion)
}
}
}