I'm having a problem in Swift 3.0 right now.
As attached picture (a), I embedded navigationController into ViewController.swift. ViewController.swift have button to connect to UITableCell MovementStatusVC.swift. And MovementDetailsVC.swift is to display all value from table cell.
The problem that i'm facing right now is when I create button in MovementDetailsVC.swift and perform segue to pass the data inside "EditData" function, Page display twice.
MovementDetailsVC.swift
import UIKit
class MovementDetailsVC: UIViewController {
#IBAction func EditData(_ sender: Any) {
performSegue(withIdentifier: "EditMovementDetails", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
The EditMovementDetailsVC.swift controller display twice when I tap Edit button in MovementDetailsVC.swift as shown as in picture below.
I'm using perform segue and prepare segue in MovementDetailsVC.swift
How to fix it so the view only perform one time ?
Thanks.
Related
So for my own reasons, I need the full control that UITextField and its delegates would normally offer, but the screen it's being added to is written with SwiftUI. Needs a .decimal keyboard, so no Return Key.
I have only 2 issues remaining, 1 of which I hope to resolve here. Attempting to add a call to resign first responder and add it to a VStack on the page basically disables the UITextField, since I can't bring up the keyboard.
How can I dismiss this keyboard without adding an arbitrary extra button to the page?
Example Code:
Struct CustomTextView: UIViewRepresentable {
/// Insert init, updateView, binding variable, coordinator, etc
func makeView() -> UITextField {
var textField = UITextField()
textField.delegate = context.coordinator
/// Set up rest of textfield parameters such as Font, etc.
return textField
}
}
extension CustomTextView {
class Coordinator: NSObject, UITextFieldDelegate {
/// UITextfield delegate implementations, extra reference to binding variable, etc
/// Primarily textField.shouldChangeCharactersInRange
}
}
struct ContentView: View {
#State viewModel: ViewModel
var body: some View {
VStack {
CustomTextView($viewModel.parameter)
/// Other views
}
.onTap {
/// Attempting to add the generic call to UIApplication for resignFirstResponder here does not allow CustomTextView to ever hold it even when tapped in
}
}
}
I can't give all the code for privacy reasons, but this should be enough to establish my issue.
I have done this by adding this Function to you view below.
func hideKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
Then with a ontapGesture you can make the keyboard go away.
For example you can use this on the background Stack of your whole view. If a user taps on the background the keyboard will dissapear.
.onTapGesture {
self.hideKeyboard()
}
So I found a trick on my own with an epiphany overnight.
First, I would like to share to anyone else a very basic reason why inb4cookies solution wasn't quite adequate. While I had already tried adding a resignFirstResponder call like it to the onTap of the background stack, it was triggering the onTap for the VStack when I was clicking the field.
This is likely because I am using a UITextField as the back end for this component and not a SwiftUI TextField.
However, it was partially used in the final solution. I still applied it, but there is an extra step.
VStack {
CustomTextView($viewModel.parameter)
.onTap {/*Insert literally any compiling code here*/ }
/// Other views
}
.onTap {
self.hideKeyboard()
}
You'll see that above, there is an extra onTap. I tested it with a print statement, but this will override the onTap for the VStack and prevent the keyboard from being dismissed right after it is brought up. Tapping anywhere else on the VStack still closes it, except for Buttons. But I can always add hideKeyboard to those buttons if needed.
I am using the following code snippet:
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController
self.navigationController.pushViewController(secondViewController, animated: true)
I want to execute this code in the viewDidLoad. I will be using something like this in a series of if statements.
I used some code I found here that utilized a label. It did not work. Can a program move from one viewController without using a button? Almost every example, youtube video uses a button. I will be using a button when it is appropriate
You can not push view controllers before your current view controller loads. You should call your code in your viewDidAppear.
If you plan on directing to a particular view when the app launches I suggest you moving your logic to the AppDelegate in the method: didFinishLaunching. This way you don't need to unnecessarily load views.
Example of a ViewController being pushed in the viewDidAppear:
///
/// FUNCTION - VIEW DID APPEAR
///
override func viewDidAppear(_ animated: Bool) {
// GET VIEW CONTROLLER
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController
// PUSH VIEW ONTOP OF CURRENT NAVIGATION CONTROLLER
self.navigationController.pushViewController(secondViewController, animated: true)
} // END - FUNCTION
I have a Table View Controller as a tab. In it, there's a button that takes you to a Facebook profile:
func didTapFacebook() {
let url = URL(string: "http://www.facebook.com/" + myFacebookId)
if UIApplication.shared.canOpenURL(url!) {
UIApplication.shared.open(url!, options: [:], completionHandler: nil)
}
}
Works fine every time you press the button.
From another tab, there's a button that presents modally a navigation controller with Table View Controller as its root:
func segueToTable(_ sender: UIViewController, tvc: MyTableViewController, completion: #escaping ((_ done: Bool) -> Void)) {
let nc = MyNavigationController(rootViewController: tvc)
sender.present(nc, animated: true, completion: {
completion(true)
})
}
…
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tvc = storyboard.instantiateViewController(withIdentifier: "TVC") as! MyTableViewController
segueToTable(self, tvc: tvc, completion: { done in
print(“segue complete”)
})
Now once you tap the same button to go to Facebook profile (or Twitter button, basically anything that causes the app to go to background), this warning occurs (there is no keyboard displayed on the screen at this time):
Cannot snapshot view (>) with afterScreenUpdates:NO, because the view is not in a window. Use afterScreenUpdates:YES.
Returning to the app and pressing the button again causes this warning to appear (and every attempt after that):
Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.
I realize this is related to snapshotting a view that automatically occurs prior to entering the background. It appears for some reason it doesn't like doing that within a view that was presented modally. I've tried a variety of things based on other posts but cannot get the warnings to go away.
Any help is appreciated.
I currently have several labels and buttons in a UIView. I am using Storyboards and I want to add an image to the background. I tried it this way:
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(patternImage: UIImage(named:"background.png")!)
But unfortunately, this does not look right in the larger screen sizes. I think that I need to add a UIImageView. When I added a UIImageView, I couldn't figure out how to set it to be in the background so my button and labels could still be seen.
let someImageView: UIImageView = {
let theImageView = UIImageView()
theImageView.image = UIImage(named: "yourImage.png")
return theImageView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(someImageView) //This add it the view controller without constraints
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
someImageView.frame = view.bounds
}
In your storyboard:
1- Add a UIImageView (inside your main view and outside everything else) and set its image to the image you want.
2- setup its constraints properly to fill the screen (give it 0 from all sides).
3- From attribute inspector, set Content Mode property to Aspect Fit.
I solved this problem by going to the panel in Storyboards and moving the UIImageView above the container view that held the labels and buttons. The UIImageView remained inside of the View, but moved to the background (under the buttons and labels).
There is the Main Storyboard, from there three other storyboards with Navigation Controller, each one connected to a 4 view controllers so they use the back button to go back to their respective storyboard. Each Storyboard has a Storyboard reference to return to the Main Storyboard. Problem: each time the secondaries storyboards return to the main storyboard appears a Navigation Bar with
I used the following code in viewDidLoad():
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBarHidden = true
}
and also on viewWillAppear:
override func viewWillAppear(animated: Bool) {
self.navigationController?.navigationBarHidden = true
}