Post

Replies

Boosts

Views

Activity

Reply to Responsible process launch constraint not working as expected
Hi @DTS Engineer! If found this in the transcript of this video: https://developer.apple.com/videos/play/wwdc2023/10266 "When your app requests a connection to your XPC service, launchd spawns the XPC service and is the parent of that XPC service but your app is "responsible" for that XPC service. If I am not mistaken, XPC service (with a lower "s") refers to an agent or daemon. Or is it just a spelling mistake and refers to a XPC Service? Thanks again! Marc
Jul ’24
Reply to Check if a binary or script is executable
Hi @DTS Engineer! Thanks for your reply. I tried this and it works perfectly. But unfortunately it does not work in a sandboxed environment. Even if our app is not sandboxed at the moment, we plan to sandbox it later this year. So I would be interested in a solution that also works for a sandboxed app. The only solution I found so far is using attributesOfItemAtPath: to get NSFileOwnerAccountName, NSFileGroupOwnerAccountName, and NSFilePosixPermissions and then check these values for the current user. Is there another way to do this from within a sandbox? Thanks.
Jul ’24
Reply to Launch constraints to prevent an agent from being launched manually by a user?
@DTS Engineer Tried this, but then the app doesn't launch anymore: <dict> <key>launch-type</key> <dict> <key>$or</key> <dict> <key>$lt</key> <integer>3</integer> <key>$gt</key> <integer>3</integer> </dict> </dict> </dict> Probably it's the wrong syntax because I get the following error if I launch the app: AMFI: Launch Constraint Violation (enforcing), error info: c[4]p[1]m[2]e[6], ($or operator disallowed for active fact) Unfortunately especially the operators are poorly documented. Any idea? Thanks, Marc
Jul ’24
Reply to Launch constraints to prevent an agent from being launched manually by a user?
Thank you, @DTS Engineer. The correct syntax seems to be: <dict> <key>$or-array</key> <array> <array> <string>$or</string> <dict> <key>launch-type</key> <dict> <key>$lt</key> <integer>3</integer> </dict> </dict> </array> <array> <string>$or</string> <dict> <key>launch-type</key> <dict> <key>$gt</key> <integer>3</integer> </dict> </dict> </array> </array> </dict> Regards, Marc
Jul ’24
Reply to Launch constraints disappear
@DTS Engineer It fails in Xcode 16 beta 3. Also tried your sample project from here: https://developer.apple.com/documentation/security/constraining_a_tool_s_launch_environment but as soon as I upload it for notarizing the constraints also disappear. So the issue seems not to be related to my project.
Jul ’24
Reply to User defaults not updating
@DTS Engineer I don't think that I misuse NSUserDefaults. In the app the user can save different configurations and they will stored in NSUserDefaults as an array of dictionaries. This works as expected. But now I got the request to allow the user to set one of the configurations as the default configuration. So I just wanted to add an additional key to one of the dictionaries in the array to mark it as the default. I also tried "mutableArrayForKeyPath" but even if using this, the user defaults are not updated…
Aug ’24
Reply to NSAttributedString draw in rect
This is how I try to get the font size at the moment but it seems the value is always a bit too small… - (CGFloat)fontSizeToFitInRect:(NSRect)rect minimumFontSize:(CGFloat)minFontSize maximumFontSize:(CGFloat)maxFontSize { CGFloat fontSize = (maxFontSize > minFontSize) ? maxFontSize : NSHeight(rect); CGFloat textHeight = CGFLOAT_MAX; CGFloat textWidth = CGFLOAT_MAX; while ((textHeight > NSHeight(rect) || textWidth > NSWidth(rect)) && fontSize >= minFontSize) { NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithAttributedString:self]; [attrString addAttribute:NSFontAttributeName value:[[NSFontManager sharedFontManager] convertFont:[self font] toSize:--fontSize] range:NSMakeRange(0, [[self string] length]) ]; CGRect usedRect = [attrString boundingRectWithSize:NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX) options:0 context:nil ]; textHeight = ceil(NSHeight(usedRect)); textWidth = ceil(NSWidth(usedRect)); } return fontSize; }
Aug ’24
Reply to NSAttributedString draw in rect
For me it looks like boundingRectWithSize:options:context: just uses the attributed string's font (and its attributes) to calculate a bounding rectangle that could hold any combination of characters with the specific font and font size. The height of the bounding rect is more or less the same, regardless of what combinations of characters I use in the string. So the question is how to get the real bounding rect… 🤷🏻‍♂️
Aug ’24
Reply to NSAttributedString draw in rect
@DTS Engineer Thank you! This looks very promising. In the sample code it works as expected but if I try to create a NSTextLineFragment from an attributed string,typographicBounds always returns {{0, 0}, {0, 0}}… NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:@"test"]; [attrString addAttribute:NSFontAttributeName value:[NSFont systemFontOfSize:90] range:NSMakeRange(0, [[attrString string] length]) ]; NSTextLineFragment *fragment = [[NSTextLineFragment alloc] initWithAttributedString:attrString range:NSMakeRange(0, [[attrString string] length]) ]; CGRect usedRect = [fragment typographicBounds];
Aug ’24
Reply to NSAttributedString draw in rect
@DTS Engineer Thanks, again. I tried your code but it returns more or less the same rect as boundingRectWithSize:options:context:. So it returns the exact same height for a lower case "x" and an upper case "X": x -> {{-66, 0}, {132, 303.63671875}} X -> {{-82.88671875, 0}, {165.7734375, 303.63671875}} Any idea? Thanks…
Aug ’24
Reply to NSAttributedString draw in rect
@DTS Engineer Thanks a lot. Seems this is what I was looking for. This allows me to figure out the best font size for a text to fit in a given rect. The only issue still see is related to drawing the string. For whatever reason half of the string is missing: Here's the code: - (void)drawRect:(NSRect)dirtyRect { [super drawRect:dirtyRect]; NSDictionary *attributes = [NSDictionary dictionaryWithObject:[NSFont systemFontOfSize:10] forKey:NSFontAttributeName]; NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:@"test" attributes:attributes]; // get the font size to make the string fit into the text view CGFloat fontSize = [attrString fontSizeToFitInRect:[self bounds] minimumFontSize:10 maximumFontSize:0 ]; // change the attributed string's font size [attrString addAttribute:NSFontAttributeName value:[[NSFontManager sharedFontManager] convertFont:[attrString font] toSize:fontSize] range:NSMakeRange(0, [attrString length]) ]; // draw the string [attrString drawInRect:[self frame]]; } And here are the extensions I made to the NSAttributedString class to calculate the string's bounds: - (CGFloat)fontSizeToFitInRect:(NSRect)rect minimumFontSize:(CGFloat)minFontSize maximumFontSize:(CGFloat)maxFontSize { CGFloat fontSize = (maxFontSize > minFontSize) ? maxFontSize : NSHeight(rect) * 2; CGFloat textHeight = CGFLOAT_MAX; CGFloat textWidth = CGFLOAT_MAX; while ((textHeight > NSHeight(rect) || textWidth > NSWidth(rect)) && fontSize >= minFontSize) { NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithAttributedString:self]; [attrString addAttribute:NSFontAttributeName value:[[NSFontManager sharedFontManager] convertFont:[self font] toSize:--fontSize] range:NSMakeRange(0, [[self string] length]) ]; CGRect usedRect = [attrString bounds]; textHeight = ceil(NSHeight(usedRect)); textWidth = ceil(NSWidth(usedRect)); } return fontSize; } - (CGRect)bounds { CGRect usedRect = CGRectZero; CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)self); NSArray *ctRuns = (__bridge NSArray*)CTLineGetGlyphRuns(line); for (id ctRun in ctRuns) { NSDictionary *attributes = (__bridge NSDictionary *)CTRunGetAttributes((CTRunRef)ctRun); id font = attributes[(NSString *)kCTFontAttributeName]; if (font) { size_t runGlyphsCount = CTRunGetGlyphCount((CTRunRef)ctRun); CGGlyph glyphs[runGlyphsCount]; CTRunGetGlyphs((CTRunRef)ctRun, CFRangeMake(0, 0), glyphs); CGRect runRects[runGlyphsCount]; CTFontGetBoundingRectsForGlyphs((CTFontRef)font, kCTFontOrientationDefault, glyphs, runRects, runGlyphsCount); for (size_t i = 0; i < runGlyphsCount; i++) { CGRect rect = runRects[i]; CGFloat width = usedRect.size.width + rect.size.width; CGFloat height = MAX(usedRect.size.height, rect.size.height); CGFloat y = MIN(usedRect.origin.y, rect.origin.y); usedRect = CGRectMake(usedRect.origin.x, y, width, height); } } else { break; } } return usedRect; } The string rect is a bit smaller than the rectangle of the view it should be drawn into. So I wonder why the string is cut off. With upper and lower case characters it looks like this: Any idea? Thank you very much. Regards, Marc
Aug ’24