Post not yet marked as solved
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?
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?
Post not yet marked as solved
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.
Post not yet marked as solved
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?
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
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?
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?