A customer reported that when my app creates directories on their NAS, an error is shown. With their cooperation I boiled the source of the error down to setting URLResourceKey.fileSecurityKey on the directory URL, or setting any of FileAttributeKey.groupOwnerAccountID, .groupOwnerAccountName, .ownerAccountID or .ownerAccountName with FileManager.
I thought that maybe URLResourceKey.volumeSupportsExtendedSecurityKey would allow me to determine in advance if setting any of these attributes works, but it seems that the result is false on one of my exFAT drives which doesn't yield any error when setting any of the attributes. I don't even know what "extended security" means in this case, and it doesn't seem to be documented. Should I rely on URLResourceKey.volumeSupportsExtendedSecurityKey?
I tried running chown -vv myusername:admin on a file on that exFAT drive: even if the output includes the text 501:20 -> 501:80, which I assume means that the group should have been changed to admin, running the command again yields the exact same output and running stat shows that the group is still staff.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I'm trying to copy the access permissions of a source directory to a destination directory. The Finder Info panel of the source directory shows the following permissions:
Source directory:
I: Read & write
Everyone: No access
Destination directory:
I: Read & write
Staff: Read only
Everyone: Read only
The following code succeeds in creating a file in the destination directory, but then fails when setting the URL.fileSecurityKey resource:
let openPanel = NSOpenPanel()
openPanel.canChooseDirectories = true
openPanel.canChooseFiles = false
openPanel.runModal()
let source = openPanel.urls[0]
openPanel.runModal()
var destination = openPanel.urls[0]
do {
try Data().write(to: destination.appendingPathComponent("asd"))
try destination.setResourceValues(source.resourceValues(forKeys: [.fileSecurityKey]))
} catch {
fatalError(error.localizedDescription)
}
The error message is:
You don’t have permission to save the file “destination” in the folder “parent”
I thought that an app run by a user has the same permissions as the user itself, and since I have read & write access to both the source and destination directories, the app should be able to copy the access permissions without issues. What is the problem?
In my table view, each row contains a popup button and a date picker. When clicking on the popup button, it behaves as expected: the menu appears and I can change the selected item. But when clicking on the date components of date picker, the table view row is selected, as if I'm clicking on a non-interactive control. Only when clicking on the stepper (the up/down arrows on the right) does the first date component get selected, which then allows me to click on the other ones as well.
Can I change this behaviour so that clicking on the date picker behaves as if I'm directly interacting with it, instead of the table view?
I'm writing an app that uses the App Store Connect API and would like to store the private key contained in the .p8 file downloaded from the website in the keychain.
The following code successfully stores a key in the keychain with SecItemAdd, then tries to read it immediately, but without success (the error code of SecItemCopyMatching is errSecItemNotFound and the console outputs nil). Running the code a second time causes SecItemAdd to fail with code errSecDuplicateItem, and SecItemCopyMatching again with code errSecItemNotFound.
What am I doing wrong?
class AppDelegate: NSObject, NSApplicationDelegate {
private let secApplicationTag = "com.example.app".data(using: .utf8)!
func applicationDidFinishLaunching(_ aNotification: Notification) {
do {
try storeKey("asdf")
print(try readKey() as Any)
} catch {
print(error)
}
}
private func storeKey(_ key: String) throws {
guard let data = Data(base64Encoded: key) else {
fatalError()
}
let status = SecItemAdd([kSecClass as String: kSecClassKey, kSecAttrLabel as String: "Asdf", kSecAttrApplicationTag as String: secApplicationTag, kSecAttrKeyClass as String: kSecAttrKeyClassPrivate, kSecValueData as String: data, kSecAttrSynchronizable as String: true] as [String: Any] as CFDictionary, nil)
if status != errSecSuccess {
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
}
}
private func readKey() throws -> String? {
var item: CFTypeRef?
let status = SecItemCopyMatching([kSecClass as String: kSecClassKey, kSecAttrApplicationTag as String: secApplicationTag, kSecAttrKeyClass as String: kSecAttrKeyClassPrivate, kSecReturnData as String: true] as [String: Any] as CFDictionary, &item)
switch status {
case errSecSuccess:
let data = item as! Data
return (data as Data).base64EncodedString()
case errSecItemNotFound:
return nil
default:
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
}
}
}
I use the following code to save a private key with a custom label, but the Keychain app shows an entry with name and account octagon-com.apple.security.keychain and type Octagon Account State (com.apple.security.keychain,defaultContext). (This entry, by the way, stays in the Keychain app even after trying to remove it from the Keychain app itself.) Can these values be customized, and what is kSecAttrLabel if it's not displayed in the Keychain app? The documentation only reads The corresponding value is of type CFString and contains the user-visible label for this item.
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
do {
try storeKey("asdf")
} catch {
print(error)
}
}
private func storeKey(_ key: String) throws {
guard let data = Data(base64Encoded: key) else {
fatalError()
}
let status = SecItemAdd([kSecClass as String: kSecClassKey, kSecAttrLabel as String: "Asdf", kSecAttrApplicationTag as String: "com.example.app2".data(using: .utf8)!, kSecAttrKeyClass as String: kSecAttrKeyClassPrivate, kSecValueData as String: data, kSecAttrSynchronizable as String: true] as [String: Any] as CFDictionary, nil)
if status != errSecSuccess {
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
}
}
}
When copying a 7 GB file, the filecopy function is always about 20% slower than the cp command. I tested using my MacBook Pro 14" M1 and an external SSD connected via USB.
Mac to Mac
filecopy: 4.78s
cp: 3.40s
Mac to SSD
filecopy: 20.22s
cp: 15.93s
SSD to Mac
filecopy: 20.61s
cp: 16.64s
I use the following code:
let openPanel = NSOpenPanel()
openPanel.runModal()
let source = openPanel.urls[0]
openPanel.canChooseDirectories = true
openPanel.canChooseFiles = false
openPanel.runModal()
let destination = openPanel.urls[0].appendingPathComponent(source.lastPathComponent)
source.withUnsafeFileSystemRepresentation { sourcePath in
destination.withUnsafeFileSystemRepresentation { destinationPath in
let state = copyfile_state_alloc()
defer {
copyfile_state_free(state)
}
let date = Date()
if copyfile(sourcePath, destinationPath, state, copyfile_flags_t(COPYFILE_ALL | COPYFILE_NOFOLLOW | COPYFILE_EXCL)) != 0 {
print(NSError(domain: NSPOSIXErrorDomain, code: Int(errno)))
}
print(-date.timeIntervalSinceNow)
}
}
and the very basic cp command:
time cp /path/to/source /path/to/destination
Is there a faster way to copy files? Am I doing something wrong with filecopy?
When a file named a.txt is not downloaded locally, the iCloud Drive folder actually only contains a placeholder named .a.txt.icloud (that is still displayed as a.txt by the Finder) with a very small file size, something like 176 bytes. How can I get the original file size, like the Finder displays?
I would like to install macOS 14 Sonoma on an external partition, but I couldn't find an installer on the developer website. It seems that it's only possible to upgrade from the System Settings, so I thought I would install Ventura first on the separate partition and then upgrade to Sonoma.
I downloaded the Ventura installer from the App Store and selected the external partition during the installation, but when the Mac reboots, it just reboots into my main macOS partition. If I shut down and hold the power button pressed to select the boot partition (I have a M1 MacBook Pro 14" 2022), then nothing happens: an indeterminate progress indicator spins for a couple seconds, the partition list remains there and I can only successfully boot into my main partition again. I also tried running the installer from another macOS Ventura and macOS Monterey partition I had installed last year, but when I select the partition on which to install the new Ventura, nothing happens and I can only quit the installer.
Is there a way to debug all these issues? How can I install macOS Sonoma on a separate partition without overwriting my main macOS Ventura install?
I need to manually set the frame of a NSTextField, but it seems that when added to AVPlayerView.contentOverlayView the frame gets resized so that it hugs the text.
This doesn't happen when the text field is added to a simple NSView instead.
Is this a bug? Is there a workaround?
class ViewController: NSViewController {
override func loadView() {
view = NSView()
let text = NSTextField(frame: CGRect(x: 0, y: 0, width: 200, height: 30))
text.translatesAutoresizingMaskIntoConstraints = false
text.isEditable = false
text.backgroundColor = .red
let paragraph = NSMutableParagraphStyle()
paragraph.alignment = .center
text.attributedStringValue = NSAttributedString(string: "asdf", attributes: [.paragraphStyle: paragraph])
view.addSubview(text)
// commenting out the following 3 lines solves the issue
let playerView = AVPlayerView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
view.addSubview(playerView)
playerView.contentOverlayView!.addSubview(text)
// uncommenting the following 5 lines also solves the issue, but the wrong text field frame is briefly visible before it resizes to the correct width
// DispatchQueue.main.async {
// print(text.frame)
// text.frame.size.width = 200
// text.removeConstraints(text.constraints)
// }
}
}
Is there a way to compare a local app screenshot on my Mac with the one currently on App Store Connect without downloading the screenshot itself? The API returns fileSize and sourceFileChecksum properties (https://developer.apple.com/documentation/appstoreconnectapi/read_app_screenshot_information), but the file size of my local image is different (url.resourceValues(forKeys: [.fileSizeKey]).fileSize) and the checksum is also different from the one I provided when completing the app screenshot upload.
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect API
Tags:
App Store Connect API
NSTextField and NSParagraphStyle have a alignment: NSTextAlignment property that allows to align text to the left, center, right, or natural, which means that text for left-to-right languages is aligned left and text for right-to-left languages is aligned right. What I'm looking for is how to align text in the opposite direction of the natural direction. (Note that using the leading and trailing NSLayoutConstraints is not enough as they only aligns the text bounding box, but not the text within the bounding box.)
Is there a way to accomplish this? Or is there a built-in function that allows to determine what the natural direction of a String is, so that I can then calculate the alignment by flipping that value?
In the WebVTT video subtitle format, subtitles can be horizontal, vertical growing left, or vertical growing right. The natural text direction of NSTextView is horizontal; with setLayoutOrientation(_:) I get vertical text growing left. How can I get vertical text growing right? The documentation says that with setLayoutOrientation(_:) the text view's bounds are rotated by 90° clockwise, but manually rotating them by -90° with boundsRotation = -90 just rotates everything, including the text which should have the same orientation as before, just expanding in the opposite direction.
After typing anything in a custom text field with undo support, when opening the Edit menu, the undo item is disabled. It seems that setting translatesAutoresizingMaskIntoConstraints=false, a formatter, allowsEditingTextAttributes=true and calling invalidateIntrinsicContentSize() in textDidChange(_:) causes this behaviour.
Is this expected, or is there a workaround?
Here is the code:
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
@IBOutlet weak var textField: NSTextField!
override func loadView() {
view = NSView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
let textField = MyTextField()
textField.frame = CGRect(x: 0, y: 0, width: 100, height: 20)
textField.translatesAutoresizingMaskIntoConstraints = false
textField.formatter = MyFormatter()
textField.allowsEditingTextAttributes = true
view.addSubview(textField)
}
}
class MyTextField: NSTextField {
override func textDidChange(_ notification: Notification) {
super.textDidChange(notification)
super.invalidateIntrinsicContentSize()
}
}
class MyFormatter: Formatter {
override func string(for obj: Any?) -> String? {
return obj as? String
}
override func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool {
obj?.pointee = string as NSString
return true
}
}
I'm trying to implement a text field in a table view that automatically adjusts its height to fit the contained text. My current implementation adjusts its intrinsicContentSize in textDidChange(_:). Unfortunately, NSCell.cellSize(forBounds:) doesn't seem to return the correct height unless setting attributedStringValue and allowsEditingTextAttributes = true for the NSTextField.
Is this expected, or is there a workaround?
Here is the code:
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
var asdf = "asdf fjdskalöf öf fjkldösa jfklödsa kfljsaödkfj klsdajf kldöasj flkjsdöa fkljasö flkjsa öj "
override func loadView() {
view = NSView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
let scrollView = NSScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
let tableView = NSTableView()
tableView.usesAutomaticRowHeights = true
tableView.addTableColumn(NSTableColumn())
tableView.dataSource = self
tableView.delegate = self
scrollView.documentView = tableView
view.addSubview(scrollView)
NSLayoutConstraint.activate([scrollView.topAnchor.constraint(equalTo: view.topAnchor), scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor), scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor)])
}
func numberOfRows(in tableView: NSTableView) -> Int {
return 1
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let view = NSTableCellView()
let text = AutoSizingTextField()
text.translatesAutoresizingMaskIntoConstraints = false
text.cell?.wraps = true
// uncommenting the next 2 lines and commenting out the line after them solves the issue
// text.attributedStringValue = NSAttributedString(string: asdf, attributes: [.font: text.font!, .foregroundColor: NSColor.labelColor])
// text.allowsEditingTextAttributes = true
text.stringValue = asdf
view.addSubview(text)
NSLayoutConstraint.activate([text.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), text.topAnchor.constraint(equalTo: view.topAnchor, constant: 20), text.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20), text.widthAnchor.constraint(equalToConstant: 200)])
return view
}
}
class AutoSizingTextField: NSTextField {
override var intrinsicContentSize: NSSize {
var size = super.intrinsicContentSize
guard let cell = cell else {
return size
}
var frame = frame
frame.size.height = .infinity
size.height = cell.cellSize(forBounds: frame).height
NSLog("intrinsicContentSize \(size)")
return size
}
override func textDidChange(_ notification: Notification) {
super.textDidChange(notification)
invalidateIntrinsicContentSize()
needsLayout = true
layoutSubtreeIfNeeded()
}
override func layout() {
invalidateIntrinsicContentSize()
super.layout()
}
}
When building the code below, two compiler errors appear in AppDelegate.swift:
Value of type 'Slice<MyCollection<MySubCollection>>' has no member 'url'
No exact matches in call to instance method 'remove'
When moving the first 2 classes in ViewController.swift to AppDelegate.swift, the issues go away. Is this expected, or a bug?
// AppDelegate.swift
//
import Cocoa
@main
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
var collection: MyCollection<MySubCollection>!
let a = collection.first!.url!
var subCollection: MySubCollection!
collection.remove(subCollection)
}
}
//
// ViewController.swift
//
import Cocoa
class MyCollection<Element>: MyCollectionProtocol {
var elements = [Element]()
}
class MySubCollection: MyCollectionProtocol {
var elements = [String]()
var url: URL?
}
protocol MyCollectionProtocol: AnyObject, Collection where Index == Int {
associatedtype Element
var elements: [Element] { get set }
}
extension MyCollectionProtocol {
var startIndex: Index {
return elements.startIndex
}
var endIndex: Index {
return elements.endIndex
}
subscript(position: Index) -> Element {
return elements[position]
}
func index(after i: Index) -> Index {
return elements.index(after: i)
}
}
extension MyCollectionProtocol where Element == String {
func remove(_ element: Element) {
}
}
extension MyCollectionProtocol where Element: MyCollectionProtocol {
func remove(_ element: Element) {
}
}