Post

Replies

Boosts

Views

Activity

Download a portion of a (large) file from iCloud drive
I have a large file saved in iCloud drive. I need just a portion of that file. func ubiquitousData(file: URL, offset: UInt64, size: UInt64) async -> Data { // downloads just the portion of the ubiquitous `file`. } FileManager already has an api that downloads the full file. Is there a way to download just a portion of the file?
0
0
397
Jul ’24
FileDescriptor writing to an unexpected file
I'm using a file descriptor to write into a file. I've encountered a problem where if the underlying file is removed or recreated, the file descriptor becomes unstable. I have no reliable way to confirm if it's writing on the expected file. let url = URL(fileURLWithPath: "/path/") try FileManager.default.removeItem(at: url) FileManager.default.createFile(atPath: url.path, contents: .empty) let filePath = FilePath(url.path) var fileDescriptor = try FileDescriptor.open(filePath, .readWrite) // The file is recreated - may be done from a different process. try FileManager.default.removeItem(at: url) // L9 FileManager.default.createFile(atPath: url.path, contents: .empty) // L10 let dataToWrite = Data([1,1,1,1]) try fileDescriptor.writeAll(dataToWrite) // L13 let dataWritten = try Data(contentsOf: url) print(dataToWrite == dataWritten) // false I would expect L13 to result in an error. Given it doesn't: Is there a way to determine where fileDescriptor is writing? Is there a way to ensure that fileDescriptor is writing the content in the expected filePath?
8
0
970
May ’24
Searching data using findRange(of:
The performance of DataProtocol.firstRange(of:) and Collection.firstRange(of:) is different. func testSearch(dataSize: Int = 10_000_000, segmentSize: Int = 1000) { let query = Data([1,1,1]) let data = Data(repeating: 0, count: dataSize) let segments = stride(from: 0, to: dataSize, by: segmentSize) // Search for `query` in `data` using `Data.firstRange(of:` var date = Date.now let result1 = segments.compactMap({ i in data[i..<i+segmentSize].firstRange(of: query) }) print(-date.timeIntervalSinceNow) // 1 sec. // Search for `query` in `data` using `Collection.firstRange(of:` date = .now let result2 = segments.compactMap({ i in data[i..<i+segmentSize].search(for: query) }) print(-date.timeIntervalSinceNow) // 4 secs. assert(result1 == result2) } extension Collection { func search<T: Collection>(for query: T) -> Range<Index>? where T.Element == Element, Element: Equatable { firstRange(of: query) } } To fix, I’m explicitly casting it to Data. extension Collection { func search<T: Collection>(for query: T) -> Range<Index>? where T.Element == Element, Element: Equatable { if let data = self as? Data, let query = query as? Data { return data.firstRange(of: query) as? Range<Index> } else { return firstRange(of: query) } } } This fixes, but doesn’t scale well. Given the method signature is same, how can I write the search function such that it picks up the one in DataProtocol? In my testing, the search results of both are same. Besides the performance, is there any other difference?
0
0
498
Feb ’24
App Sandbox - Outgoing connections
To restrict outgoing connections, I've ensured that the following key in not present in the entitlement file: <key>com.apple.security.network.client</key> <true/> The api calls made using URLSession and WKWebView are restricted as expected, but the same is not the case with MKMapView. The map content and the directions api are able to make outgoing network calls. Please let me know if it's possible to reliably restrict outgoing network connections in a sandboxed app?
8
0
1.5k
Jan ’24
Sandboxing iOS Simulator
An iOS app running in simulator has complete access to the Mac's file system: // Files in protected directory like Desktop, Documents, Calendar, etc will need additional permissions. let filesInSystem = FileManager.default.enumerator(at: .currentDirectory(), includingPropertiesForKeys: nil)?.allObjects This isn't the case when running in device as the app is sandboxed. Is the same possible when running in simulator? More specifically, is there a way to restrict access to the Mac's file system when running an app in the Simulator? This is particularly useful when trying out binaries/frameworks that are not open sourced.
1
0
1.3k
Sep ’23
Progressively supply media data
I'm trying to use the resourceLoader of an AVAsset to progressively supply media data. Unable to because the delegate asks for the full content requestsAllDataToEndOfResource = true. class ResourceLoader: NSObject, AVAssetResourceLoaderDelegate { func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool { if let ci = loadingRequest.contentInformationRequest { ci.contentType = // public.mpeg-4 ci.contentLength = // GBs ci.isEntireLengthAvailableOnDemand = false ci.isByteRangeAccessSupported = true } if let dr = loadingRequest.dataRequest { if dr.requestedLength > 200_000_000 { // memory pressure // dr.requestsAllDataToEndOfResource is true } } return true } } Also tried using a fragmented MP4 created using AVAssetWriter. But didn't work. Please let me know if it's possible for the AVAssetResourceLoader to not ask for the full content?
1
0
765
Aug ’23
Symbol breadcrumb
Using Xcode (or Instruments), is there a way to know all the functions/symbols that are touched by a line of code? struct Test { private func intro() { } func partOne() { intro() } func partTwo() { partOne() } func partThree() { partTwo() print(credits) } private var credits: String { "" } } let test = Test() test.partTwo() // partTwo, partOne, intro test.partThree() // partThree, partTwo, partOne, intro, credits
3
0
1.2k
Jul ’23
VPN: Password Reference
I noticed that I need not set the NEVPNProtocolIKEv2's passwordReference if I supplied the userName and password via the options argument in startVPNTunnel. Supply password using passwordReference (requires use of Keychain): func connect(userName: String, password: String, serverAddress: String) async throws {     saveToKeychain(key: "VPN_Password", value: password)     let passwordReference = keychainReference(key: "VPN_Password")     let vpn = NEVPNManager.shared()     try await vpn.loadFromPreferences()     let pc = NEVPNProtocolIKEv2()     pc.serverAddress = serverAddress     pc.authenticationMethod = .none     pc.username = userName     pc.passwordReference = passwordReference     pc.useExtendedAuthentication = true     vpn.protocolConfiguration = pc     vpn.isEnabled = true     try await vpn.saveToPreferences()     try await vpn.loadFromPreferences()     try vpn.connection.startVPNTunnel() } Supply password using options parameter in startVPNTunnel: func connect(userName: String, password: String, serverAddress: String) async throws {     let vpn = NEVPNManager.shared()     try await vpn.loadFromPreferences()     let pc = NEVPNProtocolIKEv2()     pc.serverAddress = serverAddress     pc.authenticationMethod = .none     pc.useExtendedAuthentication = true     vpn.protocolConfiguration = pc     vpn.isEnabled = true     try await vpn.saveToPreferences()     try await vpn.loadFromPreferences()     try vpn.connection.startVPNTunnel(options: [NEVPNConnectionStartOptionUsername: userName, NEVPNConnectionStartOptionPassword: password]) } Is one preferred over the other? I'm inclined to use the second one as it doesn't require the (additional) use of the Keychain. Are there any drawbacks in doing do?
3
0
1.1k
Aug ’22
VPN: Change IP every few minutes
I'm using NEVPNProtocolIKEv2 to configure NEVPNManager: func connect(userName: String, passwordReference: Data, serverAddress: String) async throws {     let vpn = NEVPNManager.shared()     try await vpn.loadFromPreferences()     let pc = NEVPNProtocolIKEv2()     pc.serverAddress = serverAddress     pc.authenticationMethod = .none     pc.username = userName     pc.passwordReference = passwordReference     pc.useExtendedAuthentication = true     vpn.protocolConfiguration = pc     vpn.isEnabled = true     try await vpn.saveToPreferences()     try await vpn.loadFromPreferences()     try vpn.connection.startVPNTunnel() } Is there a parameter I can modify so that the IP address of the client appears different every few minutes?
1
0
843
Aug ’22