Post

Replies

Boosts

Views

Activity

Reply to Crash on iOS 16.2: -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:
So after many days of using a new Adhoc build of my app with the change to write a file in the event of getting a nil cell in -tableView:cellForRowAtIndexPath: I failed to reproduce the crash. Finally I hit the crash again today. The file I attempt to write in -tableView:cellForRowAtIndexPath: does not exist on disk. The file I write to disk to capture the exception reason in my NSSetUncaughtExceptionHandler does exist. The exception reason is "UITableViewDataSource returned a nil cell for row at in index path" The exception message reason/message appears to be bogus (unless I just hit the lottery and my attempt to write a file in -tableView:cellForRowAtIndexPath: failed with an error). I think a few possibilities are: -UITableView exception message on this line 16555 is incorrect and needs to be changed to a proper exception message that truly indicates what's wrong. -UITableView is really hitting its reuse queue but isn't properly retaining the cell it thinks it has and when it gets nil back from its internal implementation, it is throwing an exception incorrectly instead of asking the delegate to make a new instance. -Maybe code triggered as part of inflight animations after delays/timers isn't properly cancelled when -reloadData is called and the table view is in a whacky state. Or something else. Impossible for me to know without source code. In any case I have no idea how I can workaround this issue using only public API. If my -tableView:cellForAtIndexPath: isn't returning nil....there doesn't seem to be a way I can fix this.
Topic: UI Frameworks SubTopic: UIKit Tags:
Jan ’23
Reply to UIMenuElement subclass that can take a target? Like UITargetedCommand?
Also this would be useful to specify targets outside the responder chain. For example I want to invoke an action from the menu bar on an object that isn't in the responder chain (it can be invoked even if my app has no open windows). As far as I can tell my only option is to use UIAction and call the method on the "target" in the actionHandler block. But what about validating the UIAction? -canPerformAction:withSender: won't be called on the object not in the responder chain. My best bet might be subclassing UIApplication and forwarding the method calls to the target I really want. Not sure why Apple seems to be abandoning targets. The UIKit APIs seem to be overusing blocks IMO.
Topic: UI Frameworks SubTopic: UIKit Tags:
Jan ’23
Reply to NSOpenPanel returning immediately in MacCatalyst
Wrapping NSOpenPanel/SavePanel in a bundle that can access the more powerful macOS APIs has its uses though. As far as I can tell there isn't a way to present UIDocumentInteractionController in the same way as NSOpenPanel -runModal. You need to present it from an existing UIViewController. Say you have an item in the menu bar that would invoke open or save and no windows are currently open (but the App is the menu bar owning app). In the Catalyst environment you can't present a freestanding UIDocumentInteractionController (unless I'm missing something?). First you need to create a window with a view controller, then present the UIDocumentInteractionController on the view controller which isn't ideal.
Topic: UI Frameworks SubTopic: AppKit Tags:
Jan ’23
Reply to How to define a Class instance type conforming to a protocol?
There is a class method flavor: +conformsToProtocol: https://developer.apple.com/documentation/objectivec/nsobject/1418893-conformstoprotocol From the documentation: Discussion A class “conforms to” a protocol if it adopts the protocol or inherits from another class that adopts it. Classes adopt protocols by listing them within angle brackets after the interface declaration. For example, here MyClass adopts the (fictitious) AffiliationRequests and Normalization protocols: @interface MyClass : NSObject <AffiliationRequests, Normalization> A class also conforms to any protocols included in the protocols it adopts or inherits. Protocols incorporate other protocols in the same way classes adopt them. For example, here the AffiliationRequests protocol incorporates the Joining protocol: @protocol AffiliationRequests <Joining> If a class adopts a protocol that incorporates another protocol, it must also implement all the methods in the incorporated protocol or inherit those methods from a class that adopts it. This method determines conformance solely on the basis of the formal declarations in header files, as illustrated above. It doesn’t check to see whether the methods declared in the protocol are actually implemented—that’s the programmer’s responsibility. To specify the protocol required as this method’s argument, use the @protocol() directive: BOOL canJoin = [MyClass conformsToProtocol:@protocol(Joining)]; Also note: Performance Considerations Calling this method in performance sensitive code can cause unwanted performance problems. conformsToProtocol: requires taking the Objective-C runtime lock and traversing the target’s class hierarchy to check for protocol conformance, which can take significant time. Consider the following alternatives in your code: Use respondsToSelector: to check for methods in the protocol instead, especially if you only need to check some of the protocol’s methods. If you do need to use conformsToProtocol:, cache the result whenever possible, rather than calling this method repeatedly.
Topic: Programming Languages SubTopic: General Tags:
Jan ’23
Reply to How to define a Class instance type conforming to a protocol?
Assuming I need to return an instance of a Class which conforms to this protocol from a method, how am I supposed to specify the return type? Like this... - (nullable id<TDWMethoding>)instantiateMethoding { Class instance = ... // some implementation if ([instance conformsToProtocol:@protocol(TDWMethoding)]) { return instance; } return nil; } If you want to return any object to the caller that conforms to the TDWMethoding protocol. Typically you'd do this if -instantiateMethoding may return objects of different classes but all those classes must conform to the protocol. If you just want to return an instance of a specific class and don't need it to be that generic just you do this: -(MyClass*)instantiateMethoding { //return it. } If MyClass conforms to the TDWMethoding protocol in its public header file you don't need to cast or write id<TDWMethoding> ... the compiler knows MyClass conforms to TDWMethoding. Not sure exactly what you're trying to do though. Hope that helps.
Topic: Programming Languages SubTopic: General Tags:
Jan ’23
Reply to NSOpenPanel returning immediately in MacCatalyst
Also UIDocumentInteractionController doesn't have any API that bridges to NSOpenPanel/NSSavePanel UI related properties like: @property (null_resettable, copy) NSString *prompt; /* NSSavePanel/NSOpenPanel: Gets and sets the title for the panel shown at the top of the window. */ @property (null_resettable, copy) NSString *title; /*  NSSavePanel: Gets and sets the text shown to the left of the "name field". Default value is a localized "Save As:" string.     NSOpenPanel: Not used. */ @property (null_resettable, copy) NSString *nameFieldLabel; Etc. etc. FWIW I'm not experiencing the OPs reported issue on Ventura 13.1.
Topic: UI Frameworks SubTopic: AppKit Tags:
Jan ’23
Reply to Crash on iOS 16.2: -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:
Perhaps I finally resolved this. My last guess is that the UITableView for some reason started outliving the object I use to return a cell in -tableView:cellForRowAtIndexPath: which was never the case prior to iOS 16.2. I made some changes, will need to test this longer to see if I finally got this fixed since the crash is pretty hard to reproduce.
Topic: UI Frameworks SubTopic: UIKit Tags:
Jan ’23
Reply to Mac Catalyst UITabBarController with hidden tab bar wrapping view controllers inside the "More" navigation controller (not desired) when 7 or more tabs are embedded
Hmm.. just for testing I showed the UITabBar and created a UITabBarItem for each view controller. UITabBarController just starts stacking view controllers in the "More" navigation controller when there are around 8 or more view controllers. It doesn't take into account the width of the UITabBarController; I can resize the window to giant size but the UITabBar just adds additional space between all the tab bar items and keeps the "More" item as the last tab bar item even though there is plenty of room to fit all tab bar items.
Topic: UI Frameworks SubTopic: UIKit Tags:
Feb ’23
Reply to Mac Catalyst UITabBarController with hidden tab bar wrapping view controllers inside the "More" navigation controller (not desired) when 7 or more tabs are embedded
Workaround is to do this in all the view controllers automatically being wrapped in the more navigation controller: -(void)willMoveToParentViewController:(UIViewController*)parent {   [super willMoveToParentViewController:parent]; #if TARGET_OS_MACCATALYST   if ([parent isKindOfClass:[UINavigationController class]])     { UINavigationController *navigationController = (UINavigationController*)parent;         [navigationController setNavigationBarHidden:YES]; } #endif }
Topic: UI Frameworks SubTopic: UIKit Tags:
Feb ’23
Reply to Getting clicked item index in NSPathControl with pathItems instead of pathComponentCells
it doesn't seem possible to get the index of the clicked path item, nor does it seem possible to associate any kind of data with each path item, What happens when you try this: -(void)pathControlAction:(NSPathControl*)pathControl {     NSPathControlItem *clickedPathItem = pathControl.clickedPathItem;     if (clickedPathItem == nil) { NSLog(@"whoops!"); return; }     NSUInteger index = [pathControl.pathItems indexOfObject:clickedPathItem];     if (index == NSNotFound) { NSLog(@"whoops!"); return;  }     //do whatever. } They deprecated the cell based NSPathControl API without introducing proper replacements as you discovered. It's been so many years I get the feeling that they are never going to improve this so it's probably pretty safe to use the cell based stuff even though it's deprecated. But if you don't want to do that your probably can associate data with path control items by subclassing and setting the path control items with some custom objects at the same time. @interface MyPathControl : NSPathControl //Each array must contain the same number of objects. -(void)setPathControlItems:(NSArray<NSPathControlItem*>*)itemsArray withRepresentedObjects:(NSArray<WhateverObject*>*)representedObjectsForEachItem; -(void)setPathControlItems:(NSArray<NSPathControlItem*>*)itemsArray NS_UNAVAILABLE; @end Or something like that. Not great but that's all I can think of.
Topic: UI Frameworks SubTopic: AppKit Tags:
Feb ’23
Reply to Getting clicked item index in NSPathControl with pathItems instead of pathComponentCells
That's the incredible thing: sender.pathItems.firstIndex(of: sender.clickedPathItem!) always returns nil, even if the clicked path item has the same address as the corresponding item in the path items array. Even sender.pathItems.firstIndex(where: { $0.description == sender.clickedPathItem!.description }) returns nil. And when executing that print statement more than once one after the other, each item always has a different address. Not sure. I don't have time to test this thoroughly but try overriding the pathControlItems setter to see if you or the system are resetting the array unexpectedly. How are you creating each NSPathControlItem? In any case as long as each NSPathControlItem URL is unique you can just hold whatever data you want to associate with each path item like so: @property NSDictionary<NSURL*,Whatever*>*representedObjectsForPathURLs; Then add a method on your path control subclass: -(Whatever*)representedObjectForPathControlItem:(NSPathControlItem*)item { return [self.representedObjectsForPathURLs objectForKey:item.URL]; } This assumes NSPathControlItem doesn't mangle your url strings after they are set.
Topic: UI Frameworks SubTopic: AppKit Tags:
Feb ’23