Button visibly clicking but event not registering - swift3

Swift 3/iOS 10/Xcode 8
I have a view controller (pieChart) that contains a label, two buttons and an empty view (which will contain a pie chart). The label and two buttons are incorporated into a horizontal stack view, which lies above the pie chart view.
The above VC is embedded into one of four container views (The main screen of the app is comprised of these four container views) when the app starts up.
In pieChart, I have linked both buttons up to their respective IBActions and IBOutlets. When clicking on button 2, a modal segue should occur to another VC but this does not happen. Visibly, the button is registering the click - ie it changes colour when you click it. I have placed a print statement in the IBAction method for button 2 but this too does not display. No error messages are displayed in console either.
The only reasons for this occurring that I have found after several hours of hunting are:
sub views have been added to the button itself so the click event signal passes by the button to be received by the added sub views. This is not the case for me. Order is Main App Window > Container View > Embedded VC > Stack View > Button. InteractionEnabled is set to true for all.
Button lies partially outside containing view (it's height/width might be greater than its containing view). This is not the case for me. The stack view, label and both buttons share the same height and the width of the stack view is equal to the sum of the widths of the label and buttons plus the spacing between the label and buttons.
I have also tried adding an event handler programmatically with:
SelectAnalyisButtonOutlet.addTarget(self, action: #selector(SelectAnalysisButtonClicked), for: .touchUpInside)
but the same outcome occurs.
Are there any other reasons for the click events seemingly not registering?
EDIT 1
The pieChart VC mentioned above is one of several VC's that are swapped out of the same container view (called detailContainerView), depending on which button (all of which work just fine) is clicked in one of the OTHER container views (called TabBar).
I placed a button in each of two other VC's that get displayed in detailContainerView and hooked them each up to an IBAction. Each IBAction contains a print statement that fires when the button is clicked. At the moment then, these two VC's only consist of a label and the newly inserted buttons. None of the buttons worked when I ran the app.
I then set one of the VC's of detailContainerView as the Initial View Controller in the Attributes Inspector and re-ran the app. Suddenly the buttons now work! If I then hook the buttons up to a segue, the segues work too!
Something seems to change when I swap out the VC's in detailContainerView. The code I am using to swap the VC's out is as follows:
func SwapOutControllers(vc: UIViewController, vcName: String){
//REMOVE OLD VC
detailPaneVCReference?.willMove(toParentViewController: nil)
detailPaneVCReference?.view.removeFromSuperview()
detailPaneVCReference?.removeFromParentViewController()
var newVc: UIViewController?
switch vcName {
case "Biography":
newVc = vc as! Biography
case "Social Media":
newVc = vc as! SocialMedia
case "News Feed":
newVc = vc as! NewsFeeds
case "Stats":
newVc = vc as! StatsAboutParliament
case "Petitions":
newVc = vc as! Petitions
default:
print("Error: No VC Found!")
}
//ADD NEW VC
ParentVC?.addChildViewController(newVc!)
let width = detailContainerView?.frame.width
let height = detailContainerView?.frame.height
newVc?.view.frame = CGRect(x: 0, y: 0, width: width!, height: height!)
detailContainerView?.addSubview((newVc?.view)!)
newVc?.didMove(toParentViewController: ParentVC)
}
detailPaneVCReference is a reference to whichever VC is currently being displayed by detailContainerView. ParentVC is the VC that contains the four container views.
The VC that is removed from the ParentVC still exists in the debugging view hierarchy after it has been removed/swapped out - could this be somehow blocking the click event from reaching the event handler?
SOLUTION!
The source of my problem has been that the references I had made to each of the view controllers that get swapped in and out of detailContainerView were incorrectly declared as weak references. I deleted "weak" (eg "weak var x: UIViewController?" --> "var x: UIViewController?") from each of the declarations and voila!, the code now works as intended!

The source of my problem has been that the references I had made to each of the view controllers that get swapped in and out of detailContainerView were incorrectly declared as weak references. I deleted "weak" (eg "weak var x: UIViewController?" --> "var x: UIViewController?") from each of the declarations and voila!, the code now works as intended!

Related

SwiftUI programatic navigation loses binding

I'm building a "Charade-like-game" app with five screens and a simple GameModel class consisting of five objects, including teams, round, and scores.
Screen1 dynamically determines the number of teams playing via #StateObject.
Screen2 is a scoreboard that displays in a VStack the dynamic number of teams playing via #ObservedObject, alongside scores from two rounds of play.
Screen3 shows the Charade criteria, and Screen4 is a timer. Neither of these affect the GameModel.
Screen5 gives the other teams a chance to score the performance. That value is then passed back to the Screen2 scoreboard.
The navigation flow begins at 1 then moves to 2 > 3 > 4 > 5 then back to 2 to repeat the cycle until the users close the app, like this:
I got tangled up in the navigation because I wanted the back button on Screen2 to start the game over, rather than return to Screen5. When I used #Environment(\.presentationMode) and presentationMode.wrappedValue.dismiss(), it didn't navigate properly.
Therefore I tried building the navigation programmatically using a #State Boolean, to change the screen like this:
if playGamePressed {
Screen2View()
} else {
Screen1 code...
Select # of teams binded via #StateObject (my source of truth)
Button(action: {
playGamePressed = true
}
}
Now, the #StateObject binding no longer passes the dynamic number of teams. Everything worked prior to changing the navigation to programmatic.
I used this as a reference: Swiftui nested navigation issue while using navigation link, but the solution was .presentationMode that didn't work for me.
What am I missing?

Navigation view is hiding while pushing from SwiftUI views to Storyboard project in iOS13

I have added SwiftUI views in my existing swift project.
I have the following flow in the project
FirstViewController --NavigationPush -> SwiftUIView1 -NavigationLink->
SwiftUIView2 - NavigationLink-> SwiftUIView3 - NavigationLink
(UIViewRepresentable) -> SecondViewController.
till SwiftUIView3 everything works as expected. while pushing from SwiftUIView3 -> SecondViewController, even though I'm setting the navigation property isHidden = false,
the navigationBar appears in the controller for a fraction of sec and disappears. I have tried to unhide navigation in all the controller life cycle methods. But nothing happens. Please let me know your suggestion to resolve this.
FYI, below code, I used SwiftUI to hide the navigation bar.
Code Block
.navigationBarTitle("") // This should be empty.
.navigationBarBackButtonHidden(true)
.navigationBarHidden(true)

Post accessibility notification in SwiftUI

I need to move the accessibility focus to certain element on the screen. In UIKit, we can simply do UIAccessibility.post(.screenChanged, element)
However, when I do that with a SwiftUI View, the app crashes with the following message in console
This class '__SwiftValue' is not a known serializable element and returning it as an accessibility element may lead to crashes
Any idea how we can move focus to certain elements on the screen in SwiftUI?
A workaround would be: Post a notification when the UIView appears:
.onAppear(perform: {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
UIAccessibility.post(notification: .screenChanged, argument: "New Screen")
}
})
As argument it would make sense to put in the text of the accessibility label of the desired view. The impaired user would just not know where the screenReader is focusing if the user could recognize the white surrounding of the screenReader focus.
To make things smooth the delay of 0.1 should be adapted while testing with different languages.

How to setUp UiTableViewController below the battery bar

newBie here. I have added an UItableViewController into storyBoard. I use this as a setting page.
HomeVC ----> Setting VC
In code : I use the below code to bring the tableView below the battery Bar:
self.tableView.contentInset = UIEdgeInsets(top: 20,left: 0,bottom: 0,right: 0)
Problem:
How to move the TableView down below the battery bar so that I can add a button above the table in StoryBoard
Please help.
For this you should use a normal view controller and drag a table on the view controller this way you can make the table size whatever you like. This will also allow you to place buttons wherever you like.
Don't forget to assign the TableViewDataSource and TableViewDelegate to your view controller.
Good luck!
After doing some search on UiTableViewController, to use it as setting page I have to set static cell to it. This UiTableViewController will occupy the entire view.
To set the tableView below the battery icon,
use:self.tableView.contentInset = UIEdgeInsets(top: 20,left: 0,bottom: 0,right: 0)
However, No need to do so. In the first TableViewSection, you can create a few tableView cell, just leave the first cell blank which acts as a margin below the battery bar.

Appcelerator. Buttons in rows are unclickable

Titanium SDK version: 1.6.2 (tried with 1.7 too)
iPhone SDK version: 4.2
I am developing an iPhone app and I am fetching data from my API and presenting it in a table. In this table I got a button on each row that should allow the user to add that person to his or her contacts. The only problem with the code (I think) is that only the last button responds when being clicked. Nothing happens when I click the other buttons.
This is my code: http://pastie.org/1932098
What is wrong?
You are adding the button.addEventListener outside of the for statement, and since you are overwriting the button var with each iteration, the eventListener only attaches to the last button created.
This probably isn't the best way to work this, but to fix your problem, move the button.addEventListener inside the for statement, and then check for a unique identifier in the object that gets sent to the event. Example:
for (x=0;x<5;x++) {
var button = Titanium.UI.createButton({
height:40,
width:100,
top:50*x,
id:x
});
var label = Titanium.UI.createLabel({
text:'LABEL '+x
});
button.add(label);
win1.add(button);
button.addEventListener('click', function(e){
Ti.API.info('Button clicked '+e.source.id);
});
}
The button.id property is just made up, but now you can see which button sends the event. You could also use title, or anything else that is unique.
Other options to look at are creating unique variable names for each button, but that's probably more work. Also, instead of working with putting a button in the table row, use a label or image, then listen for the event generated by the table or row.