Unfortunately all these tips, July 2021, BigSur 11.4 and the Text refuses to fill its parent's Size.
We could really do pixel perfection in AppKit.
struct ContentView : View {
var message: String
var body: some View {
ScrollView {
VStack {
Text(message)
.font(.subheadline)
.lineLimit(nil)
.background(Color(.sRGB, white: 0.86, opacity: 1))
}.frame(maxWidth: .infinity)
}
.border(Color.red)
}
}
Post
Replies
Boosts
Views
Activity
This is not an answer.
I wanted to note that my errors stem from the use of NSTask.
I have created some helper build scripts in swift to automate a new app build.
These are compiled and can be run from within Xcode as well or as useful command lines.
It will spawn an NSTask (Now renamed Process in swift) where I would do something like this
/usr/bin/codesign --remove-signature "/my file....."
If I ran this command in terminal, all works well.
Buy if I ran under my script, using an NSTask I see errors like the harmless [logging-persist] and others
It seems as if the apple tools are not happy running as child processes under my NSTask.
Any advice on how to configure NSTask properly.
Went through the entire process of fully symbolicating a crash.
And I was rewarded with some more gold nuggets.
NodeFactory.appendChildren(_:_:_:_:_:_:) (in com.id-design.v7.whatsizehelper) (NodeFactory.swift:256)
let modTimeInSeconds: Int32 = {}() is obviously crashing.
Also another clue, it crashes always on the same folder.
So the meta data for this folder is 'wrong' ?
let modTimeInSeconds: Int32 = {
if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_MODTIME)) != 0 {
aligningBuffer.copyMemory(from: UnsafeRawBufferPointer(start: field, count: MemoryLayout<timespec>.size))
let time = aligningBuffer.baseAddress!.load(as: timespec.self)
// the following will fails cause of memory misalignment
// let time = field.load(as: timespec.self)
field += MemoryLayout<timespec>.size
return Int32(time.tv_sec)
}
return 0
}()
I could share some more code on a direct message basis, it you are up for a challenge.
My pain is that I can't reproduce it.
It just happens on a few 'lucky' customer machines. And these machines are recent. No old software or old file systems.
I will add the 'ATTR_CMN_ERROR' and see if that will prevent me from digging deeper into trouble.
It is possible these troubled folders are returning some error and instead of bailing out early I'm continuing to read the rest of the pointer.
This class, the one that uses the getattrlistbulk was my last one to move to swift.
The previous version using Objective-C was working.
Mixing both obj-c and swift requires much more mental effort.
Imagine speaking English and French in the same conversation randomly.
Maybe I should eat it and revert this back the C base implementation.
Again thank you very much for the tips.
Klajd Deda
let myEmail = "kdeda" + "@" + "mac.com"
The ATTR_CMN_ERROR is not triggered.
As as soon as we hit this particular folder boom, we manage to collect ATTR_CMN_NAME, ATTR_CMN_FSID and ATTR_CMN_OBJTYPE and than as soon as we attempt to fetch the ATTR_CMN_MODTIME, boom.
So we are crashing on the same darn portion.
Maybe I should revert this module back to the c version.
let modTimeInSeconds: Int32 = {
if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_MODTIME)) != 0 {
aligningBuffer.copyMemory(from: UnsafeRawBufferPointer(start: field, count: MemoryLayout<timespec>.size))
let time = aligningBuffer.baseAddress!.load(as: timespec.self)
// the following will fails cause of memory misalignment
// let time = field.load(as: timespec.self)
field += MemoryLayout<timespec>.size
return Int32(time.tv_sec)
}
return 0
}()
@Quinn, I did open ticket #787511160 and can provide the main class that calls the getattrlistbulk
Thanks.
This magic is frustrating when it does not work.
I have a SwiftUI view (PhysicalSize) wrapped in NSHostingView that is placed inside a NSTableCellView.
I have set a custom NSTableRowView on the NSTableView and AppKit is setting the proper isEmphasized status when the row is selected.
Good.
Then I'm setting the backgroundStyle of the cells to .emphasized
Good.
However the swift UI is absolutely unaware, that we are being drawn in highlighted mode and the Text color does invert. Not good.
Can some apple genius chime in here.
struct PhysicalSize: View {
var file: File
var body: some View {
HStack {
Spacer()
Text(file.physicalSize.compactFormatted)
.font(.subheadline)
}
}
}
Really ?
Why did apple make this so hard.
I remember there used to be a menu on Xcode to switch this feature on and off.
I guess we need to use 3rd party markdown editors.
Interesting ...
Here are some examples
inode mismatch: '/Applications ' ' 1152921500311879699' vs ' 78133671'
inode mismatch: '/Library ' ' 1152921500311879700' vs ' 78110879'
inode mismatch: '/System/Library/Assets ' ' 1152921500312008804' vs ' 78132729'
inode mismatch: '/System/Library/AssetsV2 ' ' 1152921500312008805' vs ' 78131512'
inode mismatch: '/System/Library/Caches ' ' 1152921500312115767' vs ' 78132730'
inode mismatch: '/System/Library/Speech ' ' 1152921500312658038' vs ' 78131497'
inode mismatch: '/System/Volumes/Data ' ' 1152921500312709177' vs ' 1152921500311879682'
inode mismatch: '/System/Volumes/Preboot ' ' 1152921500312709197' vs ' 2'
inode mismatch: '/System/Volumes/Update ' ' 1152921500312709199' vs ' 2'
inode mismatch: '/System/Volumes/VM ' ' 1152921500312709200' vs ' 2'
inode mismatch: '/Users ' ' 1152921500312764772' vs ' 319'
inode mismatch: '/Volumes ' ' 1152921500312764773' vs ' 320'
inode mismatch: '/Volumes/970Raid ' ' 78720565' vs ' 2'
inode mismatch: '/Volumes/Macintosh HD ' ' 78716885' vs ' 2'
inode mismatch: '/Volumes/Macintosh HD - Data ' ' 78716879' vs ' 2'
inode mismatch: '/Volumes/TimeMachine ' ' 78716884' vs ' 2'
inode mismatch: '/Volumes/Vault ' ' 78716876' vs ' 2'
inode mismatch: '/cores ' ' 1152921500312764847' vs ' 321'
inode mismatch: '/dev ' ' 1152921500312764848' vs ' 388'
inode mismatch: '/opt ' ' 1152921500312764850' vs ' 324'
inode mismatch: '/private ' ' 1152921500312764851' vs ' 78132742'
inode mismatch: '/usr/libexec/cups ' ' 1152921500312768002' vs ' 78110424'
inode mismatch: '/usr/local ' ' 1152921500312773577' vs ' 78110530'
inode mismatch: '/usr/share/snmp ' ' 1152921500312787193' vs ' 78110532'
/Volumes/$* are mounts.
The left column is the 'inode' from getattrlistbulk
The right is the 'inode' as I fetch using lstat
typedef struct IDDNodeAttribute {
uint32_t length; // ATTR_BIT_MAP_COUNT
attribute_set_t returned; // ATTR_CMN_RETURNED_ATTRS
char *name;
attrreference_t name_info; // ATTR_CMN_NAME
fsid_t fsid; // ATTR_CMN_FSID
fsobj_type_t obj_type; // ATTR_CMN_OBJTYPE
struct timespec modtime; // ATTR_CMN_MODTIME
uint64_t inode; // ATTR_CMN_FILEID
struct {
u_int32_t link_count; // ATTR_FILE_LINKCOUNT
off_t alloc_size; // ATTR_FILE_ALLOCSIZE
off_t total_size; // ATTR_FILE_TOTALSIZE
};
} __attribute__((aligned(4), packed)) IDDNodeAttribute;
// buffer to place our results
const int IDDNodeAttributeBufferSize = 32 * sizeof(IDDNodeAttribute);
struct attrlist attrList = {
.bitmapcount = ATTR_BIT_MAP_COUNT,
.commonattr = ATTR_CMN_RETURNED_ATTRS | ATTR_CMN_NAME | ATTR_CMN_FSID | ATTR_CMN_OBJTYPE | ATTR_CMN_MODTIME | ATTR_CMN_FILEID,
.dirattr = ATTR_DIR_ENTRYCOUNT,
.fileattr = ATTR_FILE_LINKCOUNT | ATTR_FILE_ALLOCSIZE | ATTR_FILE_TOTALSIZE
};
int itemCount = getattrlistbulk(dirfd, &attrList, attrBuf, IDDNodeAttributeBufferSize, 1);
if (itemCount == -1) {
_logError(NSStringFromSelector(_cmd), [NSString stringWithFormat:@"error: '%ld = %s' path: '%s'", (long)errno, strerror(errno), path]);
break;
} else if (itemCount == 0) {
break;
} else {
char* entry_start = attrBuf;
for (int index = 0; index < itemCount; index++) {
IDDNode* child = [self _fetchChild:&entry_start :filePath :pnode];
if (child) {
[rv addObject:child];
}
}
}
- (IDDNode*)_fetchChild:(char**)entry_start :(NSString*)parentPath :(uint64)pnode {
IDDNodeAttribute attribute;
char* field = *entry_start;
attribute.length = *(uint32_t *)field;
field += sizeof(uint32_t);
*entry_start += attribute.length;
attribute.returned = *(attribute_set_t *)field;
field += sizeof(attribute_set_t);
if (attribute.returned.commonattr & ATTR_CMN_NAME) {
attribute.name = field;
attribute.name_info = *(attrreference_t *)field;
field += sizeof(attrreference_t);
// DEBUG
NSString* childPath = [parentPath stringByAppendingPathComponent:[NSString stringWithUTF8String:(attribute.name + attribute.name_info.attr_dataoffset)]];
_logInfo(NSStringFromSelector(_cmd), [NSString stringWithFormat:@"filePath: '%@'", childPath]);
}
if (attribute.returned.commonattr & ATTR_CMN_FSID) {
attribute.fsid = *(fsid_t *)field;
field += sizeof(fsid_t);
int32_t fileSystemID = (int32_t)attribute.fsid.val[0];
// DEBUG
NSString* childPath = [parentPath stringByAppendingPathComponent:[NSString stringWithUTF8String:(attribute.name + attribute.name_info.attr_dataoffset)]];
_logInfo(NSStringFromSelector(_cmd), [NSString stringWithFormat:@"filePath: '%@' fileSystemID: '%d'", childPath, fileSystemID]);
}
if (attribute.returned.commonattr & ATTR_CMN_OBJTYPE) {
attribute.obj_type = *(fsobj_type_t *)field;
field += sizeof(fsobj_type_t);
// DEBUG
NSString* childPath = [parentPath stringByAppendingPathComponent:[NSString stringWithUTF8String:(attribute.name + attribute.name_info.attr_dataoffset)]];
_logInfo(NSStringFromSelector(_cmd), [NSString stringWithFormat:@"filePath: '%@' type: '%@'", childPath, [self _fileType:attribute.obj_type]]);
}
if (attribute.returned.commonattr & ATTR_CMN_MODTIME) {
struct timespec time = *(struct timespec*)field;
field += sizeof(struct timespec);
NSDate* modificationDate = [NSDate dateWithTimeIntervalSince1970:time.tv_sec];
// DEBUG
NSString* childPath = [parentPath stringByAppendingPathComponent:[NSString stringWithUTF8String:(attribute.name + attribute.name_info.attr_dataoffset)]];
_logInfo(NSStringFromSelector(_cmd), [NSString stringWithFormat:@"filePath: '%@' modificationDate: '%@'", childPath, modificationDate]);
}
if (attribute.returned.commonattr & ATTR_CMN_FILEID) {
attribute.inode = *(uint64_t *)field;
// DEDA DEBUG
struct stat file_status;
NSString* childPath = [parentPath stringByAppendingPathComponent:[NSString stringWithUTF8String:(attribute.name + attribute.name_info.attr_dataoffset)]];
_logInfo(NSStringFromSelector(_cmd), [NSString stringWithFormat:@"filePath: '%@' inode: '%lld'", childPath, attribute.inode]);
if (lstat((const char *)[childPath fileSystemRepresentation], &file_status) == 0) {
int64_t inode2 = file_status.st_ino;
if (attribute.inode != inode2) {
_logError(NSStringFromSelector(_cmd), [NSString stringWithFormat:@"filePath: '%@' inode mismatch: '%lld'", childPath, inode2]);
} else {
_logInfo(NSStringFromSelector(_cmd), [NSString stringWithFormat:@"filePath: '%@' inode match: '%lld'", childPath, inode2]);
}
}
field += sizeof(uint64_t);
}
return nil;
}
After spending a few more hours debuging this, it is possible I have a bad pointer arithmetic somewhere.
However this code fails on about a dozen paths in my giant file system. (more than 4m inodes)
These are special links, indeed, I knew a few under /Volume/ were mounts, but forgot that some others are also links such as /Applications
[macos-bigsur]/usr/local> ls -ail /
12886009979 drwxrwxr-x 7 root admin 224 Feb 4 11:00 Applications/
[macos-bigsur]/usr/local> ls -ail /System/Volumes/Data/
12886009979 drwxrwxr-x 7 root admin 224 Feb 4 11:00 Applications/
/Applications to /System/Volumes/Data/Applications
My problem comes from inconsistent results of stat() vs getattrlistbulk()
Now if I could just figure that out :-)
Small world.
I have been banging my head for hours on this.
I have a real SwiftUI app, with one Window.
When this Window (mainWindow/keyWindow) is minimized an icon is added on the dock.
Now if i click on the app icon, i expect this minimized window to expand again.
But it does not.
If i switch to another app and than click on the app icon on the doc, the minimized window is expanded as expected.
It appears the app thinks it is still active applicationDidResignActive: is not called.
@eskimo What magic is going on pls ?
This is a known bug and has been fixed on Xcode 14, beta 5 and macOS 13.
If you need this feature on older systems, such as macOS 11 + you will need to go back and use a MainMenu.xib and an AppDelegate
struct SwiftUIView: View {
var body: some View {
Text("Hello, SwiftUI!")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
@main
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet var window: NSWindow!
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 480, height: 270),
styleMask: [.miniaturizable, .closable, .resizable, .titled],
backing: .buffered, defer: false)
window.center()
window.title = "No Storyboard Window"
window.contentView = NSHostingView(rootView: SwiftUIView())
window.makeKeyAndOrderFront(nil)
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
return true
}
}