How can I call presentViewController in UIView class?
Call this function on your button
func infoClick() {
let storyboard: UIStoryboard = UIStoryboard (name: "Main", bundle: nil)
let vc: CampainDetailView = storyboard.instantiateViewControllerWithIdentifier("campainDetailView") as! CampainDetailView
let currentController = self.getCurrentViewController()
currentController?.presentViewController(vc, animated: false, completion: nil)
}
This function will create root view controller
func getCurrentViewController() -> UIViewController? {
if let rootController = UIApplication.shared.keyWindow?.rootViewController {
var currentController: UIViewController! = rootController
while( currentController.presentedViewController != nil ) {
currentController = currentController.presentedViewController
}
return currentController
}
return nil
}
This above code must work, it is working for me in Swift 4.0
How call presentViewController from UIView?
You are instantiating a new UIViewController here
func myV1(sender : UIButton!) {
v1Ctrl = V1ViewController()
v1Ctrl.presentViewController(SecondViewController(), animated : true, completion : nil)
}
And the v1Ctrl
, which now should present a new UIViewController, is not added to the Window hierarchy before.
Generally, you should think about your architecture because a UIView should not be responsible for creating a new UIViewController and present it.
The quickest fix for your problem should be to assign the v1Ctrl
var in viewDidLoad
of class V1ViewController
like and remove the line v1Ctrl = V1ViewController()
class V1ViewController : UIViewController {
var V1 : Myv1!
override func viewDidLoad() {
V1 = Myv1()
V1.v1Ctrl = self
self.view.addSubView(V1)
}
}
.
func myV1(sender : UIButton!) {
v1Ctrl.presentViewController(SecondViewController(), animated : true, completion : nil)
}
Using presentViewController from UIView
Only UIViewController can present another view controller, so if you need to show a viewcontroller from view there are several way, one of them is like this:
make a viewcontroller on which your parent view is situated a delegate of it
ParentView *view = [ParentView new];
...
view.delegate = self;
then, inside ParentView call method of that delegate
- (IBAction)homeButtonPressed:(id)sender {
[self.delegate buttonPressed];
}
and then, inside your VC implement
-(void)buttonPressed {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
ViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"ViewController"];
[vc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:vc animated:NO completion:NULL];
}
If you need to keep this code inside UIView and avoid delegation you can do a trick like this (personally i don't like it but it should work)
-(void)buttonPressed{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
ViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"ViewController"];
[vc setModalPresentationStyle:UIModalPresentationFullScreen];
[(UIViewController*)self.nextResonder presentViewController:vc animated:NO completion:NULL];
}
iOS how present Modal ViewController from Uiview
When you need a communication between UIView
instance and UIViewController
, there are a few known iOS concepts, which you should adhere to. As you have figured out that UIView
cannot really present a new controller (missing either presetViewController:animated:completion
methods or navigationController
property, which are both present in UIViewController
).
Views are supposed to be the most reusable parts of your code, so you must think of a way to design your views to be completely blind to where they are at. They usually only know about user interaction.
So first, what you must do is refactor your view.
- If your
UIView
is supposed to be aUIControl
(has some kind of target selectors), you need to use add target in your controller to get callback from view interaction. - You can use delegate pattern as used in
UITableView
orUICollectionView
, which is designed as a protocol. - You can use gesture recognizers added to a view (
UITapGestureRecognizer
for example), so the controller knows about user interaction.
You can even mix and match those architectural patterns.
But you should really look into iOS programming basics, to understand this better.
In addition the first error I see in your code is that you create a generic UIViewController
, when you should really be creating custom subclasses of it, defined in Storyboard and separate subclass of UIViewController
.
The second error I see is that your UIView
responds do tableView:didSelectRowAtIndexPath:
method, which should in fact never happen. All this code must be moved back to one UIViewController
subclass.
How to navigate To a ViewController From xib file of a UIView Class
I did it in a different way. In class file
class SlideMenuView: UIView {
var navigationController: UINavigationController? // Declare a navigation controller variable
// And create a method which take a navigation controller
func prepareScreen(navController: UINavigationController)-> UIView {
navigationController = navController
let nibView = NSBundle.mainBundle().loadNibNamed("SlideMenuView", owner: self, options: nil)[0] as! UIView
self.addSubview(nibView)
return nibView
}
// In Button action
@IBAction func btnAction(sender: UIButton) {
var storyBoard = UIStoryboard(name: "Main", bundle: nil)
let nextViewController = storyBoard!.instantiateViewControllerWithIdentifier("NextViewController") as! UIViewController
navigationController?.pushViewController(nextViewController, animated: true)
}
}
// For calling from UIViewController
slideBarMenuIstance.prepareScreen(self.navigationController!)
How would you presentViewController from subview?
You can always use application rootviewController to present your alert view controller :) You dont always have to opt for your view controller's view :) rootview controller is always accessible no matter where your control is :)
Here is what you can do :)
Objective C
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate.window.rootViewController presentViewController:your_alert_view_controller animated:YES completion:nil];
Swift
let appDelegate : AppDelegate? = UIApplication.sharedApplication().delegate as? AppDelegate
if let unwrappedAppdelegate = appDelegate {
unwrappedAppdelegate.window!.rootViewController! .presentViewController(alert, animated: true, completion: nil)
}
Hope my answer helped you :)
How to call presentViewController?
You call the method on the UIViewController that is your MainView, and pass it your UIViewController you want to be the ActionSheet.
[mainViewController presentViewController:actionSheetController animated:YES];
To dismiss the UIActionSheet, dimissWithClickedButtonIndex:animated:
is a method for the UIActionSheet that you can implement. The method can be called by whoever (so if you want to dismiss it from your mainview have a reference to the action sheet and do something like [self.myActionSheet dismissWithClickedButtonIndex:0 animated:YES];
The method is also called whenever the 'cancel' button is clicked by the user.
how to instantiate ViewController from UIView in SWIFT
However..i accomplised using a delegate to pass an id from UIView to UIViewController and checking to the id i instantiated ViewController From UIViewController class as Para said in his answer . I did it as below
Steps:
1) First create a protocol
2) create a Variable delegate conforming to protocol
3)Then create a call back method.
//Step1:
protocol SendIndexDelegate{
func sendIndex(Int);
}
class CustomSwipeView: UIView , UITableViewDataSource , UITableViewDelegate {
var delegate : SendIndexDelegate? //Step2
override init(frame: CGRect) {
super.init(frame: frame)
self.addCustomView()
}
......
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var row = indexPath.row
//for optional binding
if let temp = self.delegate {
delegate?.sendIndex(row) //Step 3
}else{
println("optional value contains nill value")
}
}
}
Steps Continued for Another Class:
4) Conform to the protocol SendIndexDelegate(so method sendIndex(Int) must be impelemented by this class)
5) Assign the value self in variable delegate in the optional variable delegate(it says that i will act as delegate for Class CustomSwipeView and implement the method sendIndex(Int))
6) Now implement the method and add body to it(because it has been delegate so must handle actions of the above class through call back method)
class RootViewController: UIViewController,SendIndexDelegate //Step4 {
let rect: CGRect = CGRect (x: self.view.frame.size.width, y :10 , width: self.view.frame.size.width-50, height: self.view.frame.size.height-10)
var a = CustomSwipeView(frame : rect)
a.delegate = self//step5
self.myView = a
self.view.addSubview(self.myView)
}
// Step 6:
func sendIndex(row : Int){
switch row {
case 0:
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let moneySummaryVC: MoneySummaryVC = storyboard.instantiateViewControllerWithIdentifier("moneyVC") as! MoneySummaryVC
self.navigationController?.pushViewController(moneySummaryVC, animated: true)
default:
println("no index")
}
}
Related Topics
Split String into Array of Arrays
Get Progress of Uinavigationcontroller Swipe Back
iOS Swift No Such File or Directory in Debug-Iphoneos
How to Set Clear Background in Table View Cell Swipe Action
Peek/Pop Preview Ignores Cell Corner Radius in Collection View
How Is It I Can Animate the Change in Bar Tint Color of a Uinavigationbar But Not a Uitabbar
Swift - Using Cgcontext to Draw with Finger
Swift, Parse.Com: How to Pass Data from Query
Struggling to Convert Objective C Selector and Target Signature to Swift
Turning on Thread Sanitizer Results in Signal Sigabrt
iOS Healthkit How to Save Heart Rate (Bpm) Values? Swift
Uitapgesturerecognizer Sender Is the Gesture, Not the UI Object
iOS with Parse. Pfuser.Currentuser() Not Getting Cached. Returns Nil After App Restart