Post

Replies

Boosts

Views

Activity

Reply to What is changing the size of my window on first appearance?
There is actually some interaction with window restoration, which resets the size of the window after windowDidLoad. What is working is to delay the size calculation until after the window actually gets displayed (after restoration), by replacing [self calculateSize] (essentially the code above) at the end of windowDidLoad with this hack: dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self calculateSize]; }); This appears to point to a problem where the size of the various views is not always set correctly until the window has been displayed. However, I'd love to proved wrong and find out what is the actual cause.
Mar ’24
Reply to What is changing the size of my window on first appearance?
After a lot more experimentation, I've determined that it is nothing to do with something running after windowDidLoad. The problem occurs when I calculate the size of the window content. Here's a version of the code: NSScrollView *scrollView = self.myScrollView; MyContentView *myContentView = [scrollView documentView]; NSSize contentSize = [[self.window contentView] bounds].size; NSSize viewSize = [scrollView contentSize]; CGFloat verticalPadding = contentSize.height - viewSize.height; CGFloat horizontalPadding = contentSize.width - viewSize.width; NSSize myContentSize = [myContentView bounds].size; myContentSize = [NSScrollView frameSizeForContentSize:myContentSize horizontalScrollerClass:[NSScroller class] verticalScrollerClass:[NSScroller class] borderType:NSLineBorder controlSize:NSControlSizeRegular scrollerStyle:NSScrollerStyleOverlay]; myContentSize.height += 1; myContentSize.width += 1; NSSize maximumSize = myContentSize; maximumSize.height += verticalPadding; maximumSize.width += horizontalPadding; The problem is that viewSize, the size of the visible portion of the scroll view, can have one of two different values, which differ by 24. It seems to be arbitrary which of the two values is provided. Thus the maximum size, which is then set as the window content size with setContentSize, varies by 24, dependent on nothing that I can see.
Feb ’24
Reply to Struggling with SMJobBless in a sandboxed app
Just to be clear, you can’t use SMJobBless from a sandboxed app. Yes, this is using a non-sandboxed XPC service (essentially the EBAS code), so it shouldn't be running into that sort of problem. SMJobBless has largely been replaced by SMAppService, which can install a daemon. I was hoping to still support macOS 12, while SMAppService is macOS 13 and later. But if I have to switch, I can. [1] The caveat here is that, starting with macOS 14.2, the daemon itself must be sandboxed. That probably nukes my use-case, unfortunately. The daemon has to be able to move files and folders (well, bundles) into and out of specific folders within /Library, which is presumably not allowed in a sandboxed daemon. I was given an entitlement to allow secure file system access, but you can't move folders with that, and so I was thrown back to SMJobBless, but even that avenue looks like it's closing.
Feb ’24
Reply to Struggling with SMJobBless in a sandboxed app
After a long hiatus, I am back working on this application. I have got to the point where the plists are set up correctly, as far as I can tell, and running SMJobBlessUtil-python3.py check doesn't report any errors. However, the call to SMJobBless fails with Error Domain=CFErrorDomainLaunchd Code=2. Searching for this leads to problems with the location of the helper tool, but it is exactly where it is supposed to be. I've gone through everything that I can think of to verify that it looks like the EBAS sample code, which is working on my system (macOS 14.2.1, Xcode 15.2, M1 mac). Does anyone have any specific pointers to places that I can check further? Or, if more information is needed, what should I provide/
Feb ’24
Reply to Struggling with SMJobBless in a sandboxed app
OK, that makes sense. I was working with the debug scheme, so only arm64 was available on my iMac, and only x86_64 on the MBP. The workaround requires some rewriting of the Python tool, which I'm not equipped to do myself (I've never taken the time to learn Python), so this will probably go on the back burner for a while, and I'll work on some other areas that are incomplete. However, a question that will need to be answered is whether the issue will cause the privileged helper invocation to fail on arm64. In other words, does the system's checking run into the same problem? If the bug is in otool, then I suspect not, but I don't know the internals, of course.
Jun ’22
Reply to Struggling with SMJobBless in a sandboxed app
OK, I got it to work on the MBP, and it works there. Significantly, the otool output starts off like this: Contents of (__TEXT,__info_plist) section 0000000100003af6 3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 0000000100003b06 2e 30 22 20 65 6e 63 6f 64 69 6e 67 3d 22 55 54 And it is byte-swapped compared to the one on Apple Silicon! So where can I go now?
Jun ’22
Reply to Struggling with SMJobBless in a sandboxed app
I was running the old version with Python 2. I tried the updated version with Python 3, and get the same result. Running otool -P gives me the info.plist as XML, so the system thinks it's OK. Looking at the comments in the utility script: # line looks like this: # # '0000000100000b80\t3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 ' makes me wonder if there's an endianness problem, since the first line has the bytes swapped (0000000100003ada 6d783f3c 6576206c 6f697372 31223d6e). But I'm not familiar enough with Python to know whether that is a valid objection.
Jun ’22
Reply to Struggling with SMJobBless in a sandboxed app
I get what I expect, a hex representation of the plist: Contents of (__TEXT,__info_plist) section 0000000100003ada 6d783f3c 6576206c 6f697372 31223d6e 0000000100003aea 2022302e 6f636e65 676e6964 5455223d 0000000100003afa 22382d46 3c0a3e3f 434f4421 45505954 0000000100003b0a 696c7020 50207473 494c4255 2d222043 0000000100003b1a 70412f2f 2f656c70 4454442f 494c5020 0000000100003b2a 31205453 2f2f302e 20224e45 74746822 0000000100003b3a 2f2f3a70 2e777777 6c707061 6f632e65 0000000100003b4a 54442f6d 502f7344 65706f72 4c797472 0000000100003b5a 2d747369 2e302e31 22647464 703c0a3e 0000000100003b6a 7473696c 72657620 6e6f6973 2e31223d 0000000100003b7a 0a3e2230 6369643c 090a3e74 79656b3c 0000000100003b8a 4246433e 6c646e75 65644965 6669746e 0000000100003b9a 3c726569 79656b2f 3c090a3e 69727473 0000000100003baa 6f3e676e 732e6772 552e6c69 656c656b 0000000100003bba 4b2e656c 6f627965 49647261 6174736e 0000000100003bca 72656c6c 6c6f6f54 74732f3c 676e6972 0000000100003bda 3c090a3e 3e79656b 75424643 656c646e 0000000100003bea 6f666e49 74636944 616e6f69 65567972 0000000100003bfa 6f697372 6b2f3c6e 0a3e7965 74733c09 0000000100003c0a 676e6972 302e363e 74732f3c 676e6972 0000000100003c1a 3c090a3e 3e79656b 75424643 656c646e 0000000100003c2a 656d614e 656b2f3c 090a3e79 7274733c 0000000100003c3a 3e676e69 2e67726f 2e6c6973 6c656b55 0000000100003c4a 2e656c65 6279654b 6472616f 74736e49 0000000100003c5a 656c6c61 6f6f5472 732f3c6c 6e697274 0000000100003c6a 090a3e67 79656b3c 4246433e 6c646e75 0000000100003c7a 72655665 6e6f6973 656b2f3c 090a3e79 0000000100003c8a 7274733c 3e676e69 3c302e31 7274732f 0000000100003c9a 3e676e69 6b3c090a 533e7965 7475414d 0000000100003caa 69726f68 4364657a 6e65696c 2f3c7374 0000000100003cba 3e79656b 613c090a 79617272 09090a3e 0000000100003cca 7274733c 3e676e69 68636e61 6120726f 0000000100003cda 656c7070 6e656720 63697265 646e6120 0000000100003cea 65646920 6669746e 20726569 67726f22 0000000100003cfa 6c69732e 656b552e 656c656c 4350582e 0000000100003d0a 76726553 22656369 646e6120 65632820 0000000100003d1a 66697472 74616369 656c2065 665b6661 0000000100003d2a 646c6569 322e312e 3034382e 3331312e 0000000100003d3a 2e353336 2e303031 2e312e36 2f205d39 0000000100003d4a 7865202a 73747369 202f2a20 6320726f 0000000100003d5a 69747265 61636966 31206574 6569665b 0000000100003d6a 312e646c 382e322e 312e3034 33363331 0000000100003d7a 30312e35 2e362e30 5d362e32 202a2f20 0000000100003d8a 73697865 2a207374 6e61202f 65632064 0000000100003d9a 66697472 74616369 656c2065 665b6661 0000000100003daa 646c6569 322e312e 3034382e 3331312e 0000000100003dba 2e353336 2e303031 2e312e36 205d3331 0000000100003dca 65202a2f 74736978 2f2a2073 646e6120 0000000100003dda 72656320 69666974 65746163 61656c20 0000000100003dea 75735b66 63656a62 554f2e74 203d205d 0000000100003dfa 45593322 36385734 2247334c 732f3c29 0000000100003e0a 6e697274 090a3e67 72612f3c 3e796172 0000000100003e1a 642f3c0a 3e746369 702f3c0a 7473696c 0000000100003e2a 3e 0a (BTW, I'll be away tomorrow, so will get back to things again on Friday.)
Jun ’22
Reply to Two document types in SwiftUI?
It looks like the answer is no. The second DocumentGroup is necessary for opening a file of the second type, but I haven't found a way to make SwiftUI create a document of that type. Using .handlesExternalEvents doesn't seem to help, as it seems to want to open a window defined by a WindowGroup rather than a DocumentGroup. The best idea I've come up with is to create a temporary file and then push the URL for that to openURL, but that leaves the user with a file which they don't actually need, and doesn't replicate the experience of a new document.
Mar ’22