Modal dialogs breaking responder chain in mac catalyst scene based app - ios

I have a multi-window scene-based (not SwiftUI) iPad app that I am adapting for Mac using mac catalyst. I am having trouble with the main menu behavior. The menu is built in AppDelegate.swift using func buildMenu(). I have, for example, an Open Image... menu item that uses a selector in my main view controller. Here is the code in buildMenu():
let openFileCommand = UIKeyCommand(
title: "Open Image...",
action: #selector(DiagramViewController.openImageFile(_:)),
input: "o",
modifierFlags: [.command]
)
let openFileMenu = UIMenu(
title: "",
image: nil,
identifier: UIMenu.Identifier("openImage"),
options: .displayInline,
children: [openFileCommand]
)
builder.insertSibling(openFileMenu, afterMenu: .newScene)
It is enabled and works fine when first opening the view controller. See:
I then open any modal dialog, for example, the About dialog, and after closing it, the Open Image... menu item is deactivated, as if the selector is no longer in the responder chain, though everything works on the view controller.
I don't understand what is going on here. This kind of functionality works fine on a non-multi-window catalyst app.
UPDATE: Well the problem has nothing to do with the app being scene-based. It is a UIDocument based app, and the UIDocumentBrowserViewController presents the main view controller modally. The main view controller is then the first responder and everything is fine, but as soon as you open another modal window on top of it, like the system generated About dialog, the original document browser view controller becomes the first responder and the main view controller is no longer in the window hierarchy (even though the document browser view controller is invisible, and the main view controller is still shown and works normally). If anyone has experience with dealing with this issue, I'd appreciate their advice.

With further experimentation, and given that this is a UIDocument based app, it looks like the document browser view controller becomes the first responder after the dialog closes. So I think I can work around that and forward actions form the document browser to the main view controller.

Related

Latest Vaadin Start generated app - bug in main-layout theme with Flow/Hybrid views?

I used the latest Vaadin Start page to generate an app skeleton (Vaadin 21 / Java 11)
It works so far, I used hybrid mode with various views.
When clicking view links in the menu only TS+HTML based views will register in the GUI as selected and get a colored "selected/active" styling.
When I generate an app which only has Flow views, the first view will be stuck with the selected styling, but other views will register properly when clicked.
Only when I generate an app which only has Fusion views, all view selects will properly register.
I guess this is a bug?
Edit: video of the behavior when in hybrid mode. The menu item names correspond to the type of view which is being selected. As you can see only fusion views show the "select" in the menu:
Edit2: I think the problem is caused here:
?highlight=${viewRoute.path == appStore.location
Seems like the appStore.location is not being set from non-Fusion views. I put a console.log in the index.ts eventListener and non-Fusion views all just pass "(.*)" as the view name/location, which is the reasion why this fails.
So the #Route(value = "view-name") declaration in the java-class seems not to be passed properly at the moment.
BR
Daniel
This seems to be a bug in the Start project templates. I added an issue in our internal issue tracker.
Thanks a lot for reporting.
Edit: the issue is already fixed.
The question is not very clear to me, but if the problem is the fact that "the first view will be stuck with the selected styling", have you tried to add setAutoselect(false) to the tabbed menu in your MainLayout?
Here it is:
private Tabs createMenu() {
final Tabs tabs = new Tabs();
tabs.setOrientation(Tabs.Orientation.VERTICAL);
tabs.addThemeVariants(TabsVariant.LUMO_MINIMAL);
tabs.setId("tabs");
tabs.setAutoselect(false); //Needed not to select first tab by default
tabs.add(createMenuItems());
return tabs;
}

UISearchController disappears when pushing a new UIViewController

I'm currently working with an example from Raywenderlich: UISearchController-Tutorial (The finished project is at the end of their article or here) and I noticed that when I execute a search and click on one of the results, during the push transition, the UISearchController disappears. It's visible on this video: here
Before selecting a result
During the transition to the new VC
I run this example with Xcode 10, iOS 12 (sim: iPhone 8)
Any idea / pointer would be deeply appreciated
Cheers.
Its default in iOS12. Just look at the Apple-Mail App. There it is the same. Actually you dont need the searchbar, when you are showing another VC

WatchKit reloadRootControllersWithNames causing error, with pageController or after push/pop

I have a basic watchkit app that loads a page based navigation of 3 interface controllers. This works well, but I'd then like to trigger an action to remove the page-control and essentially revert back to the original InterfaceController that was present when the app first loads.
// load page based control, with 3 views. this works ok
[WKInterfaceController reloadRootControllersWithNames:#[#"pageController1",#"pageController2",#"pageController3"]
contexts:#[#"data1",#"data2",#"data3"]];
// attempt to reload original interface controller, identified by storyboard id
[WKInterfaceController reloadRootControllersWithNames:#[#"myInterfaceController"] contexts:#[#{}]];
The page based navigation remove, the original navigation loads after a short spinner. However it fails to function correctly and original Actions result in this error.
Extension[6766:123665] *********** ERROR
-[SPRemoteInterface _interfaceControllerClientIDForControllerID:] clientIdentifier for interfaceControllerID:(null) not found
Is there a better way to cleanly reload the original InterfaceController?
EDIT, 2/19
It seems there are some other actions that are causing this error too. For instance, if segue to a second InterfaceController and then popController to get back, the error often appears. It is always related to a secondary call to this function.
[WKInterfaceController reloadRootControllersWithNames: contexts:]
EDIT2, 3/18
As previously mentioned, this is reproducible 100% of the time by doing the seguePush, the popController, then attempting to reloadRootControllersWithNames.
If the seguePush/popController is not done beforehand, then the reloadRootControllersWithNames will work fine.
This situation seems to be in addition to the multi->single-multi instance of this bug.
This is actually not a bug because according to Apple:
You cannot combine hierarchical and page-based interface styles. At design time, you must choose the style that best suits your app’s content and design for that style.
So unfortunately, we can't mix Hierarchical and Page-based navigation patterns within the same Watch app.
Just one of many limitations we have to deal with when developing apps for  Watch
This is a bug in WatchKit in Xcode 6.2 Beta 5. Please dupe the following radar on Apple's Bug Reporting System to help raise the priority to get this fixed.
In the meantime, a workaround that I've found can be found on the dev forums. What you can do is add a dummy interface controller to any single interface controller page set so you always have two. This will fix the error until Apple get's the bug fixed (hopefully in Beta 6). Please dupe!
I was able to solve my instance of this problem by not using popController on a pushed view controller. Instead I use a reloadRootControllersWithNames in place of the popController.
How this allows both push and paging, via an example:
Push a view controller
reloadRootControllersWithNames to return to the original controller. (The transition is not quite as animated, but is sufficient)
Create page based view controller.
reloadRootControllersWithNames to return to the original controller
Repeat 1 or 3 as needed.
This eliminates the error at the cost of non-animated popControllers, and allows partial pushing and paging. It would not allow more complex push navigation though.
There may be a better method of navigating to a sub interface controller without a push call, but I'm not aware of it on the watch yet.
None or the answers above worked for me. This problem began when I changed the icon names for the app and the watch app name. I solved it like this:
1) Click on your Watch app Target > Capabilities > make sure app Group
is in ON.
2) Make sure the App Group is selected.
3) Clic on the circled arrow Refresh icon (this will apparently just
refresh this thing if you already had it)
4-Repeat steps 1-3, but for your Watch App EXTENSION target too.
5-Click on the Scheme button (on the right side of the STOP button),
and clic on Edit Schemes.
6-Click Run > Info 7-In executable select your target (Actually it
should already be selecting but opening this window seems to
refresh the option, and wipe the error)
Apparently all these things above are not updated automatically when you change the icon name (Target names) and you have to go to those menus and open them to refresh them manually. Shame on Apple perhaps?

Issue dismissing/ re-presenting MFMessageComposeViewController with iOS6 but fine with iOS5

I'm presenting an MFMessageComposeViewController which works fine with iOS4 and iOS 5 but has problems with iOS6.
The view is presented ok but if its dismissed and then represented it doesn't display correctly - only the To: line is displayed, the body and keyboard are missing. (Sorry I can't post a screen shot at the moment as XCode crashes when I take a shot, I'm downloading an older version of XCode as I type).
Stepping through the code in the debugger I noticed that the problem may originate earlier than the re-presenting - I noticed than when dismissViewControllerAnimated: gets called the entire view does not get dismissed immediately, rather it is the message body and keyboard that gets dismissed leaving behind the To:, the same thing that is displayed when the view is re-presented.
It might be easier to describe with screenshot, I'll post some shortly.
I'm using presentViewController: and dismissViewControllerAnimated: to present/dismiss the MFMessageComposeViewController.
+++ UPDATE +++
I've found the problem can be solved if instead of using the same MFMessageComposeViewController object to re-present the view I first delete it and then create a new one.
That seems a little inefficient though, and it should not be necessary I'd have though, like i mentioned it worked on iOS5.
In iOS 6 apple introduced a new feature "remote view controller". Some external view controllers are no longer part of your app, and the messaging controller is one of them.
I guess that is the problem in your case.
you can read more about it there: http://oleb.net/blog/2012/10/remote-view-controllers-in-ios-6/

UITapGestureRecognizer from Objects library in storyboard on a view which is inside a tab bar controller

I added a UITapGestureRecognizer to a view which is inside a tab bar controller and when I switch to the tab which contains the view with the UITapGestureRecognizer, I get a crash with the message -
-[__NSCFString setView:]: unrecognized selector sent to instance 0x2ae8d0
I am using Xcode 4.3
i had this same trouble on iOS5 only with an app targeted to iOS 5 and iOS 6 and a gesture recognizer on the last tab. our code also has very similar gesture-recognizers that are loaded for modal dialogs or pushed view controllers for other tabs. so it was only gesture-recognizers in a tab that was not the first tab, and only in the rootViewController for that tab.
as Arunabh Das ended up doing, it would seem the only answer is really to add the UIGestureRecognizers in code. there is a thread at Ray Wenderlich's website (which is a decent site containing some good iOS tips) , which, summarized, notes that there appears to be a bug in iOS5, starting with the beta versions, never fixed in the final, and containing a code-snippet that shows how to put the gesture-recognizers in code if you want them.

Resources