Post

Replies

Boosts

Views

Activity

Passing nil to NEFilterDataProvider.apply(_:completionHandler:) causes error and doesn't apply default settings as documented
I'm trying to adapt the Filter Network Traffic sample code found at https://developer.apple.com/documentation/networkextension/filtering_network_traffic In FilterDataProvider.swift I've replaced the argument passed to NEFilterDataProvider.apply(_:completionHandler:) with nil, which according to the documentation should apply the default settings. Instead I'm getting the following error: Error Domain=NEFilterErrorDomain Code=1 "The settings parameter doesn’t correspond to a NEFilterSettings object" (translated from my local language) (When logging the error with os_log, the Console app just shows it as <private>. A NSLog call instead displays it correctly.) After that the internet doesn't seem to work at all anymore and I have to trash the app to make the internet work again. (If the bin is not completely empty before trashing the app from the Applications folder, I'm prompted that there is another operation in progress like moving a file.) If a nil parameter doesn't work, what is the correct way of not filtering anything, but just observing all the network traffic?
1
0
416
Mar ’23
Listing all apps with App Store Connect API returns error ENTITY_INVALID
I'm using this code to get all apps in App Store Connect: let jwt = ... var request = URLRequest(url: URL(string: "https://api.appstoreconnect.apple.com/v1/apps")!) request.setValue("Bearer \(jwt)", forHTTPHeaderField: "Authorization") let session = URLSession(configuration: .ephemeral) let task = session.dataTask(with: request) { data, response, error in if let error = error { print(error) } else if let data = data { print(String(data: data, encoding: .utf8)) } } task.resume() But the response is an error status: 400, code: ENTITY_INVALID, title: JSON processing failed. What entity is this error referring to? And what JSON is invalid? The JWT token seems to be fine, since when using a random value I get an error 401 NOT_AUTHORIZED.
0
0
559
Mar ’23
Force app appearance in UI tests to be light or dark
In my UI test I'm trying to force the app's appearance (light or dark). When the system appearance is light, I can force the app to be dark with this code: var app = XCUIApplication() app.launchArguments += ["-AppleInterfaceStyle", "Dark"] app.launch() But replacing Dark with Light doesn't have any effect: if the system appearance is dark: the app remains dark. Is this not possible?
0
0
474
Mar ’23
Using custom shadow path on NSView
Unfortunately it seems that setting the shadow attributes on the layer directly doesn't work: let shadowView = NSView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) shadowView.wantsLayer = true shadowView.layer!.backgroundColor = .white shadowView.layer!.shadowRadius = 50 shadowView.layer!.shadowColor = .black shadowView.layer!.shadowOffset = CGSize(width: 0, height: -30) shadowView.layer!.shadowPath = CGPath(roundedRect: shadowView.bounds, cornerWidth: 25, cornerHeight: 25, transform: nil) Setting the NSView.shadow property instead works: let shadowView = NSView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))let shadow = NSShadow() shadow.shadowBlurRadius = 50 shadow.shadowColor = .black shadow.shadowOffset = CGSize(width: 0, height: -30) shadowView.shadow = shadow shadowView.wantsLayer = true shadowView.layer!.backgroundColor = .white But NSShadow doesn't support a custom path. What's the easiest way to set a shadow with a custom path?
Topic: UI Frameworks SubTopic: AppKit Tags:
0
0
515
Mar ’23
Localized name for default sounds in /System/Library/Sounds
In the Mail settings one can choose one of the default sounds located at /System/Library/Sounds. Playing them is easy, e.g. with NSSound(named: "Purr")?.play(), but how can I show a localized name for those sounds as Mail does? I couldn't find any way of getting a localized name. Would I have to manually translate each one to each supported language?
Topic: UI Frameworks SubTopic: AppKit Tags:
0
0
458
Mar ’23
Mismatching locale identifiers for default languages in Xcode and App Store Connect
The list of "main" languages that can be added in Xcode in the project's Info panel (i.e. the ones that can be added without diving into the long submenu) are basically the same that can be added in App Store Connect (except that Xcode also lists Chinese (Hong Kong) (zh-HK) and English (India) (en-IN) which don't exist in App Store Connect). But I noticed that the locale identifiers sometimes refer to different regions: e.g. Xcode has Spanish (es) and Spanish (Latin America) (es-419) while App Store Connect uses Spanish (Spain) and Spanish (Mexico) which when downloaded through the App Store Connect API have the identifiers en-ES and en-MX. Forgive my ignorance, but does that mean that the language used in Latin America and Mexico is the same? Or should I instead select the Mexico variant in Xcode so that the locale identifiers used in the app and on the App Store match? All the mismatching locales are (Xcode first, App Store Connect second): ar vs. ar-SA de vs de-DE en vs en-US es vs es-ES es-419 vs es-MX fr vs fr-FR nl vs nl-NL
0
0
685
Mar ’23
Reading Finder Info ATTR_CMN_FNDRINFO with getattrlistbulk
After successfully implementing a scan with getattrlistbulk (thanks to https://developer.apple.com/forums/thread/656787/), I'm now trying for each file to get whether the extension is shown in the Finder or not. I think this could be read from the Finder Info (i.e.ATTR_CMN_FNDRINFO), although I'm not sure, since there doesn't seem do be any documentation about what this attribute actually contains. From the setattrlist documentation archive it seems that it is char[32], and I've tried different changes within readUnaligned() so that it would work with an array, but I couldn't get it to work. Below is my current implementation. The comment How to get Finder Info? shows where the implementation currently doesn't work. class AppDelegate: NSObject, NSApplicationDelegate { private static var attributeKeys: attrlist = { var attributeKeys = attrlist() attributeKeys.bitmapcount = u_short(ATTR_BIT_MAP_COUNT) attributeKeys.commonattr = attrgroup_t(ATTR_CMN_RETURNED_ATTRS) | attrgroup_t(bitPattern: ATTR_CMN_ERROR | ATTR_CMN_NAME | ATTR_CMN_OBJTYPE | ATTR_CMN_MODTIME | ATTR_CMN_FNDRINFO | ATTR_CMN_FILEID) attributeKeys.fileattr = attrgroup_t(bitPattern: ATTR_FILE_DATALENGTH) return attributeKeys }() private let bufferWithAlignment16 = UnsafeMutableRawBufferPointer.allocate(byteCount: 256, alignment: 16) func applicationDidFinishLaunching(_ notification: Notification) { let openPanel = NSOpenPanel() openPanel.canChooseDirectories = true openPanel.canChooseFiles = false openPanel.runModal() try! scan(directoryPath: openPanel.urls[0].path) } deinit { bufferWithAlignment16.deallocate() } func scan(directoryPath: String) throws { let fileDescriptor = open(directoryPath, O_RDONLY) if fileDescriptor < 0 { throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno)) } defer { let result = close(fileDescriptor) assert(result == 0) } let attributeBuffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 2048, alignment: 16) defer { attributeBuffer.deallocate() } while true { let itemCount = Int(getattrlistbulk(fileDescriptor, &AppDelegate.attributeKeys, attributeBuffer.baseAddress!, attributeBuffer.count, 0)) if itemCount == 0 { return } else if itemCount > 0 { var entryOffset = attributeBuffer.baseAddress! for _ in 0..<itemCount { let length = Int(entryOffset.load(as: UInt32.self)) try unpackResources(at: entryOffset + MemoryLayout<UInt32>.size, parentDirectory: directoryPath) entryOffset += length } } else if errno != EINTR { throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno)) } } } private func unpackResources(at attributeOffset: UnsafeMutableRawPointer, parentDirectory: String) throws { var attributeOffset = attributeOffset let returned = attributeOffset.load(as: attribute_set_t.self) attributeOffset += MemoryLayout<attribute_set_t>.size var error: Error? if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_ERROR)) != 0 { error = NSError(domain: NSPOSIXErrorDomain, code: Int(attributeOffset.load(as: UInt32.self))) attributeOffset += MemoryLayout<UInt32>.size } let name: String if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_NAME)) != 0 { let nameInfo = attributeOffset.load(as: attrreference_t.self) name = String(cString: (attributeOffset + Int(nameInfo.attr_dataoffset)).assumingMemoryBound(to: CChar.self)) attributeOffset += MemoryLayout<attrreference_t>.size } else { name = "" } let fileType: fsobj_type_t if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_OBJTYPE)) != 0 { fileType = attributeOffset.load(as: fsobj_type_t.self) attributeOffset += MemoryLayout<fsobj_type_t>.size } else { fileType = VNON.rawValue } var modificationDate: Date? if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_MODTIME)) != 0 { modificationDate = Date(timeIntervalSince1970: TimeInterval(readUnaligned(pointer: attributeOffset, as: timespec.self).tv_sec)) attributeOffset += MemoryLayout<timespec>.size } // How to get Finder Info? let finderInfo: [Int8] if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_FNDRINFO)) != 0 { finderInfo = readUnaligned(pointer: attributeOffset, as: [Int8].self) attributeOffset += MemoryLayout<Int8>.size } else { finderInfo = [] } let fileId: UInt64 if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_FILEID)) != 0 { fileId = readUnaligned(pointer: attributeOffset, as: UInt64.self) attributeOffset += MemoryLayout<UInt64>.size } else { fileId = 0 } let size: Int64 if (returned.fileattr & attrgroup_t(bitPattern: ATTR_FILE_DATALENGTH)) != 0 { size = Int64(readUnaligned(pointer: attributeOffset, as: off_t.self)) attributeOffset += MemoryLayout<off_t>.size } else { size = 0 } if let error = error { throw error } let isDirectory = fileType == VDIR.rawValue let isSymbolicLink = fileType == VLNK.rawValue print(name, isDirectory, isSymbolicLink, modificationDate as Any, finderInfo, fileId, size) } private func readUnaligned<Result>(pointer: UnsafeRawPointer, as: Result.Type) -> Result { bufferWithAlignment16.copyMemory(from: UnsafeRawBufferPointer(start: pointer, count: MemoryLayout<Result>.size)) return bufferWithAlignment16.baseAddress!.load(as: Result.self) } }
1
0
541
Apr ’23
Error when trying to set access permissions of file owned by user
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?
1
0
416
Apr ’23
Components of NSDatePicker inside NSTableView cannot be selected
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?
Topic: UI Frameworks SubTopic: AppKit Tags:
1
0
484
Apr ’23
filecopy function is slower than cp command
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?
0
0
624
May ’23
NSTextField frame automatically hugs content when superview is AVPlayerView.contentOverlayView
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) // } } }
0
0
838
Jun ’23
Comparing local and uploaded app screenshots with App Store Connect API
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.
0
0
587
Jun ’23
NSTextField and NSParagraphStyle: right align left-to-right text and left align right-to-left text
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?
0
0
822
Jul ’23
Vertical text from left to right with NSTextView
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.
0
0
870
Jul ’23
Passing nil to NEFilterDataProvider.apply(_:completionHandler:) causes error and doesn't apply default settings as documented
I'm trying to adapt the Filter Network Traffic sample code found at https://developer.apple.com/documentation/networkextension/filtering_network_traffic In FilterDataProvider.swift I've replaced the argument passed to NEFilterDataProvider.apply(_:completionHandler:) with nil, which according to the documentation should apply the default settings. Instead I'm getting the following error: Error Domain=NEFilterErrorDomain Code=1 "The settings parameter doesn’t correspond to a NEFilterSettings object" (translated from my local language) (When logging the error with os_log, the Console app just shows it as <private>. A NSLog call instead displays it correctly.) After that the internet doesn't seem to work at all anymore and I have to trash the app to make the internet work again. (If the bin is not completely empty before trashing the app from the Applications folder, I'm prompted that there is another operation in progress like moving a file.) If a nil parameter doesn't work, what is the correct way of not filtering anything, but just observing all the network traffic?
Replies
1
Boosts
0
Views
416
Activity
Mar ’23
Listing all apps with App Store Connect API returns error ENTITY_INVALID
I'm using this code to get all apps in App Store Connect: let jwt = ... var request = URLRequest(url: URL(string: "https://api.appstoreconnect.apple.com/v1/apps")!) request.setValue("Bearer \(jwt)", forHTTPHeaderField: "Authorization") let session = URLSession(configuration: .ephemeral) let task = session.dataTask(with: request) { data, response, error in if let error = error { print(error) } else if let data = data { print(String(data: data, encoding: .utf8)) } } task.resume() But the response is an error status: 400, code: ENTITY_INVALID, title: JSON processing failed. What entity is this error referring to? And what JSON is invalid? The JWT token seems to be fine, since when using a random value I get an error 401 NOT_AUTHORIZED.
Replies
0
Boosts
0
Views
559
Activity
Mar ’23
Force app appearance in UI tests to be light or dark
In my UI test I'm trying to force the app's appearance (light or dark). When the system appearance is light, I can force the app to be dark with this code: var app = XCUIApplication() app.launchArguments += ["-AppleInterfaceStyle", "Dark"] app.launch() But replacing Dark with Light doesn't have any effect: if the system appearance is dark: the app remains dark. Is this not possible?
Replies
0
Boosts
0
Views
474
Activity
Mar ’23
Using custom shadow path on NSView
Unfortunately it seems that setting the shadow attributes on the layer directly doesn't work: let shadowView = NSView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) shadowView.wantsLayer = true shadowView.layer!.backgroundColor = .white shadowView.layer!.shadowRadius = 50 shadowView.layer!.shadowColor = .black shadowView.layer!.shadowOffset = CGSize(width: 0, height: -30) shadowView.layer!.shadowPath = CGPath(roundedRect: shadowView.bounds, cornerWidth: 25, cornerHeight: 25, transform: nil) Setting the NSView.shadow property instead works: let shadowView = NSView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))let shadow = NSShadow() shadow.shadowBlurRadius = 50 shadow.shadowColor = .black shadow.shadowOffset = CGSize(width: 0, height: -30) shadowView.shadow = shadow shadowView.wantsLayer = true shadowView.layer!.backgroundColor = .white But NSShadow doesn't support a custom path. What's the easiest way to set a shadow with a custom path?
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
0
Boosts
0
Views
515
Activity
Mar ’23
Rearranging in-app purchases listed in App Store
I created in-app purchases in ascending order of their price, but in the App Store they seem to be listed in the reverse order. I would like to sort the in-app purchases by ascending price, but cannot find a way to do so. Is there a way?
Replies
0
Boosts
0
Views
583
Activity
Mar ’23
Localized name for default sounds in /System/Library/Sounds
In the Mail settings one can choose one of the default sounds located at /System/Library/Sounds. Playing them is easy, e.g. with NSSound(named: "Purr")?.play(), but how can I show a localized name for those sounds as Mail does? I couldn't find any way of getting a localized name. Would I have to manually translate each one to each supported language?
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
0
Boosts
0
Views
458
Activity
Mar ’23
Mismatching locale identifiers for default languages in Xcode and App Store Connect
The list of "main" languages that can be added in Xcode in the project's Info panel (i.e. the ones that can be added without diving into the long submenu) are basically the same that can be added in App Store Connect (except that Xcode also lists Chinese (Hong Kong) (zh-HK) and English (India) (en-IN) which don't exist in App Store Connect). But I noticed that the locale identifiers sometimes refer to different regions: e.g. Xcode has Spanish (es) and Spanish (Latin America) (es-419) while App Store Connect uses Spanish (Spain) and Spanish (Mexico) which when downloaded through the App Store Connect API have the identifiers en-ES and en-MX. Forgive my ignorance, but does that mean that the language used in Latin America and Mexico is the same? Or should I instead select the Mexico variant in Xcode so that the locale identifiers used in the app and on the App Store match? All the mismatching locales are (Xcode first, App Store Connect second): ar vs. ar-SA de vs de-DE en vs en-US es vs es-ES es-419 vs es-MX fr vs fr-FR nl vs nl-NL
Replies
0
Boosts
0
Views
685
Activity
Mar ’23
Reading Finder Info ATTR_CMN_FNDRINFO with getattrlistbulk
After successfully implementing a scan with getattrlistbulk (thanks to https://developer.apple.com/forums/thread/656787/), I'm now trying for each file to get whether the extension is shown in the Finder or not. I think this could be read from the Finder Info (i.e.ATTR_CMN_FNDRINFO), although I'm not sure, since there doesn't seem do be any documentation about what this attribute actually contains. From the setattrlist documentation archive it seems that it is char[32], and I've tried different changes within readUnaligned() so that it would work with an array, but I couldn't get it to work. Below is my current implementation. The comment How to get Finder Info? shows where the implementation currently doesn't work. class AppDelegate: NSObject, NSApplicationDelegate { private static var attributeKeys: attrlist = { var attributeKeys = attrlist() attributeKeys.bitmapcount = u_short(ATTR_BIT_MAP_COUNT) attributeKeys.commonattr = attrgroup_t(ATTR_CMN_RETURNED_ATTRS) | attrgroup_t(bitPattern: ATTR_CMN_ERROR | ATTR_CMN_NAME | ATTR_CMN_OBJTYPE | ATTR_CMN_MODTIME | ATTR_CMN_FNDRINFO | ATTR_CMN_FILEID) attributeKeys.fileattr = attrgroup_t(bitPattern: ATTR_FILE_DATALENGTH) return attributeKeys }() private let bufferWithAlignment16 = UnsafeMutableRawBufferPointer.allocate(byteCount: 256, alignment: 16) func applicationDidFinishLaunching(_ notification: Notification) { let openPanel = NSOpenPanel() openPanel.canChooseDirectories = true openPanel.canChooseFiles = false openPanel.runModal() try! scan(directoryPath: openPanel.urls[0].path) } deinit { bufferWithAlignment16.deallocate() } func scan(directoryPath: String) throws { let fileDescriptor = open(directoryPath, O_RDONLY) if fileDescriptor < 0 { throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno)) } defer { let result = close(fileDescriptor) assert(result == 0) } let attributeBuffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 2048, alignment: 16) defer { attributeBuffer.deallocate() } while true { let itemCount = Int(getattrlistbulk(fileDescriptor, &AppDelegate.attributeKeys, attributeBuffer.baseAddress!, attributeBuffer.count, 0)) if itemCount == 0 { return } else if itemCount > 0 { var entryOffset = attributeBuffer.baseAddress! for _ in 0..<itemCount { let length = Int(entryOffset.load(as: UInt32.self)) try unpackResources(at: entryOffset + MemoryLayout<UInt32>.size, parentDirectory: directoryPath) entryOffset += length } } else if errno != EINTR { throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno)) } } } private func unpackResources(at attributeOffset: UnsafeMutableRawPointer, parentDirectory: String) throws { var attributeOffset = attributeOffset let returned = attributeOffset.load(as: attribute_set_t.self) attributeOffset += MemoryLayout<attribute_set_t>.size var error: Error? if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_ERROR)) != 0 { error = NSError(domain: NSPOSIXErrorDomain, code: Int(attributeOffset.load(as: UInt32.self))) attributeOffset += MemoryLayout<UInt32>.size } let name: String if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_NAME)) != 0 { let nameInfo = attributeOffset.load(as: attrreference_t.self) name = String(cString: (attributeOffset + Int(nameInfo.attr_dataoffset)).assumingMemoryBound(to: CChar.self)) attributeOffset += MemoryLayout<attrreference_t>.size } else { name = "" } let fileType: fsobj_type_t if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_OBJTYPE)) != 0 { fileType = attributeOffset.load(as: fsobj_type_t.self) attributeOffset += MemoryLayout<fsobj_type_t>.size } else { fileType = VNON.rawValue } var modificationDate: Date? if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_MODTIME)) != 0 { modificationDate = Date(timeIntervalSince1970: TimeInterval(readUnaligned(pointer: attributeOffset, as: timespec.self).tv_sec)) attributeOffset += MemoryLayout<timespec>.size } // How to get Finder Info? let finderInfo: [Int8] if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_FNDRINFO)) != 0 { finderInfo = readUnaligned(pointer: attributeOffset, as: [Int8].self) attributeOffset += MemoryLayout<Int8>.size } else { finderInfo = [] } let fileId: UInt64 if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_FILEID)) != 0 { fileId = readUnaligned(pointer: attributeOffset, as: UInt64.self) attributeOffset += MemoryLayout<UInt64>.size } else { fileId = 0 } let size: Int64 if (returned.fileattr & attrgroup_t(bitPattern: ATTR_FILE_DATALENGTH)) != 0 { size = Int64(readUnaligned(pointer: attributeOffset, as: off_t.self)) attributeOffset += MemoryLayout<off_t>.size } else { size = 0 } if let error = error { throw error } let isDirectory = fileType == VDIR.rawValue let isSymbolicLink = fileType == VLNK.rawValue print(name, isDirectory, isSymbolicLink, modificationDate as Any, finderInfo, fileId, size) } private func readUnaligned<Result>(pointer: UnsafeRawPointer, as: Result.Type) -> Result { bufferWithAlignment16.copyMemory(from: UnsafeRawBufferPointer(start: pointer, count: MemoryLayout<Result>.size)) return bufferWithAlignment16.baseAddress!.load(as: Result.self) } }
Replies
1
Boosts
0
Views
541
Activity
Apr ’23
Error when trying to set access permissions of file owned by user
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?
Replies
1
Boosts
0
Views
416
Activity
Apr ’23
Components of NSDatePicker inside NSTableView cannot be selected
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?
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
1
Boosts
0
Views
484
Activity
Apr ’23
filecopy function is slower than cp command
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?
Replies
0
Boosts
0
Views
624
Activity
May ’23
NSTextField frame automatically hugs content when superview is AVPlayerView.contentOverlayView
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) // } } }
Replies
0
Boosts
0
Views
838
Activity
Jun ’23
Comparing local and uploaded app screenshots with App Store Connect API
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.
Replies
0
Boosts
0
Views
587
Activity
Jun ’23
NSTextField and NSParagraphStyle: right align left-to-right text and left align right-to-left text
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?
Replies
0
Boosts
0
Views
822
Activity
Jul ’23
Vertical text from left to right with NSTextView
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.
Replies
0
Boosts
0
Views
870
Activity
Jul ’23