iOS How can I access UIView property from UIViewController - ios

Can someone Please walk me through the steps because I feel a little stuck and lost
Previous question : iOS - set UIButton target and action from its super class
Now I'm trying to get a more general idea - I'm very new to this
Help is very appreciated

If you are looking to access the UIView of an associated UIViewController from inside the view controller itself, you simply use self.view. To access the same UIView from outside of the UIViewController class you would use the instance name of the class plus the .view property. For example:
//SomeClass.m
- (void)accessVCView
{
//With a Nib File:
MyUIViewController *aVCObject = [[MyUIViewController alloc] initWithNibName:#"MyNib" bundle:nil];
//Or with a Storyboard:
MyUIViewController *aVCObject = [[UIStoryboard storyboardWithName:#"myStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:#"MyViewController"];
UIView *myUIViewControllerView = aVCObject.view;
}

Related

iOS how present Modal ViewController from Uiview

i have subclass a UIView and now i need to show a view controller but UIView not have method to present view controller.
this is my problem
thank's
this is a piece of code inside my uiview subclass
-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if ([tabella isEqualToString:#"Articoli"]) {
NSDictionary *itm=(NSDictionary*)[comanda objectAtIndex:indexPath.row];
Articoli *aboutViewController = [[Articoli alloc] initWithNibName:#"Articoli" bundle:nil];
aboutViewController.modalPresentationStyle = UIModalPresentationFormSheet;
aboutViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
aboutViewController.idarticolo=[itm objectForKey:#"idarticolo"];
CGRect aboutSheetFrame = aboutViewController.view.frame;
UIViewController *viewController = [UIViewController new];
viewController.view = self;
//here xcode give me a red error
[self presentViewController:viewController animated:YES completion:nil] ;
aboutSheetFrame =CGRectZero;
aboutViewController.view.superview.bounds = aboutSheetFrame;
}
}
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 a UIControl (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 or UICollectionView, 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.
You can do this without any view hierarchy issues using the below code.
ObjectiveC
UIViewController *currentTopVC = [self currentTopViewController];
currentTopVC.presentViewController.........
- (UIViewController *)currentTopViewController
{
UIViewController *topVC = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
while (topVC.presentedViewController)
{
topVC = topVC.presentedViewController;
}
return topVC;
}
Swift
var topVC = UIApplication.sharedApplication().keyWindow?.rootViewController
while((topVC!.presentedViewController) != nil){
topVC = topVC!.presentedViewController
}
topVC?.presentViewController........
PresentViewController is method of UIViewController class not of UIView, you can do one thing, create UIViewController instance and set its view to the view you have and then present it.
Something like below
YourCustomView *customView = [[YourCustomView alloc]initWithFrame:someFrame];
UIViewController *viewController = [UIViewController new];
viewController.view = customView;
//From currentViewController present this
[self presentViewController:viewController animated:YES completion:nil] ;
Customize this code as per your requirement
But as you are in view you need to pass this event to viewController, so better implement delegate method and at place where you calling present viewController call delegate which is implemented in ViewController and in side that presentViewController with customView set to its view property
You can also present your viewcontroller from the navigation controller object
Create Global Navigation Object in App Delegate or anywhere, you can access navigationcontroller object from view
#property (strong, nonatomic) UINavigationController *gblNavigation;
//Present viewcontroller from NavigationController object
[gblNavigation presentViewController:YOUR_VC_Object animated:YES completion:nil];
You can't present a view controller from a view. You can only present a view controller from a view controller.
Apple wants views to be dumb. That is views should only know how to display content. View should not respond to user interaction: that should be passed to a view controller.
You may want to consider using a delegate pattern, target action, or something similar to allow a view controller to control the interaction.
iOS 15, compatible down to iOS 13
Based on Shamsudheen TK solution for anyone who comes across this question in the future.
let presentedWindow = UIApplication.shared.connectedScenes.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }.first { $0.isKeyWindow }
guard let currentViewController = presentedWindow?.rootViewController else {
return
}
currentViewController.present(UIViewController(nibName: nil, bundle: nil), animated: true)
Note that connectedScenes is available only since iOS 13. If you need to support earlier versions of iOS, you have to place this in an if #available(iOS 13, *) statement.

Xcode 6 subclasses

I want to put a view controller inside a scroll view.
I think I can do it with something like:
MyViewController *vc = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
[scrollView addSubview:vc];
What I don't understand is how to specify my nib name correctly, because I have an interface built which I want to use but it is one of multiple views appearing in my main storyboard.
You cannot add a viewController as a subview. You can add a childViewController and the viewController's view as a subview. But you should probably read up more on how Objective-C and iOS works.

Property 'navigationController' not found. UIView Interface

I have a storyboard that handles all of my applications UI, apart from the header on each page which is handled by its own .xib file following this guide:
http://patientprogrammer.wordpress.com/2012/03/12/re-usable-subviews-in-ios/
Within my header .xib I have a button that I want to have when clicked load a view that is part of my story board.
I have tried:
- (IBAction)clicked:(id)sender {
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
someViewController *storyViewController = [mainStoryBoard instantiateViewControllerWithIdentifier:#"someViewController"];
[self.navigationController pushViewController:storyViewController animated:YES];
}
However as my class uses the interface UIView controller navigationController is not found, what can I do to launch a view within the story board from my UIView.
Or if there another interface I can use that will still let me have this as a subview.
what can I do to launch a view within the story board from my UIView
This is bad. A view is a view. Its purpose is to show something to the user, not controlling the app.
UIViewController is where you will need to do this. The navigationController is a property on this class, not on UIView. Read UIViewController class reference for more info.

Instantiating a view controller from another storyboard getting a key value coding-compliant error

I am attempting to add a UITableViewController subclass from another storyboard into the current on as one of the tab bar view controllers.
I am using the following code which is working for other view controllers.
UIViewController *vc;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
if (storyboard)
{
vc = [storyboard instantiateViewControllerWithIdentifier:#"ABCCustomViewControllerStoaryboardID"];
}
This gives me the following error:
* Terminating app due to uncaught exception
'NSUnknownKeyException', reason: '[
setValue:forUndefinedKey:]: this class is not key value
coding-compliant for the key fitnessStatusView.'
The fitnessStatusView is an outlet to a subview of one of the Static cells.
If I remove the outlet connection to this subview the problem goes away.
Is it not possible to connect a view in this way? It works fine when used in the storyboard that it is created in.
Any suggestions as to what I'm doing wrong here? Thanks.
Try this code :
UIStoryboard *loStoryboard ;
loStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
This code for navigate from AppDelegate Class..
// Instantiate the initial view controller object from the storyboard
UIViewController *initialViewController = [loStoryboard instantiateInitialViewController];
// Instantiate a UIWindow object and initialize it with the screen size of the iOS device
self.view = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Set the initial view controller to be the root view controller of the window object
[self.navigationController pushViewController:initialViewController animated:YES];
This code for navigate from Tabbar Controller..
UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"ABCCustomViewControllerStoaryboardID"];
[self.navigationController pushViewController:vc animated:YES];
Nope, you're not supposed to attach outlets from View Controllers to UITableViewCell subviews. Yes, I understand that the storboard allows it but it won't work in runtime as you (and I) have already found out.
I don't know why you need an outlet to a static cell subview though, because by definition, you shouldn't have to modify it because it's static.
If you really want an outlet to it, you can create a UITableViewCell subclass, assign it to the cell with the subview you want and then you can create the outlet from the subview in the storyboard to the UITableViewCell subclass. You can access the outlet in tableView:cellForRowAtIndexPath. Although that would make your table view dynamic. :)
I figured out the problem. It was related to the fact I testing another target and the table view subclass was not included in that target.
I must admit it would have been nice if I got a class not found error.

UIView in nib not connecting to IBOutlets

I am adding on screen a UIView in this way:
ViewController2 *detailViewController = [[ViewController2 alloc] initWithNibName:#"MJDetailViewController" bundle:nil];
[self presentPopupViewController:detailViewController animationType:MJPopupViewAnimationFade];
since MJDetailViewController is a nib and holds a UIView, I have created a custom class of UIView and selected it as class for the view in the inspector. When the window is loaded, the UIButtons do actions in the class that has been created, but the IBOutlets don't work. Even if I decided to add a UIButton programmably, it doesn't appear on screen. Why is this?
I thought of changing the UIView to a UIViewController, but it won't work because you can't present it with an animation.
I suspect you haven't set up the nib objects correctly.
In addition to setting the class of your UIView subclass you need to configure the 'File's Owner' and connect the views to it. You do this by selecting the file owner and setting its' class (this is done the same as setting the view's class). In your case the class of the file owner should be ViewController2.
Hopefully this screenshot explains this better:
Also you can simplify things a bit by using UIViewController nib naming conventions. If you give your nib the same file name as the view controller then you can specify nil as the nibName:. For example, if you name your nib ViewController2.xib then you can do this:
ViewController2 *detailViewController = [[ViewController2 alloc] initWithNibName:nil bundle:nil];
This approach is preferable as it means that the nib filename becomes an implementation details which calling code does not need to know about.

Resources