Foundation

RSS for tag

Access essential data types, collections, and operating-system services to define the base layer of functionality for your app using Foundation.

Pinned Posts

Posts under Foundation tag

293 Posts
Sort by:
Post not yet marked as solved
10 Replies
2.9k Views
I have a couple of questions about how to properly implement data protection for my iOS apps. I couldn't find very much information about how the AppID Entitlement and it's default then relates to the options that you set when you write a file using NSFileManager or NSData writetofile. If you don't have the data protection entitlement on for your AppID, does this mean that adding NSDataWritingFileProtectionComplete to your code will not provide any protection?If you do have the data protection entitlement enabled in your AppID, and you have set that entitlement to Protected Until First User Authentication, is this the default level of protection? Can you still choose a higher level of data protection like NSDataWritingFileProtectionComplete for particular files?Thanks
Posted
by
Post not yet marked as solved
14 Replies
6.4k Views
I can't get NSURLSession background tasks to use client certificates.I have a simple app that creates an NSURLSessionDownloadTask from an NSURLSession that uses NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(...).I have a custom delegate that implements:"func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void)". For NSURLAuthenticationMethodServerTrust, I accept any server. For NSURLAuthenticationMethodClientCertificate, I have a hardcoded PKCS12 bundle with a single certificate and key from which I successfully create an NSURLCredential (using SecPKCS12Import), then pass that credential to the completion handler with .UseCredential.At runtime, I get the didReceiveChallenge callback for ClientCertificate, then another for NSURLAuthenticationMethodServerTrust, then URLSessionDidFinishEventsForBackgroundURLSession right away without completing the TLS handshake.If I change the NSURLSessionConfiguration to use NSURLSessionConfiguration.defaultSessionConfiguration(), the client cert is presented correctly and the download proceeds.Both tests are done with the app in the foreground.
Posted
by
Post not yet marked as solved
3 Replies
3.6k Views
Trying to convert some code over from NSURLConnection and noticed that the timeouts are per-session, not per-task. In our existing code there are a few places where some requests are given longer timeouts then the others.I see that in NSURLSession the timeouts are all session based. i.e one-size-fits all. There seem to be a couple of options to be able to fine-tune the timouts per-task:Use different sessions for each different timeout. Not pleasant and goes against the idea of having one session-per client-server pairing.Set the Session timeout for each task at task creation time. Not even sure this would work and if it did would need additional multithreading safeguards to ensure only one task at at time can be created.Anyone else had to deal with this oversight?
Posted
by
Post not yet marked as solved
7 Replies
4.9k Views
Hi,I am wondering if its possible to do a GET request with a JSON payload.According to the documentation for NSURLSession, the following is stated: "Your app can provide the request body content for an HTTP POST request in three ways: as an NSData object, as a file, or as a stream."However, this does not mention GET requests. I have tried to put a body in HTTP POST request but it seemed like nothing was actually sent over. I am wondering how to do this properly.. and if it can't be done, are their lower level APIs that I can use to perform this task anyway?
Posted
by
rty
Post not yet marked as solved
13 Replies
4.4k Views
NSBackgroundURLSession (watchOS) executes my ~2mb upload multiple (sometimes >100) times before the task is returned to my app as completed. it appears like the tasks retry the request even before getting a response back from the server.How can I tune my NSURLSessionUploadTasks to only retry on the background session to not send so many retrys so quickly?
Posted
by
Post not yet marked as solved
10 Replies
8.2k Views
I'm using URLSession to make a get request with TLS 1.2 protocol and certificates (which are all self-signed) included in the main bundle. Hopefully I managed to do the pinning but server also requires a client certificate for authentication so I'm trying to respond to the AuthenticationChallenge with UrlCredential but it's not working: i keep getting NSURLErrorDomain Code=-1206 which is "The server “my_server_domain.it” requires a client certificate."Here is my request: func makeGetRequest(){ let configuration = URLSessionConfiguration.default var request = try! URLRequest(url: requestUrl, method: .get) let session = URLSession(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main) let task = session.dataTask(with: request, completionHandler: { (data, response, error) in print("Data = \(data)") print("Response = \(response)") print("Error = \(error)") }) task.resume() }URLSessionDelegate, where I respond to the AuthenticationChallenge:func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { let authenticationMethod = challenge.protectionSpace.authenticationMethod print("authenticationMethod=\(authenticationMethod)") if authenticationMethod == NSURLAuthenticationMethodClientCertificate { completionHandler(.useCredential, getClientUrlCredential()) } else if authenticationMethod == NSURLAuthenticationMethodServerTrust { let serverCredential = getServerUrlCredential(protectionSpace: challenge.protectionSpace) guard serverCredential != nil else { completionHandler(.cancelAuthenticationChallenge, nil) return } completionHandler(.useCredential, serverCredential) } }Server certificate pinning:func getServerUrlCredential(protectionSpace:URLProtectionSpace)->URLCredential?{ if let serverTrust = protectionSpace.serverTrust { //Check if is valid var result = SecTrustResultType.invalid let status = SecTrustEvaluate(serverTrust, &result) print("SecTrustEvaluate res = \(result.rawValue)") if(status == errSecSuccess), let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0) { //Get Server Certificate Data let serverCertificateData = SecCertificateCopyData(serverCertificate) //Get Local Certificate NSData let localServerCertNSData = certificateHelper.getCertificateNSData(withName: "localServerCertName", andExtension: "cer") //Check if certificates are equals, otherwhise pinning fails and return nil guard serverCertificateData == localServerCertNSData else{ print("Certificates doesn't match.") return nil } //Certificates does match, so we can trust the server return URLCredential(trust: serverTrust) } } return nil }And here is where i obtain the client URLCredential from the PKCS12 (.pfx) certificate:func getClientUrlCredential()->URLCredential { let userCertificate = certificateHelper.getCertificateNSData(withName: "userCertificateName", andExtension: "pfx") let userIdentityAndTrust = certificateHelper.extractIdentityAndTrust(fromCertificateData: userCertificate, certPassword: "cert_psw") //Create URLCredential let urlCredential = URLCredential(identity: userIdentityAndTrust.identityRef, certificates: userIdentityAndTrust.certArray as [AnyObject], persistence: URLCredential.Persistence.permanent) return urlCredential }The func 'extractIdentityAndTrust' -successfully- returns a struct with pointers to identity, certificate-chain and trust extracted from the PKCS12; I know that identity and certificates should be stored in the keychain but at the moment I'm just including them in the bundle.I've also added App Transport Security Settings to my Info.plist allowing arbitrary loads and configuring an exception domain.It looks like client doesn't even try to authenticate, so I'm missing something, I guess...
Posted
by
Post not yet marked as solved
4 Replies
1k Views
According to the documentation https://developer.apple.com/documentation/foundation/nsurlrequest.cachepolicy if I'm using the NSURLRequestUseProtocolCachePolicy option and the response stale, system issues a HEAD request. But if there is no internet connection, this request could not be completed so NSURLRequest cannot determine whether the HEAD changed and decide should it return the cached response.Is there a way to force NSURLRequest to use the cached response if there is no connection and cache policy is NSURLRequestUseProtocolCachePolicy?
Posted
by
Post marked as solved
4 Replies
5.7k Views
I'm working on an API client for a REST service that uses a custom token-based authentiation scheme. The app hits a specificed authentication endpoint with a username and password, said endpoint returns a token that's good for X amount of time, and the app passes that token along with every subsequent request. When that token expires, we start over.Most literature out there tells me to manually set the Authorization header on my request, but official Apple documentation discourages this, as that header is meant to be 'owned' by the built-in HTTP loading system. That said, official documentation on the 'correct' way to do this is shockingly lacking, and the standard didReceiveChallenge callbacks seem better suited for non-custom Basic/Digest/etc authentication schemes. One thought I had was registering my own URLProtocol subclass to handle our custom flow. However, while I haven't had a chance to sit down and take a crack at that yet, my understanding from skimming these forums is that it's suffering from some bit-rot right now, so it 'might' (?) not be the best choice. That, and it's also not clear to me whether the rules around the Authorization header change when a custom URLProtocol is in play.So, community (paging eskimo in particular!), what's the correct way for me to go about this?
Posted
by
Post not yet marked as solved
7 Replies
1.7k Views
I have everything associate with on-demand resources working correctly in my application with the exception of the ability to cancel, pause or resume downloading ODR content. Using Xcode 9.4.1 with iOS 11.4 target, the cancel, pause, etc. IBAction is called when a tap occurs, but the progress bar continues unabated. The ODR progress observer completes too. I've seen code like this:class ODRManager {var myCollectionRequest: NSBundleResourceRequest?@IBAction func cancelLoadingOnDemandResource(_ sender: UIButton) { guard let myCurrentRequest = myCollectionRequest else { return } myCurrentRequest.progress.cancel() }}But such code doesn't cancel/pause the NSBundleResourceRequest. I found a radar report dated Jan. 12, 2016 indicating the same problem. Is it possible to cancel, pause or resume a NSBundleResourceRequest download? If so, how is it done?Thank you.
Posted
by
Post marked as solved
5 Replies
3.0k Views
I am really struggling to find how one creates a file that doesn't already exist in Objective-C, and then use that file write data. In C, one uses a fopen command, usually wrapped in an if statement to catch a failure...if ((file_pointer = fopen(file_name, "wb")) == NULL) { fprintf(stderr, "could not create file.\n"); exit(EXIT_FAILURE);}You have created a file, and you have a file_pointer to use as you write data to your file ... fprintf(file_pointer, %d, someInt); So easy.With Objective-C and Xcode... I'm already getting the feeling like there's many ways to skin a cat... but I can't get any of them to work for me.I see some people use an NSData method...BOOL written = [dataBuffer writeToFile:destinationPath options:0 error:NULL]; //assumes a NSData file *dataBuffer and NSString *destinationPath.But this doesn't work, no file is actually created.I also tried:NSFileHandle *file;NSData *data = [...file = [NSFileHandle fileHandleForUpdatingAtPath: @"/tmp/filename.xyz"];[file writeData: data];But this also failed to create a file. There also seems to be a whole other trajectory using NSFileManager and a "createFileAtPath" method, which I ALSO could not get to work. HELP! What am I missing?
Posted
by
Post marked as Apple Recommended
13k Views
We keep getting intermittent app crash from our customers and it is related to initialisation of NSMutableAttributedString.Code:let result = try NSMutableAttributedString(data: data, options: htmlOptions, documentAttributes: nil) <- Crash hereThe above code is executed in cellForRowAt inside a TableViewCell and in some code also in viewDidLoad of a view.data only contains short html text or sometimes even empty string "".We also cannot reproduce the issue when testing with simulator and our test devices.If I google this issue, it seems like there is no official solution that really worked.Suggestions to run in main thread or run in background and then post in main thread seems to contradict the description in the documentation about NSMutableAttributedString.The HTML importer should not be called from a background thread (that is, the options dictionary includes NSDocumentTypeDocumentAttribute with a value of NSHTMLTextDocumentType). It will try to synchronize with the main thread, fail, and time out. Calling it from the main thread works (but can still time out if the HTML contains references to external resources, which should be avoided at all costs). The HTML import mechanism is meant for implementing something like markdown (that is, text styles, colors, and so on), not for general HTML import.Any recommendation on how to use NSMutableAttributedString properly without running into this crash?Here is the crash logs:Fatal Exception: NSInternalInconsistencyException0 CoreFoundation 0x1b3a9c518 __exceptionPreprocess1 libobjc.A.dylib 0x1b2c779f8 objc_exception_throw2 CoreFoundation 0x1b39b6148 +[_CFXNotificationTokenRegistration keyCallbacks]3 Foundation 0x1b44c5f5c -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:]4 UIKitCore 0x1e000d9b0 _prepareForCAFlush5 UIKitCore 0x1e003a674 _beforeCACommitHandler6 CoreFoundation 0x1b3a2d89c __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__7 CoreFoundation 0x1b3a285c4 __CFRunLoopDoObservers8 CoreFoundation 0x1b3a28b40 __CFRunLoopRun9 CoreFoundation 0x1b3a28354 CFRunLoopRunSpecific10 UIFoundation 0x1be08fc78 -[NSHTMLReader _loadUsingWebKit]11 UIFoundation 0x1be092bfc -[NSHTMLReader attributedString]12 UIFoundation 0x1be0deb88 _NSReadAttributedStringFromURLOrData13 UIFoundation 0x1be092b38 -[NSAttributedString(NSAttributedStringUIFoundationAdditions) initWithData:options:documentAttributes:error:]14 MyApp 0x10140b140 @nonobjc NSMutableAttributedString.init(data:options:documentAttributes:) (<compiler-generated>)
Posted
by
Post not yet marked as solved
14 Replies
6.7k Views
I read here that when using `URLSessionConfiguration.background(withIdentifier:)`, it shouldn't timeout and should try again 'till there is an available internet connection or 'till `timeoutIntervalForResource` reached out (which is set to 7 days), but in this case, I'm getting the timeout after less than 15 seconds and after that it doesn't seems to try again, also when there is an internet connection (e.g. turning off Network Link Conditioner).I haven't set anything to that time so I really don't know why this is happening, all I've done is to set `100% Loss` in Network Link Conditioner to check offline usage (which shouldn’t matter to URLSession since it using background configuration).In short:My goal is to start the session whenever there is or there isn't an internet connection and let it fetch as soon as it can, when there is an available internet connection.What happens right now is that the session is timed out and not performing the session also when there is an internet connection (e.g. turning off Network Link Conditioner).*It's important to note that when there is an available internet connection while the session is resumed, it does fetching successfully, so the issue is not with the server I'm sending the task to for sure.Here is my code:Defining session configuration:static let urlSessionConfiguration: URLSessionConfiguration = { let configuration = URLSessionConfiguration.background(withIdentifier: FilesManager.urlSessionIdentifier) configuration.sessionSendsLaunchEvents = false configuration.sharedContainerIdentifier = "myApp" return configuration }()Starting the session:let url = URL(string: "https://url.com/path")! var urlRequest = URLRequest(url: url) urlRequest.httpMethod = "POST" urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") urlRequest.httpBody = body URLSession(configuration: FilesManager.urlSessionConfiguration, delegate: self, delegateQueue: nil).dataTask(with: urlRequest).resume()Delegate:extension FilesManager: URLSessionDataDelegate, URLSessionDelegate { func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { print("\(#function) \(error)") } }Print in console:urlSession(_:task:didCompleteWithError:) Optional(Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={_kCFStreamErrorCodeKey=-2104, _NSURLErrorFailingURLSessionTaskErrorKey=BackgroundDataTask .<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=( "BackgroundDataTask .<1>", "LocalDataTask .<1>" ), NSLocalizedDescription=The request timed out., _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=https://url.com/path, NSErrorFailingURLKey=https://url.com/path})If you know a better way to achieve my goal or you’re think there is something wrong in this code, please, let me know.Thanks,Ido.
Posted
by
Post marked as Apple Recommended
3.3k Views
How do I access a returned value from a Process(), in this case 'which'... var sips_path : String? //MARK: locate sips on local machine let which_sips = Process() which_sips.executableURL = URL(fileURLWithPath: "which") which_sips.arguments = ["sips"] do { sips_path = try which_sips.run() } catch let error as NSError { sips_path = "/usr/bin/sips"; print("Failed to execute which_sips", error) }line 8. gets compiler error "Cannot assign value of type '()' to type 'String?'" I believe, but cannot prove, 'which' returns a string. .run() throws and throws are for errors only, right? So where is the result of calling which?It seems I should use a closure to use $0 but it's already in one...line 9. intends to assign a default path.
Posted
by
Post not yet marked as solved
3 Replies
528 Views
I've implemented the NSFilePresenter protocol in a Mac app (Catalina 10.15.3 Xcode 10.15.3) to watch a directory.Most protocol methods get called correctly, but some don't get called at all. For some there are (cumbersome) alternatives, but if, for example a file is immediately deleted in Finder using option+command+del, the NSFilePresenter delegate never receives any callback. Is there a workaround to trigger the callbacks?final class FileController: NSObject, NSFilePresenter { ... init() { presentedItemURL = // Some directory NSFileCoordinator.addFilePresenter(self) } func accommodatePresentedItemDeletion(completionHandler: @escaping (Error?) -> Void) { // Never gets called completionHandler(nil) } func presentedSubitemDidAppear(at url: URL) { // Never gets called } func presentedSubitemDidChange(at url: URL) { // Does get called } }
Posted
by
Post not yet marked as solved
2 Replies
583 Views
I want to use URLCache to make data (e.g. User, Session, Privileges objects) available when offline. I think it is better to manually saving data in file or UserDefaults because it will fit seamlessly with existing code that load stuff from URLs and without extra code. One of my concern is this. In URLCache documentation - https://developer.apple.com/documentation/foundation/urlcache, it says: Note In iOS, the on-disk cache may be purged when the system runs low on disk space, but only when your app is not running. I don't want my on-disk cache to get purged on low disk space. I browse around and see URLCache has a new initializer in iOS 13 that accepts a directory url for on-disk cache. convenience init(memoryCapacity: Int, diskCapacity: Int, directory: URL? = nil) From my understanding, Caches directory gets purged on low disk space. From File System Programming Guide - https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html: In iOS 5.0 and later, the system may delete the Caches directory on rare occasions when the system is very low on disk space. This will never occur while an app is running. However, be aware that restoring from backup is not necessarily the only condition under which the Caches directory can be erased. So, my question is, if I pass a URL that is not a Caches directory URL. Will my on-disk cache survive the low memory purge? If not, is there any other way to achieve it?
Posted
by
Post marked as solved
5 Replies
1.7k Views
Is there a recommended approach for detecting WebSocket connectivity issues? More specifically, does URLSessionWebSocketTask have a way to access errors within CFNetwork? My app maintains a WebSocket connection with a remote server, and I would like to notify the user that their connection has dropped when the phone loses network connectivity. I'm simulating a dropped network connection in my test environment by placing my phone in Airplane mode and deactivating WiFi. None of URLSessionWebSocketTask's delegates or callbacks pass back an error, and I only get the following log message: Connection 1: encountered error(1:53) I'm using a URLSessionWebSocketDelegate and the urlSession(session:, webSocketTask:, didCloseWith:) does not get triggered, neither does webSocketTask.receive(completionHandler:) I believe the log messages comes from CFNetwork since I can find the log within the Console app and the log references CFNetwork. I found that webSocketTask.sendPing(pongReceiveHandler:) does eventually discover that connectivity is lost, but after a really long time. As far as I know, sendPing should probably run in a background task that runs every 30 seconds or so, and the error isn't discovered until about another 30+ seconds when the ping request times out. So, it could take 1+ minute(s) before the user is notified of the issue. I don't really like this approach since it requires extra code, extra network requests, and a very delayed response. So, do errors within CFNetwork propagate to URLSessionWebSocketTask in any way? If not, I would really like if errors within CFNetwork propagated to webSocketTask.receive(completionHandler:) as a .warning URLSessionWebSocketTask.Message along with an error code. Ultimately, I would like to handle connection errors when they are encountered. I noticed in another forum post that Apple changed iOS WebSockets in a beta release, so I tried to update my software without any luck. I updating macOS to 10.15.6 Beta (19G60d), iOS to 13.6 (17G5059c), and XCode to Version 12.0 beta 2 (12A6163b). However, XCode couldn't connect to my phone, and webSocketTask.send(message:) had intermittent string encoding issues. System Details: macOS 10.15.5 (1 June 2020 update) iOS 13.5.1 (1 June 2020 update) XCode Version 11.5 (11E608c)
Posted
by
Post not yet marked as solved
28 Replies
5.0k Views
We've noticed that our app is now immediately crashing on background on iOS 14 Beta 3 with the 0xdead10cc termination reason. This indicates (as per Technical Note TN2151 - https://developer.apple.com/library/archive/technotes/tn2151/_index.html) that the app held on to a file lock or sqlite database lock during suspension. However this crash didn't occur at all prior to beta 3. Did something change in iOS that might cause this? Stricter enforcement? This is a hard crash for us to debug with little than the technical note to go on and potentially an unknown change in iOS itself.
Posted
by
Post not yet marked as solved
1 Replies
313 Views
I have a Settings.bundle for my app Roughly, which tells the approximate time in words (e.g. it's about quarter to six) in a complication. It supports a number of languages, but I allow people to use a different language to their own, to help them learn how to tell the time in another language. The preference switch works fine in the Watch app on the iPhone, but if a user downloads the app direct from the App Store to their watch, there is no way for them to access those preferences. The preferences do not appear in the Watch app without the iOS app present on the iPhone. Does anyone have a good solution to this? Do I have to offer a preferences switch in the app itself?
Posted
by
Post not yet marked as solved
4 Replies
516 Views
I have had 2 apps in the store for several years now.  Unfortunately, I have never been able to advertise. They were supposed to be 2 separate apps. The English and the Spanish version. They were incorrectly loaded as one - English and Italian languages - not Spanish. In addition, I have no access to my files. My questions are: can I replace these apps with a newly created version with same Titles? My new version is huge - what is the maximum file size for interactive eBook or IOS Apps?
Posted
by
Post not yet marked as solved
23 Replies
5.6k Views
Hi, I am facing a strange issue in my app with iOS14 there is a intermittent crash, i am using NetServiceBrowser for MDNS discovery not sure if that is causing the problem crash log has below information: Crashed: com.apple.main-thread 0 CoreFoundation 0x1a906c4c4 CFAssertMismatchedTypeID + 108 1 CoreFoundation 0x1a8f7db0c CFRunLoopSourceRemoveFromRunLoop + 298 2 CFNetwork 0x1a96255b0 CFNetServiceBrowserStopSearch + 460 3 CoreFoundation 0x1a8f81240 CFRUNLOOPISCALLINGOUTTOASOURCE0PERFORMFUNCTION + 24 4 CoreFoundation 0x1a8f81140 CFRunLoopDoSource0 + 204 5 CoreFoundation 0x1a8f80488 CFRunLoopDoSources0 + 256 6 CoreFoundation 0x1a8f7aa40 CFRunLoopRun + 776 7 CoreFoundation 0x1a8f7a200 CFRunLoopRunSpecific + 572 8 GraphicsServices 0x1bf075598 GSEventRunModal + 160 9 UIKitCore 0x1ab840004 -[UIApplication run] + 1052 10 UIKitCore 0x1ab8455d8 UIApplicationMain + 164
Posted
by