I'm trying to put an attributed string in to an NSTextField the user creates in their document. I cannot use an NSTextView. The problem is once the textfield is created attributes cannot be edited. Also I work in Objective-c because reasons.
So when the field is created this is the code used:
[attribDict setObject:[self.editor.delegate foregroundColor] forKey:NSForegroundColorAttributeName];
[attribDict setObject:aFont forKey:NSFontAttributeName];
[attribDict setObject:[self.editor.delegate backgroundColor] forKey:NSBackgroundColorAttributeName];
[attribDict setObject:self.editor.delegate.strokeColor forKey:NSStrokeColorAttributeName];
[attribDict setObject:[NSNumber numberWithInt:-self.editor.delegate.strokeWidth] forKey:NSStrokeWidthAttributeName];
This part works if I set all the attributes before I create the textfield.
But I need to be able to edit attributes on the string. For that I use this code:
NSFont * aFont = [NSFont fontWithName:self.delegate.fontSelectorButton.title size:self.delegate.fontSize.intValue];
NSMutableDictionary * attribDict = [[NSMutableDictionary alloc]init];
[attribDict setObject:[self.delegate foregroundColor] forKey:NSForegroundColorAttributeName];
[attribDict setObject:aFont forKey:NSFontAttributeName];
[attribDict setObject:[self.delegate backgroundColor] forKey:NSBackgroundColorAttributeName];
[attribDict setObject:self.delegate.strokeColor forKey:NSStrokeColorAttributeName];
[attribDict setObject:[NSNumber numberWithInt:self.delegate.strokeWidth] forKey:NSStrokeWidthAttributeName];
[textShape updateTextAttributesFromDictionary:attribDict];
And finally this is called the change the string attributes:
-(void)updateTextAttributesFromDictionary:(NSDictionary*)attribs
{
self.stringAttributes = attribs;
NSMutableAttributedString * as = [[NSMutableAttributedString alloc]initWithAttributedString:self.myTextField.attributedStringValue];
[as beginEditing];
[as setAttributes:attribs range:NSMakeRange(0, as.length)];
[as endEditing];
self.myTextField.attributedStringValue = as;
}
I have tried just setting the new attributes and get nothing. The above code however gives me wildly unpredictable results. Sometimes the NSTextfield gets a background color that cannot be altered. Sometimes the text vanishes. Sometimes all attributes are lost, sometimes if I include a stroke color and width I get the stroke but no fill. That's the most common.
Is there some fundimental NSTextField short coming I'm missing? Is there something I'm missing with NSAttributedString? Are NSAttributedStrings not compatible with NSTextField?
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
Sort by:
Post
Replies
Boosts
Views
Activity
I get and int unix timestamp from database
and convert it to timeinterval as some instructions said.
But the result date is not correct.
the code is as follows:
let dateValue = try join.get(examDate);
print (dateValue)
let timeInterval = TimeInterval(dateValue);
print(timeInterval)
let date = Date(timeIntervalSince1970: timeInterval)
print(date)
the result is as follows:
1709942400000
1709942400000.0
56155-12-02 00:00:00 +0000
by converting 1709942400000 with js Date, we got the value:
>new Date(1709942400000)
2024-03-09T00:00:00.000Z
How can I properly convert unix timestamp to Date object?
Thanks in advance.
Our app has a share extension. And we recently noticed something with iOS 17.3.1.
From Safari, when we receive the plist and try to load it, we are seeing exceptions for classes not allowed to be unarchived.
[itemProvider loadItemForTypeIdentifier:[UTTypePropertyList identifier] options:nil completionHandler:^(NSDictionary *jsDict, NSError *error) {
}
We see these exceptions:
value for key 'NS.keys' was of unexpected class 'NSString' (0x1ee7d2970) [/System/Library/Frameworks/Foundation.framework].
Allowed classes are:
{(
"'NSDictionary' (0x1ee7cad38) [/System/Library/Frameworks/CoreFoundation.framework]"
)}
(null)
Our preprocessing javascript file is basic, and only passes a title and URL as part of the payload.
arguments.completionFunction({
"URL": document.URL
"title": document.title,
});
I regularly see folks confused as to which URLSession task types are supported in which session types. Here’s a handy reference:
Task Type Standard Background
--------- -------- ----------
data, convenience yes no
data, delegate yes yes [1]
download, convenience yes no
download, delegate yes yes
upload, convenience yes no
upload, delegate, data yes no
upload, delegate, stream yes no
upload, delegate, file yes yes
stream yes no
WebSocket yes no
In this table:
A background session is one created from a configuration that was created with the background(withIdentifier:) method.
A standard session is one created from some other configuration, namely default or ephemeral.
A convenience task is one created by a Swift async method or a method that takes a completion handler.
A delegate task is one created otherwise; these signal their completion by calling the urlSession(_:task:didCompleteWithError:) delegate method.
For an upload task, the data, stream, and file modifiers indicate how you specify the HTTP request body.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] While it’s possible to run a data task in a background session, this only works if your app avoids suspension while the request is in flight. This is useful in very rare circumstances [2] that most developers never encounter.
[2] The specific situation I’m aware of is when you don’t know whether a request’s response will be big (like a file to download) or small (like a status response). To handle this, you start a data task in the background session and, if the response indicates that it’s large, transform it to a download task in your urlSession(_:dataTask:didReceive:completionHandler:) method.
(r. 123084713)
Please help me understand this section!
I'm reading Finding the Dynamic Type in a Generic Context that has this snippet:
func printGenericInfo<T>(_ value: T) {
let t = type(of: value)
print("'\(value)' of type '\(t)'")
}
protocol P {}
extension String: P {}
let stringAsP: P = "Hello!"
printGenericInfo(stringAsP)
// 'Hello!' of type 'P'
... that's followed up by this sentence:
This unexpected result occurs because the call to type(of: value) inside printGenericInfo(_:) must return a metatype that is an instance of T.Type , but String.self (the expected dynamic type) is not an instance of P.Type (the concrete metatype of value).
1. How come String.self is not an instance of P when I can run this code?
func f(_ t: P.Type) { print("...") }
f(String.self)
2. Why does type(of:) return the concrete metatype outside but not inside generic functions?
print("'\(stringAsP)' of type '\(type(of: stringAsP))'")
// 'Hello!' of type 'String'
Hello,
I am developing launch agent which sets signal handler for SIGTERM.
I am calling CFRunLoopRun() in main thread.
Is it safe to call CFRunLoopStop(CFRunLoopGetMain()) in SIGTERM signal handler?
Thank you for your help!
I am using Relay to connect to nginx server which supports http3 connections for which I get
quic_stream_send_create [C1.1.1.1:5] [24e7c30b6b4eb7ba-0000000000001002e2c0e6cb5099cd86ef1f0f7c] unable to create DATAGRAM flow since the peer did not provide max_datagram_frame_size in transport parameters
[C1.1.1.1:3] Unable to send 1200 early bytes
quic_stream_send_create [C1.1.1.1:5] [24e7c30b6b4eb7ba-0000000000001002e2c0e6cb5099cd86ef1f0f7c] unable to create DATAGRAM flow since the peer did not provide max_datagram_frame_size in transport parameters
This is something very simple I have written :
` let relayURL = URL(string: "https://192.168.64.2:8443")!
let relayEndpoint = NWEndpoint.url(relayURL)
if #available(iOS 17.0, *) {
var tlsOptions = NWProtocolTLS.Options()
let relayServer = ProxyConfiguration.RelayHop(http3RelayEndpoint: relayEndpoint, tlsOptions: NWProtocolTLS.Options = .init())
let relayConfig = ProxyConfiguration(relayHops: [relayServer])
let config = URLSessionConfiguration.default`
config.connectionProxyDictionary = [kCFNetworkProxiesHTTPEnable as AnyHashable: true,
kCFNetworkProxiesHTTPProxy as AnyHashable: "192.168.64.2",
kCFNetworkProxiesHTTPPort as AnyHashable: 8443,
kCFStreamPropertySSLSettings as AnyHashable: sslSettings]
config.proxyConfigurations = [relayConfig]
// Call addCert to add the certificate to the trust store
//addCert(cert: "cert")
// Example usage of the custom session
let session = makeInsecureURLSession(config: config)
let url = URL(string: "https://google.com")! // Example URL
let task = session.dataTask(with: url) { data, response, error in
// Handle response
print("response is \(response)")
if let httpResponse = response as? HTTPURLResponse {
let protocolUsed = httpResponse.url?.scheme ?? "Unknown"
print("Protocol used: \(protocolUsed)")
} else {
print("Response is not an HTTPURLResponse")
}
}
task.resume()
I'm having an issue with showing progress in a upload task. I have created a local express app to test it's behavior. But progress / delegate always throughs the same results. I'm also conforming to URLSessionTaskDelegate.
This is the way I configure URLSession it's always .default
private lazy var session: URLSession = {
.init(
configuration: self.configuration,
delegate: self,
delegateQueue: OperationQueue.main
)
}()
private var observation: NSKeyValueObservation?
Then I call it using this func and convert it into a publisher
func loadData1(path: String, method: RequestMethod, params: [String: String]) -> AnyPublisher<Data, Error> {
let publisher = PassthroughSubject<Data, Error>()
guard let imageUrl = Bundle.main.url(forResource: "G0056773", withExtension: "JPG"),
let imageData = try? Data(contentsOf: imageUrl) else { return Fail(error: NSError(domain: "com.test.main", code: 1000)).eraseToAnyPublisher() }
var request = URLRequest(url: URL(string: "http://localhost:3000/")!)
request.httpMethod = "POST"
let data = request.createFileUploadBody(parameters: [:], boundary: UUID().uuidString, data: imageData, mimeType: "image/jpeg", fileName: "video")
let task = session.uploadTask(with: request, from: data) { data, response, error in
if let error = error {
return publisher.send(completion: .failure(error))
}
guard let response = response as? HTTPURLResponse else { return publisher.send(completion: .failure(ServiceError.other)) }
guard 200..<300 ~= response.statusCode else { return publisher.send(completion: .failure(ServiceError.other)) }
guard let data = data else { return publisher.send(completion: .failure(ServiceError.custom("No data"))) }
return publisher.send(data)
}
observation = task.progress.observe(\.fractionCompleted) { progress, _ in
print("progress: ", progress.totalUnitCount)
print("progress: ", progress.completedUnitCount)
print("progress: ", progress.fractionCompleted)
print("***********************************************")
}
task.resume()
return publisher.eraseToAnyPublisher()
}
request.createFileUploadBody is just an extension of URLRequest that I have created to create the form data's body.
Delegate
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
print(bytesSent)
print(totalBytesSent)
print(totalBytesExpectedToSend)
print("*********************************************")
}
No matter how big or small is the file that I'm uploading I always get the same results.
The delegate is only called once. And the progress is also always the same.
progress: 100
progress: 0
progress: 0.0095
***********************************************
progress: 100
progress: 0
progress: 4.18053577746524e-07
***********************************************
2272436
2272436
2272436
*********************************************
progress: 100
progress: 95
progress: 0.95
***********************************************
progress: 100
progress: 100
progress: 1.0
***********************************************
^^^^^^ Output from prints
Does anyone knows what might I be doing wrong?
Thanks in advance
When I run app in iPad in release mode app crashes on launch Only in Xcode 15
it works fine in older Xcodes (14,13 etc)
dyld[36278]: Symbol not found: _$s10Foundation13__DataStorageC12replaceBytes2in4with6lengthySnySiG_SVSgSitF
Referenced from: <DC51D787-077E-3775-80C8-609FB1460F73> /private/var/containers/Bundle/Application/1A433D08-5BBA-4CEA-A8B1-78ED0777FB2C/MYAPP.app/MyAPP
Expected in: <57FF5555-479E-3634-931A-26D334C85350> /System/Library/Frameworks/Foundation.framework/Foundation
Hey there i try to adept the Observable macro for my SwiftUI Project.
I wanna get data from HealthKit and transform it to FHIR.
Here i need one class for managing this process which will be shared through my project in order to access these data.
The following Codesnippet raises an error:
import Observation
import HealthKit
import FHIR
@Observable
class HealthKitManager{
let healthStore = HKHealthStore()
init(){
}
func requestAuthorization(){
let authTypes: Set = [HKQuantityType(.stepCount),
HKQuantityType(.heartRate)
]
guard HKHealthStore.isHealthDataAvailable() else {
print("health data not available!")
return
}
healthStore.requestAuthorization(toShare: nil, read: authTypes) {
success, error in
if success {
print("OK Fetching")
} else {
print("\(String(describing: error))")
}
}
}
}
So the FHIR module contains a Models module which define different models.
In the FHIR world there is also a concept called observation... now the problems begin.
open class Observation : Models.DomainResource {
...
}
When i try import Observation for the Observable macro and also import FHIR in order to create Observations, XCode rises an error: Observable' is not a member type of class 'Models.Observation'
It's also said that Observation is declared in the FHIR.Models.Observation class which is true, but it seems that this raises the Problem with the @Observable macro.
It's also said that Type 'Observation' has no member 'ObservationRegistrar'
Which comes from the Observable Macro i think.
When i don't import FHIR then everything works fine, but then my use case is broken because i need these standard in order to get my use case running.
All in all i need big help and be thankfull for possible solutions!
Is it possible to get the original date created for an IntentFile? The following code always gets the date for right now, surely because it's copied into a temporary directory so that's when it was created at that location.
if let fileURL = file.fileURL, fileURL.startAccessingSecurityScopedResource() {
if let attributes = try? FileManager.default.attributesOfItem(atPath: fileURL.path), let date = attributes[.creationDate] as? Date {
print(date)
}
fileURL.stopAccessingSecurityScopedResource()
}
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?
One of our client has contacted us with the following error :
Task .&lt;3&gt; request https:URL is NOT allowed to set HSTS for main doc (null)
Th request is sent from our SDK. According to the client it happens only on Vision Pro.
All our requests to the server on the SDK side are https.
The serve has the following header: X-Content-Type-Options X-Frame-Options Strict-Transport-Security
Can somebody share some insight?
For the current app, I can get the Application Scripts directory with FileManager.url(for: .applicationScriptsDirectory, in: .userDomainMask, appropriateFor: nil, create: true), but I cannot find a similar API for application groups. Does one exist, or do I have to construct the URL manually? That would probably be ~/Library/Application Scripts/[app group id], but there doesn't seem to be a FileManager API to access ~ either, as FileManager.default.homeDirectoryForCurrentUser returns /Users/username/Library/Containers/[app id]/Data/.
Is there a way of converting AttributedString or NSAttributedString to Markdown?
I tried to read an Object :
-(NSMutableDictionary*) readMyObject:(NSData*)data;
{
NSError * error;
Class class = [NSMutableDictionary class];
NSMutableDictionary * dict;
dict = [NSKeyedUnarchiver unarchivedObjectOfClass:class
fromData:data error:&error];
return dict;
the result was nil.
I searched by Developer for a solution and found one :
{
// NSKeyedUnarchiver * unarchiver = [[NSKeyedUnarchiver alloc] init];
[unarchiver decodeObjectOfClasses:
[[NSSet alloc]initWithArray:
@[[NSDictionary class],
[NSMutableDictionary class],
[NSArray class],
[NSMutableArray class],
[NSString class], [NSNumber class]]]
forKey:NSKeyedArchiveRootObjectKey];
[unarchiver finishDecoding];
}
The first line was from me and it crashed the project.
I assume there is an easy answer, not for me.🥲
Uwe
I recently handled a couple of questions about this for DTS, so I thought I’d write it up for the benefit of all.
If you have any questions or comments, please put them in a new thread here on DevForums. Tag it with Foundation and CFNetwork so that I see it.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
HTTP authentication challenges with Swift concurrency
URLSession has always made it easy to access HTTP resources, but things get even better when you combine that with Swift concurrency. For example:
import Foundation
func main() async throws {
// Set up the request.
let url = URL(string: "https://example.com")!
let request = URLRequest(url: url)
// Run it; this will throw if there’s a transport error.
let (body, response) = try await URLSession.shared.data(for: request)
// Check for a server-side error.
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
… handle the error …
}
// Success.
… HTTP response headers are in `response.allHeaderFields` …
… HTTP response body is in `body` …
}
try await main()
But what happens if you need to handle an HTTP authentication challenge? The current documentation for authentication challenges is very good, but it assumes that you have a session delegate. That doesn’t really mesh well with Swift concurrency.
Fortunately there’s an easier way: Pass in a per-task delegate. Consider this slightly updated snippet:
let url = URL(string: "https://postman-echo.com/basic-auth")!
let request = URLRequest(url: url)
let (body, response) = try await URLSession.shared.data(for: request)
This fetches a resource, https://postman-echo.com/basic-auth, that requires HTTP Basic authentication. This request fails with a 401 status code because nothing handles that authentication. To fix that, replace the last line with this:
let delegate = BasicAuthDelegate(user: "postman", password: "password")
let (body, response) = try await URLSession.shared.data(for: request, delegate: delegate)
This creates an instance of the BasicAuthDelegate, passing in the user name and password required to handle the challenge. That type implements the URLSessionTaskDelegate protocol like so:
final class BasicAuthDelegate: NSObject, URLSessionTaskDelegate {
init(user: String, password: String) {
self.user = user
self.password = password
}
let user: String
let password: String
func urlSession(
_ session: URLSession,
task: URLSessionTask,
didReceive challenge: URLAuthenticationChallenge
) async -> (URLSession.AuthChallengeDisposition, URLCredential?) {
// We only care about Basic authentication challenges.
guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic else {
return (.performDefaultHandling, nil)
}
// Limit the authentication attempts.
guard challenge.previousFailureCount < 2 else {
return (.cancelAuthenticationChallenge, nil)
}
// If all is well, return a credential.
let credential = URLCredential(user: user, password: password, persistence: .forSession)
return (.useCredential, credential)
}
}
This delegate handles the NSURLAuthenticationMethodHTTPBasic authentication challenge, allowing the overall request to succeed.
Now you have the best of both worlds:
An easy to use HTTP API
With the flexibility to handle authentication challenges
This approach isn’t right for all programs, but if you’re just coming up to speed on URLSession it’s a great place to start.
Hi,
It seams that the public func isSuperset(of other: CharacterSet) -> Bool API gives inconsistent results for some emoji symbols when uses with and without prefix text. Here is a playground example:
import Foundation
let input1 = "🥀"
let input11 = "a🥀"
let input2 = "😀"
let input22 = "a😀"
let letters = CharacterSet.letters
print("'\(input1)' is part of 'CharacterSet.letters': \(letters.isSuperset(of: CharacterSet(charactersIn: input1)))") // Gives false
print("'\(input11)' is part of 'CharacterSet.letters': \(letters.isSuperset(of: CharacterSet(charactersIn: input11)))") // INCORRECT: Should give false, but it gives true
print("'\(input2)' is part of 'CharacterSet.letters': \(letters.isSuperset(of: CharacterSet(charactersIn: input2)))") // Gives false
print("'\(input22)' is part of 'CharacterSet.letters': \(letters.isSuperset(of: CharacterSet(charactersIn: input22)))") // Gives false
Output:
'🥀' is part of 'CharacterSet.letters': false
'a🥀' is part of 'CharacterSet.letters': true
'😀' is part of 'CharacterSet.letters': false
'a😀' is part of 'CharacterSet.letters': false
Has anyone observed this?
I just wasted quite a lot of time on this .. so in case somebody else checks in here, beware that the following:
formatted(dateTime.hour(.defaultDigits(amPM: .omitted)))
does, indeed omit AM/PM, but it doesn't change to using a 24 hour clock. Instead, hours cycle through 1...12 twice a day.
Hi,
I am implementing the HTTP3 Relay server, and testing by the URLSession,
let relayEndpoint = NWEndpoint.url(URL(string:"https://localhost:8002")!)
let relayServer = ProxyConfiguration.RelayHop(
http3RelayEndpoint: relayEndpoint,
additionalHTTPHeaderFields: ["Proxy-Authorization":"Basic ***"]
)
let relayConfig = ProxyConfiguration(relayHops: [relayServer])
let config = URLSessionConfiguration.default
config.proxyConfigurations = [relayConfig]
let s = URLSession(configuration: config)
I have implemented both the CONNECT method and CONNECT method with :protocol of CONNECT-UDP over HTTP/3.
If I enabled CONNECT-UDP only, when I try to connect some HTTP/3 URL like https://quic.aiortc.org/4, it works without problem. And URLSession will use the CONNECT-UDP to connect the UDP channel, throw which the URLSession will do the HTTP/3 request.
However, if i enabled both the CONNECT-UDP and CONNECT (for TCP tunnel), the URLSession seems wired. It first try to establish the tunnel for UDP using the CONNECT-UDP method, and then closed it. And finally, it created the TCP tunnel using the CONNECT method.
So is there any detailed document for the behavior of the behavior of URLSession with http3RelayEndpoint?
Thanks you.