How come my IBAction isn't connecting? - ios

So in my attached image I show my subclass I'm creating for my HOME button. I have many VCs with a HOME button and I want to connect them to this class to make them all send the user HOME
So far, I made my button to take this class, as shown in the image. My issue is I'm not able to connect my IBAction here and not sure why.... would appreciate any tips anyone can tell me about why I'm not able to connect my IBAction function to the button right now....
Another confusing thing is that although I haven't given any of the other buttons in this stackview of buttons a class, I'm actually able to connect any of my other buttons in this stackview to my IBAction... which I find odd.
class HomeButton: UIButton {
#IBAction func showHomeVC(sender: AnyObject) {
var sb: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var vc: UINavigationController = sb.instantiateViewController(withIdentifier: "HomeNC-ID") as! UINavigationController
self.present(vc, animated: false, completion: nil)
}
}
I'm aware that I can simply go to each VC where there's a HOME button and create an IBAction from each and just paste this code in there and it will work, but I would like to do this another way where I don't have to have so much of the same code being repeated.... I would like to know what changes need to be made to make this happen.

The error that you are are getting is because you are using the class of UIButton which doesn't have the property to display a view controller. You should present it either on a UIViewController, or one of the other types.
It is linked up but you just can't present a view controller using self (UIButton)

Related

How should we show following ViewController?

I am facing a interrogation, and I hope you could help me to find an answer.
I am selecting X items in a row.
I have already made a custom alert for 1 item selection in a row that look like this.
Here is how I call the alert
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let myAlert = storyboard.instantiateViewController(withIdentifier: "uploadAlert") as! AlertUploadViewController
myAlert.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
myAlert.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
let image = self.interventionsSelected[0].picture
myAlert.initAlert(image: image!)
request.view.present(myAlert, animated: true, completion: nil)
As you can see, I'm only taking the first image selected. Now, I want to take ALL selected images.
My problematic here is that I want to link all alerts and make smooth transition between them. How can I link the dismissing of an alert and the presenting of the next one ?
Should I make a array of all alerts and catch the dismissing ?
Should I have to use closure and linking all closure ?
I am not sure how I can do that in the best possible smooth way.
you need to maintain a delegate method for the alertcontroller of yours
make a Protocol as
protocol AlertProtocol: class {
func showNextAlert()
}
now assign your main view controller as its delegate
in your alertviewcotntroller:
var delegate: AlertProtocol?
and as you click button in alert controller to do something and close the alert , in its completion handler
self.dismiss(animated: true) {
self.delegate.showNextAlert()
}
this was your current alert closes, and a window heirarcy is maintained and another alert is opened with new data in flow
I would not go with multiple alerts at the same time because it seems visually what will happen is your darker background will be even darker with more alerts. And when dismissing each of them you will have the background brighter...
Supporting multiple images internally seems quite good but it is maybe not scalable if you later choose that some of these internal views will be completely different (one for images the other for whatever you can think of).
The best scenario I can think of is creating this overlay view controller with a container view. So this view is capable of showing view controllers and is able to animate them internally. The interface from how you then use it would look something like:
let container = MyContainerViewController.instantiateFromStoryboard()
container.injectViewControllers([
ShowImageViewController.instantiateFromStoryboard(image: image[0], delegate: self),
ShowImageViewController.instantiateFromStoryboard(image: image[1], delegate: self),
ShowSomethingElseViewController.instantiateFromStoryboard(data: data[0], delegate: self)
])
present(container...
So then I guess you would have a delegate method such as
func embeddedController(_ sender: UIViewController, shouldProceedWithData outputData: Any?) {
if container.canGoForward() {
container.forward(animated: true)
} else {
container.dismiss(...
}
}

Instantiating ViewController from new storyboard

I have just made a small transition so my project loads a different storyboard as its main (did it in the info.plist).
I have my new storyboard to keep my viewController that are responsible for login screen etc. Just to make it more clear.
After the login button is tapped I want to initiate a navigationController from another storyboard:
func instantiateViewController(fromStoryboard storyboard: String, withIdentifier identifier: String) -> UIViewController! {
let storyboard = UIStoryboard(name: storyboard, bundle: nil)
let viewController = storyboard.instantiateViewControllerWithIdentifier(identifier)
return viewController
}
#IBAction func loginButtonTapped(sender: UIButton) {
let viewController = instantiateViewController(fromStoryboard: "Main", withIdentifier: "MainNavigationController")
presentViewController(viewController, animated: true, completion: nil)
}
Everything works correctly but one thing is driving me nuts.
After presenting the MainNavigationController from Main.storyboard its view hierarchy is not maintained.
What I mean is, the labels and buttons which supposed to be on top of another, full screen UIView (but are not its child and so they should remain) are now behind it.
What might be causing this and what is the simplest way to make them appear on top (as they do whey I open main.storyboard)
EDIT
I added a line of code in the rootView of the MainNavigationController in its viewDidLoad method:
self.view.sendSubviewToBack(wholeScreenView)
and it solved the problem.
However, does anybody know why do I have to code it myself and the views are not like in the Main.storyboard?
The storyboard is not configured the way you think it is. Your wholeScreenView is in fact in front of the other views, in the storyboard. The other views (the labels and buttons) are not subviews of wholeScreenView; they are subviews of the main view, and so is wholeScreenView. It is a later subview, so it is in front of them.

Segues from a PopupView

I am facing a problem I cannot solve alone. At least, I don't know what's the right way to program this. I am writing an app which will open a PopupView as a Subview of my main menu when pressing + . This looks like this:
As soon as this subview is visible, I want to perform different segues (when pressing button 1,2,3 or 4) so this popup can change the view to 1-4:
I created a separate Storyboard for this popup and when pressing +, the initial view of it will be added as a subview:
let addFilePopup : UIStoryboard = UIStoryboard(name: "AddFilePopup", bundle: nil)
animations.showInView(self.view, aView: addFilePopup.instantiateInitialViewController()?.view, animated: true)
// the method for adding the PopupView as a Subview
func showInView(superView: UIView, aView: UIView!, animated: Bool)
{
aView.center = superView.center
superView.addSubview(aView)
if animated
{
self.showAnimate(aView)
}
}
Showing the Popup itself works so far, but as soon as I press one button, the segue of the Popup is not performed... Do you have any hints to me for this problem? Besides, is this the right approach?
If you also could let me know how I can make the superview.alpha = 0,5 and ignoring touches without taking affect on the subview that would be great too. Thanks in advance!

How to open next viewcontroller after choosing image from gallery (swift)

I am trying to open next viewController after choosing photo from gallery. I can get image from gallery, but after that I dont know how to open controller next to it. !.This is photo of that storyboard
You can put an UITapGestureRecognizer inside your UIImageView using Interface Builder or in code (as you want), I prefer the first. The you can put an #IBAction and handle the tap inside your UIImageView, Don't forget to set the UserInteractionEnabled to true in Interface Builder or in code.
To present the next view controller you can do it in code like below or just using Interface Builder using a segue through the UITapGestureRecognizer you set before (it's up to you).
To present the view controller manually like in the following code you need to set the Storyboard ID for you view controller like in the following picture (in the Identity Inspector panel):
#IBAction func imageTapped(sender: AnyObject) {
// Set the storyboard name by default is Main
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
// Instantiate the ViewController with the name you set before like in the image
let nextViewController = storyboard.instantiateViewControllerWithIdentifier("ViewControllerB") as! UIViewController
// present the nextViewController
self.presentViewController(nextViewController, animated: true, completion: nil)
}
I hope this help you.

Programmatically changing View Controllers without Navigation Controller Swift

I want to switch to a new view controller when I press a button without using a navigation controller and I can't seem to be able to do this. I have looked everywhere for an answer but everything that I have found is either in objective-c, using a navigation controller, or not working at all.
func gunsoutButtonPressed(sender:UIButton!) {
print("yay\t")
//let encounterVC:AnyObject! = self.storyboard?.instantiateViewControllerWithIdentifier("ecounterViewController")
//self.showViewController(encounterVC as UIViewController, sender: encounterVC)
let encounterViewController = self.storyboard.instantiateViewControllerWithIdentifier("encounterViewController") as encounterViewController
self.pushViewController(encounterViewController, animated: true)
}
You have to connect the two ViewControllers you would like to use. Then name the segue however you want and then use the following code to trigger the segue (inside an IBAction or something). It is not completely programmatically but you can trigger them programmatically, which should be enough.
performSegueWithIdentifier("mySegue", sender: nil)
Check out this video for support.
Hope this helps :)
You cannot use a push segue without a UINavigationController. You could achieve this with a modal segue, such as this:
self.presentViewController(encounterViewController, animated: true, completion: nil)
Segue
So you use the Segue ID to make sure you segue correctly.
No Segue
I would suggest doing this instead though:
let vc = ViewControllerToSegueTo()
self.presentViewController(vc, animated: true, completion: nil)
It is slightly better if you do not want to use the storyboard.

Resources