Code Block @implementation DWViewController : UIViewController {} |
-(void)viewWillLayoutSubviews |
{ |
DWWindow *window = (DWWindow *)[[self view] window]; |
NSArray *array = [window subviews]; |
CGRect frame = [window frame]; |
DWView *view = nil; |
UINavigationBar *nav = nil; |
NSInteger sbheight = [[[window windowScene] statusBarManager] statusBarFrame].size.height; |
|
for(id obj in array) |
{ |
if([obj isMemberOfClass:[DWView class]]) |
view = obj; |
else if([obj isMemberOfClass:[UINavigationBar class]]) |
nav = obj; |
/* Hide the UITransitionView which is blocking the screen... |
* This is probably not the correct solution, but it solves the |
* problem for the moment. Figure out what to do with this view. |
*/ |
else |
[obj setHidden:YES]; |
} |
/* Adjust the frame to account for the status bar and navigation bar if it exists */ |
if(nav) |
{ |
CGRect navrect = [nav frame]; |
|
navrect.size.width = frame.size.width; |
navrect.origin.x = 0; |
navrect.origin.y = sbheight; |
sbheight += navrect.size.height; |
[nav setFrame:navrect]; |
|
if (@available(iOS 14.0, *)) { |
DWMenu *windowmenu = [window menu]; |
UINavigationItem *item = [[nav items] firstObject]; |
|
if(windowmenu && !item.rightBarButtonItem) |
{ |
UIBarButtonItem *options = [[UIBarButtonItem alloc] initWithImage:[UIImage systemImageNamed:@"list.bullet"] |
menu:[windowmenu menu]]; |
item.rightBarButtonItem = options; |
} |
} else { |
} |
} |
frame.size.height -= sbheight; |
/* Account for the special area on iPhone X and iPad Pro |
*/ |
frame.size.height -= 24; |
frame.origin.y += sbheight; |
[view setFrame:frame]; |
[view windowResized:frame.size]; |
} |
@end |
|
DW_FUNCTION_DEFINITION(dw_window_new, HWND, DW_UNUSED(HWND hwndOwner), const char *title, DW_UNUSED(ULONG flStyle)) |
DW_FUNCTION_ADD_PARAM3(hwndOwner, title, flStyle) |
DW_FUNCTION_RETURN(dw_window_new, HWND) |
DW_FUNCTION_RESTORE_PARAM3(DW_UNUSED(hwndOwner), HWND, title, char *, DW_UNUSED(flStyle), ULONG) |
{ |
DW_FUNCTION_INIT; |
CGRect screenrect = [[UIScreen mainScreen] bounds]; |
DWWindow *window = [[DWWindow alloc] initWithFrame:screenrect]; |
DWView *view = [[DWView alloc] init]; |
UIUserInterfaceStyle style = [[DWObj hiddenWindow] overrideUserInterfaceStyle]; |
|
[window setWindowLevel:UIWindowLevelNormal]; |
[window setRootViewController:[[DWViewController alloc] init]]; |
[window addSubview:view]; |
[window setBackgroundColor:[UIColor systemBackgroundColor]]; |
|
/* TODO: Handle style flags... if we can? There is no visible frame */ |
if(@available(iOS 13.0, *)) { |
NSString *nstitle = [NSString stringWithUTF8String:title]; |
[window setLargeContentTitle:nstitle]; |
if(flStyle & DW_FCF_TITLEBAR) |
{ |
NSInteger sbheight = [[[window windowScene] statusBarManager] statusBarFrame].size.height; |
UINavigationBar* navbar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, sbheight, screenrect.size.width, 40)]; |
UINavigationItem* navItem = [[UINavigationItem alloc] initWithTitle:nstitle]; |
|
[navbar setItems:@[navItem]]; |
[window addSubview:navbar]; |
} |
} |
/* Copy the overrideUserInterfaceStyle property from the hiddenWindow */ |
if(style != UIUserInterfaceStyleUnspecified) |
[window setOverrideUserInterfaceStyle:style]; |
DW_FUNCTION_RETURN_THIS(window); |
} |
Think I may be seeing what is happening... after reading an article about the UIResponder chain, I wrote a recursive function to traverse the UIResponder chain up... according to the Apple documentation on this, https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/using_responders_and_the_responder_chain_to_handle_events?language=objc the UIViewController should be in the chain... but traversing it via nextResponder the UIViewController does not show up in the chain. I assume this is because I programmatically created the DWWindow, DWViewController and all the subviews. I suspect that the UIMenu code traverses the responder chain and does not find the UIViewController and produces this error. My question now is... how do I correctly add the UIViewController to the UIResponder chain?
Maybe that isn't the problem after all, I added nextResponder overrides to DWView and DWWindow to include DWViewController in the chain... and I still get the error... here is the console output with my UIResponder chain dump from the UITableView context menu:
` === Starting responder chain dump ===
<DWContainer: 0x103839400; baseClass = UITableView; frame = (6 404; 1002 200); clipsToBounds = YES; tag = 100; gestureRecognizers = <NSArray: 0x2824214a0>; layer = <CALayer: 0x282a67140>; contentOffset: {0, 0}; contentSize: {1002, 176}; adjustedContentInset: {0, 0, 0, 0}; dataSource: <DWContainer: 0x103839400; baseClass = UITableView; frame = (6 404; 1002 200); clipsToBounds = YES; tag = 100; gestureRecognizers = <NSArray: 0x2824214a0>; layer = <CALayer: 0x282a67140>; contentOffset: {0, 0}; contentSize: {1002, 176}; adjustedContentInset: {0, 0, 0, 0}; dataSource: <DWContainer: 0x103839400>>>
<DWBox: 0x102e24f10; frame = (0 0; 1014 634); layer = <CALayer: 0x282a165e0>>
<DWNotebookPage: 0x102e31290; frame = (5 45; 1014 634); layer = <CALayer: 0x282a16380>>
<DWNotebook: 0x102d0bee0; frame = (5 5; 1014 674); tag = 1; layer = <CALayer: 0x282a73260>>
<DWBox: 0x102e0ba00; frame = (0 0; 1024 684); layer = <CALayer: 0x282a6cd40>>
<DWView: 0x102d0fe10; frame = (0 60; 1024 684); layer = <CALayer: 0x282a70dc0>>
<DWViewController: 0x102d101a0>
<DWWindow: 0x102d0ed30; baseClass = UIWindow; frame = (0 0; 1024 768); autoresize = W+H; gestureRecognizers = <NSArray: 0x282405470>; layer = <UIWindowLayer: 0x282a70b60>>
<UIWindowScene: 0x102e078b0; scene = <FBSScene: 0x280454780; identifier: sceneID:org.dbsoft.dwindows.dwtest-default>; persistentIdentifier = ADFA76E7-BFE5-4733-B8DD-5B3BEAAEE88D; activationState = UISceneActivationStateForegroundActive; settingsCanvas = <UIWindowScene: 0x102e078b0>; windows = ( "<UIWindow: 0x102e095d0; frame = (0 0; 1024 768); hidden = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x282401560>; layer = <UIWindowLayer: 0x282a795c0>>", "<UITextEffectsWindow: 0x102e0d8f0; frame = (0 0; 1024 768); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x282a7c340>>", "<DWWindow: 0x102d0ed30; baseClass = UIWindow; frame = (0 0; 1024 768); autoresize = W+H; gestureRecognizers = <NSArray: 0x282405470>; layer = <UIWindowLayer: 0x282a70b60>>" )>
<UIApplication: 0x102d05850>
<DWAppDel: 0x282858570>
=== Responder chain dump complete ===
[Assert] Failed to find a presenting view controller for view (<DWContainer: 0x103839400; baseClass = UITableView; frame = (6 404; 1002 200); clipsToBounds = YES; tag = 100; gestureRecognizers = <NSArray: 0x2824214a0>; layer = <CALayer: 0x282a67140>; contentOffset: {0, 0}; contentSize: {1002, 176}; adjustedContentInset: {0, 0, 0, 0}; dataSource: <DWContainer: 0x103839400; baseClass = UITableView; frame = (6 404; 1002 200); clipsToBounds = YES; tag = 100; gestureRecognizers = <NSArray: 0x2824214a0>; layer = <CALayer: 0x282a67140>; contentOffset: {0, 0}; contentSize: {1002, 176}; adjustedContentInset: {0, 0, 0, 0}; dataSource: <DWContainer: 0x103839400>>>) in window (<DWWindow: 0x102d0ed30; baseClass = UIWindow; frame = (0 0; 1024 768); autoresize = W+H; gestureRecognizers = <NSArray: 0x282405470>; layer = <UIWindowLayer: 0x282a70b60>>). The interaction's view (or an ancestor) must have an associated view controller for presentation to work.`
I really need an Apple engineer who knows this code to look and tell where it is looking for the View Controller, because as far as I can tell there are view controllers to handle this presentation despite the error's protest.