Post

Replies

Boosts

Views

Activity

Reply to Mac Catalyst UIWindowScene requestGeometryUpdateWithPreferences: doesn't respect provided systemFrame origin.
So basically what I'm trying to do is this: //Position the window in the center of the screen, initially. UIScreen *targetScreen = scene.screen;  CGRect initialWindowRect = CGRectMake((targetScreen.bounds.size.width/2.0)-(DEFAULT_SIZE.width/2.0),                                      targetScreen.bounds.size.height/2.0-(DEFAULT_SIZE.height/2.0),                                      DEFAULT_SIZE.width,                                      DEFAULT_SIZE.height); Sometimes the origin is ignored (depending whether or not another window is opened, the system adds a default space between open windows. Typically this is how "New Document" windows open on Mac but you wouldn't always want this behavior (for example the "Welcome to Xcode" window always positions itself in the center of the screen when opening). Also is there a way I can compute NSScreen's visibleFrame property from the Mac Catalyst environment so I can position the window relative to the visible frame (the area not including the menu bar and the dock)? UIScreen.bounds property is  (origin = (x = 0, y = 0), size = (width = 1440, height = 900)) but really I'd like to compute the initial window frame relative to NSScreen's .visibleFrame property which would be {{0, 95}, {1440, 780}}
Topic: UI Frameworks SubTopic: UIKit Tags:
Dec ’22
Reply to Mac Catalyst on Multiple Displays: Using UIWindowSceneGeometryPreferencesMac to set a default window size causes new windows to open on the wrong display
I can't even try setting the frame from the call site with this API:  [application requestSceneSessionActivation:nil                            userActivity:theActivity                                options:activationOptions                           errorHandler:^(NSError * _Nonnull error)     {     }]; } Because there is an error handler but I don't get back the created UIWindowScene on success.... Is it really necessary to have an error handler on opening a window? An error handler on setting a window's frame? Why is everything hard to do? Passing data to a new window has to be done through these absurd NSUserActivity objects.... Like why isn't there a normal API? windowController.window.frame = initialRect; windowController.modelData = modelObject; [windowController showWindow:sender]; I need an error handler to set a frame and to open a window? Am I making a network request? And if I get an error on set frame how exactly am I supposed to handle the error? Set the frame again and hope that it works?
Topic: UI Frameworks SubTopic: UIKit Tags:
Dec ’22
Reply to Sharing Multiple Links at Once on Mac Catalyst Via UIActivityViewController for the Messages Activity?
YES IT IS POSSIBLE! EXCELLENT! Here's something that might be a Catalyst bug, but who knows what they'll say really. My UIActivityItemSource wasn't handling the Messages situation properly because -activityViewController:itemForActivityType: passes in @"com.apple.share.Messages.window" on Catalyst when the Messages activity is selected. This does not match the UIActivityTypeMessage constant, which is @"com.apple.UIKit.activity.Message".
Topic: UI Frameworks SubTopic: UIKit Tags:
Dec ’22
Reply to Mac Catalyst on Multiple Displays: Using UIWindowSceneGeometryPreferencesMac to set a default window size causes new windows to open on the wrong display
I usually don't do this, but I wonder if not enough developers are providing feedback so I'm going to go on a short tangent. Just to go back to my snippet of what I consider to be “normal API”: windowController.window.frame = initialRect; windowController.modelData = modelObject; [windowController showWindow:sender]; This coding style has essentially been “abstracted away” in Catalyst underneath this: NSUserActivity *newWindowActivity = [[NSUserActivity alloc]initWithActivityType:@“my.new.window.activitytype”]; //Our options to pass data to the new window are the following: //Option 1) Write methods to convert a model object to and from one of the types NSUserActivity's userInfo accepts. //Option 2) Make the model object conform to NSSecureCoding and convert it to and from NSData and stuff the NSData in the activity). //Option 3) Pass a "database identifier" and query for the model object on the other end from a singleton and/or database. //In this sample I'm using option 1 because that's the "easiest." Not always possible though. NSArray *modelAsPlist = [modelData propertyListRepresentation]; NSDictionary *modelDictionary = @{@"NewWindowModelData":modelAsPlist}; [newWindowActivity addUserInfoEntriesFromDictionary:modelDictionary]; UISceneActivationRequestOptions *activationOptions = [[UISceneActivationRequestOptions alloc]init]; activationOptions.requestingScene = self.view.window.windowScene; UIApplication *application = [UIApplication sharedApplication]; [application requestSceneSessionActivation:nil userActivity:newWindowActivity options:activationOptions errorHandler:^(NSError * _Nonnull error) { //Whoops the system didn't give me a window. Tough luck. What kind of error handling are application developers expected to do here? }]; And we still haven't achieved the three lines of the "normal API" yet. The controller that needs the model object still hasn't gotten it yet. And the initial frame for the window isn't set. Now on the other end in the UIWindowSceneDelegate: -(void)scene:(UIWindowScene*)scene willConnectToSession:(UISceneSession*)session options:(UISceneConnectionOptions*)connectionOptions { //connectionOptions can have more than 1 activity...we gotta dig for our model object and that's the bottom line because the System says so. NSUserActivity *activityToConfigureWith = nil; for (NSUserActivity *aActivity in connectionOptions.userActivities) { if (aActivity.activityType isEqualToString:@"my.new.window.activitytype"]) { activityToConfigureWith = aActivity; break; } } if (activityToConfigureWith != nil) { NSArray *topLevelModelPlist = activityToConfigureWith.userInfo[@"NewWindowModelData"]; ModelData *model = [ModelData makeWithPropertyList:topLevelModelPlist]; MyViewController *myVC = [[MyViewController alloc]initWithModel:model]; self.window = [[UIWindow alloc]initWithWindowScene:scene]; self.window.rootViewController = myVC; [self.window makeKeyAndVisible]; } else { //Not found. Maybe we have a state restoration activity to configure.. //Or maybe not. Maybe we are just on app launch. We have to sort our way through this pile of user activities just to get started here..it's kind of a mess. } CGRect systemFrame = scene.effectiveGeometry.systemFrame; CGRect newFrame = systemFrame; newFrame.size.width = DEFAULT_WIDTH; newFrame.size.height = DEFAULT_HEIGHT; UIWindowSceneGeometryPreferencesMac *geometryPrefs = [[UIWindowSceneGeometryPreferencesMac alloc]initWithSystemFrame:newFrame]; [scene requestGeometryUpdateWithPreferences:geometryPrefs errorHandler:^(NSError * _Nonnull error) { //Error setting frame. Tough luck! What kind of error handling are application developers expected to do here? }]; } Now in my real app a lot of this code I silo in categories because the amount of code required for such simple tasks is kind of absurd. All we did is 1) create a window 2) set its initial frame and model object and 3) show it on screen. Not sure how this was decided on but IMHO the abstraction is 10x more complex than the internal implementation. At the very least creating and passing data to a new window shouldn't be any harder than creating a new view controller programmatically or using storyboards with -prepareForSegue: But it is a lot harder. And requires lots more boilerplate. This doesn't include the code required to workaround the issue described in FB11885144. If you want to make it easy to port iOS apps to the Mac maybe just expose a NSViewController subclass in the public API that embeds a UIKit view hierarchy inside of it and let developers use them in NSWindows directly? Maybe?
Topic: UI Frameworks SubTopic: UIKit Tags:
Dec ’22
Reply to Crash on iOS 16.2: -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:
Thanks for the reply. That's not my post on Stackoverflow but I'm experiencing a similar crash that percolates up to -_createPreparedCellForGlobalRow:withIndexPath:willDisplay The crash report for my app doesn't actually get to -tableView:cellForRowAtIndexPath: Instead I can see it all starts from my app checking the .visibleCells property on the table view: 0   CoreFoundation                       0x19c789e48 __exceptionPreprocess + 164 1   libobjc.A.dylib                      0x195a5b8d8 objc_exception_throw + 60 2   Foundation                           0x19704a94c _userInfoForFileAndLine + 0 3   UIKitCore                            0x19eaa0888 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 572 4   UIKitCore                            0x19ea744cc -[UITableView _updateVisibleCellsForRanges:createIfNecessary:] + 596 5   UIKitCore                            0x19e9adb28 -[UITableView _updateVisibleCellsNow:] + 1088 6   UIKitCore                            0x19e9785e8 -[UITableView _visibleCellsUsingPresentationValues:] + 340 7   MyApp                      0x103125120 -[MyTableViewSubclass checkIfLoadingCellIsIsVisible] The checkIfLoadingCellIsIsVisible just enumerates the .visibleCells property on the table view, looking to see if a "loading more" cell is in the visible region of the table view. I've been unable to reliably reproduce the crash. Haven't managed to reproduce it at all when attached to the debugger. I picked up two of these crash reports today since I updated to iOS 16.2.
Topic: UI Frameworks SubTopic: UIKit Tags:
Dec ’22
Reply to Mac Catalyst Determine Default Size of NSToolbarItems When Creating them with UIBarButtonItems and SF Symbol Images?
Using the image property on NSToolbarItem and passing in a SF symbol image does not create a toolbar item that matches the size of the other items created through UIBarButtonItem. The image toolbar item is clearly bigger than the ones created with UIBarButtonItem APi. Setting the bordered property to YES (which means only bordered on highlight these days) did the trick.
Topic: UI Frameworks SubTopic: UIKit Tags:
Dec ’22
Reply to Crash on iOS 16.2: -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:
Thanks again for the reply (for some reason I didn't get an email notification for your Comment even though I'm "Watching" this thread." I just hit the crash again. I haven't hit it in a couple days (it isn't easy to reproduce). Exact same crash report as before just now: ** Last Exception Backtrace: 0 CoreFoundation 0x19c789e48 __exceptionPreprocess + 164 1 libobjc.A.dylib 0x195a5b8d8 objc_exception_throw + 60 2 Foundation 0x19704a94c _userInfoForFileAndLine + 0 3 UIKitCore 0x19eaa0888 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 572 4 UIKitCore 0x19ea744cc -[UITableView _updateVisibleCellsForRanges:createIfNecessary:] + 596 5 UIKitCore 0x19e9adb28 -[UITableView _updateVisibleCellsNow:] + 1088 6 UIKitCore 0x19e9785e8 -[UITableView _visibleCellsUsingPresentationValues:] + 34 7 MyApp           0x103125120 -[MyTableViewSubclass checkIfLoadingCellIsIsVisible]** I don't see anywhere in my -tableView:celForRowAtIndexPath: method the possibility of my app returning nil unless for some strange reason UITableView -dequeueReusableCellWithIdentifier:forIndexPath: returned nil in some odd circumstance to me. I've been using my app for a long time on daily basis and this didn't start happening until after I updated to iOS 16.2, not sure if that's related though.
Topic: UI Frameworks SubTopic: UIKit Tags:
Dec ’22
Reply to Crash on iOS 16.2: -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:
Hmm just hit it again. Slightly different code path this time before the -checkIfLoadingCellIsIsVisible method is called. This time after an object was removed from the model: ** Last Exception Backtrace: 0 CoreFoundation 0x19c789e48 __exceptionPreprocess + 164 1 libobjc.A.dylib 0x195a5b8d8 objc_exception_throw + 60 2 Foundation 0x19704a94c _userInfoForFileAndLine + 0 3 UIKitCore 0x19eaa0888 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 572 4 UIKitCore 0x19ea744cc -[UITableView _updateVisibleCellsForRanges:createIfNecessary:] + 596 5 UIKitCore 0x19e9adb28 -[UITableView _updateVisibleCellsNow:] + 1088 6 UIKitCore 0x19e9785e8 -[UITableView _visibleCellsUsingPresentationValues:] + 34 7 MyApp           0x103125120 -[MyTableViewSubclass checkIfLoadingCellIsIsVisible] My App 0x1045b4380 -[MyTableViewControllerClass processRemovedObjectsNotification:] + 1573760 ** The -processRemovedObjectsNotification: method removes objects from the data source and reloads the table view (via -reloadData call). Then after reloading the table view it calls -checkIfLoadingCellIsIsVisible which enumerates the visibleCells to see if a loading more placeholder is in the visible region of the table view. Definitely feels like something changed in UITableView in iOS 16.2 because I've been using this app for so long and it would seem highly unlikely for this to just be a coincidence. I still have a device on iOS 15. I haven't hit this crash on that device. But since going from iOS 16 to 16.2 on my iPhone I hit this like once or twice a day now.
Topic: UI Frameworks SubTopic: UIKit Tags:
Dec ’22
Reply to Crash on iOS 16.2: -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:
I tried overriding -layoutSubviews in the table view subclass to see if I'm accessing visibleCells in the middle of table view layout: -(void)layoutSubviews { self.isBuildingCellsInProgress = YES; [super layoutSubviews]; self.isBuildingCellsInProgress = NO; } Then in my checkIfLoadingCellIsIsVisible method I check if isBuildingCellsInProgress property is YES on the table view, and if it is, return out and don't call the visibleCells getter. Unfortunately the isBuildingCellsInProgress is never YES when the checkIfLoadingCellIsIsVisible method is called. Haven't been able to isolate the issue. The only thing I can say for sure is that it started happening every so often since the iOS 16.2 update. I do have a few of these tables views inside UITabBarController tabs. I'm thinking the issue may be triggered when this code is hit on a table view not currently in the window (the user is on another tab), but I can't say for sure because I'm unable to reproduce the issue when my app is attached to the debugger. When the "loading" cell is visible and the table view is not in the window my app just empties the data and reloads it on the next -viewDidAppear: call so enumerating the visibleCells when the table view is not in the window still provides value.
Topic: UI Frameworks SubTopic: UIKit Tags:
Dec ’22
Reply to Crash on iOS 16.2: -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:
So I pushed an App update that uses the check above in layout subviews to block myself from accessing visibleCells during layoutSubviews (in my testing that wasn't showing to be occurring but since this crash is so rare I figured it might be the cause under some rare circumstances) so figured it was worth a shot. I've been using the app for two days now with the new update (quite a bit). I finally hit the crash again. Crash reports show that my call to the visibleCells getter is that last part of my code being called. Then it goes to system code and then I crash (here's the call stack after I call the visibleCells getter) 0 CoreFoundation 0x19c789e48 __exceptionPreprocess + 164 1 libobjc.A.dylib 0x195a5b8d8 objc_exception_throw + 60 2 Foundation 0x19704a94c _userInfoForFileAndLine + 0 3 UIKitCore 0x19eaa0888 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 572 4 UIKitCore 0x19ea744cc -[UITableView _updateVisibleCellsForRanges:createIfNecessary:] + 596 5 UIKitCore 0x19e9adb28 -[UITableView _updateVisibleCellsNow:] + 1088 6 UIKitCore 0x19e9785e8 -[UITableView _visibleCellsUsingPresentationValues:] + 340 Anyone at Apple know what exception is being thrown here down this code path (or possible exceptions, if more than one is possible)? That'd at least point me in some kind of direction as to what (if anything) I can do to avoid this. Thanks in advance.
Topic: UI Frameworks SubTopic: UIKit Tags:
Dec ’22
Reply to Crash on iOS 16.2: -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:
So I went ahead and pushed another update out with my second attempt at avoiding the crash without having much to go on. This time I avoid accessing the visibleCells property on the table view all together. Now I hit a crash again that bubbles up to _createPreparedCellForRowAtIndexPath:willDisplay: but this time the crash report includes a bit more: CoreFoundation 0x1d1069e48 __exceptionPreprocess + 164 1 libobjc.A.dylib 0x1ca33b8d8 objc_exception_throw + 60 2 Foundation 0x1cb92a94c _userInfoForFileAndLine + 0 3 UIKitCore 0x1d3380888 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 572 4 UIKitCore 0x1d344eeb4 -[UITableView _createPreparedCellForRowAtIndexPath:willDisplay:] + 68 5 UIKitCore 0x1d344ea9c -[UITableView _heightForRowAtIndexPath:] + 124 6 UIKitCore 0x1d344e938 -[UISectionRowData heightForRow:inSection:canGuess:] + 176 7 UIKitCore 0x1d3681394 -[UITableViewRowData heightForRow:inSection:canGuess:adjustForReorderedRow:] + 228 8 UIKitCore 0x1d328e8c4 -[UITableViewRowData rectForRow:inSection:heightCanBeGuessed:] + 304 9 UIKitCore 0x1d368091c -[UITableViewRowData rectForGlobalRow:heightCanBeGuessed:] + 112 10 UIKitCore 0x1d3681f70 -[UITableViewRowData globalRowsInRect:canGuess:] + 468 11 UIKitCore 0x1d36b43b8 -[_UITableViewUpdateSupport _faultInRealHeightsOfNeededElements] + 96 12 UIKitCore 0x1d36ee6c8 -[_UITableViewUpdateSupport _setupAnimations] + 36 13 UIKitCore 0x1d3524154 -[UITableView _updateWithItems:updateSupport:] + 832 14 UIKitCore 0x1d34e7ff0 -[UITableView _endCellAnimationsWithContext:] + 9900 15 UIKitCore 0x1d40ac6fc -[UITableView reconfigureRowsAtIndexPaths:] + 352 16 MyApp 0x104fcffa4 -[TableCellImageLoader didLoadImagesForCells] + 606116 -- Before the crash was triggered shortly after a reload data call on the table view when I accessed the visible cells property to determine the location of a "loading" cell. Now the crash is happening after my thumbnail loader loads some images and figures out the index paths needed to be reconfigured. The TableCellImageLoader uses indexPathsForVisibleRows to determine the index paths to reconfigure (it does not access the visibleCells property instead it looks through my model object using indexPathsForVisibleRows). This crash report seems to imply that the crash may be related to the cell heights. My table view cells are self sizing (they override -systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: and compute their size based on their content). My table view delegate does implement -tableView:estimatedHeightForRowAtIndexPath: (returning either a cached value or UITableViewAutomaticDimension) but I still don't really have a clue as to what the exception is about. My delegate does not implement -tableView:heightForRowAtIndexPath: as the actual height is determined by the cell itself.
Topic: UI Frameworks SubTopic: UIKit Tags:
Jan ’23
Reply to Is it possible to use Settings.bundle just for Mac Catalyst, and not for the iOS version of the app?
Yes this is possible in Build Phases. Select the Setting.bundle uncheck "Allow on Any Platform" and just keep Mac Catalyst checked. Figured this out awhile ago but forgot to update this thread. Figured I'd update it in case anyone stumbles upon it in a search. I don't think I'll be able to use a Settings bundle for this after all because I have an additional window that needs to be shown in a window sheet with some dynamic content and that can't be done with a Settings bundle.
Topic: UI Frameworks SubTopic: UIKit Tags:
Jan ’23