Draw to UIView subview using an instance of that subview - ios

I am trying to draw to a UIView subview from another class.
MainViewController with a view that I have dragged a UIView into in IB.
I have created a DrawView class and changed the UIView's(the one I dragged onto the MainController's view in IB earlier) class to DrawView.
I can draw to that DrawView UIView subview by coding in DrawView so that works as expected.
I have a custom UITableViewController class and would like to draw in the "DrawView UIView" from the custom UITableViewController. How to do so?
I have tried creating a new instance of DrawView from the custom UITableViewController and creating functions in DrawView that I can call to draw. Doesn't work because my created instance of DrawView is a different instance than the "DrawView UIView" in IB that is created on launch. The newly created DrawView's bounds are zero, too, passing in bounds for initWithFrame doesn't work.
I don't understand how I can get the same instance of DrawView created in IB to use in the custom UITableViewController.
In case the above is too wordy, I want to call drawing methods to draw in a UIView subview in its class from another class.
How can I implement this? Thanks.

Related

UIView: which method is called just before being shown?

I would like to make some operation inside a custom UIView, based on its width.
Which UIView method is called just after the UIView dimensions have been defined and before the UIView is ready to be shown?
The method is layoutSubviews: of the UIView class

Using a subclass of UIViewController subclass with subclass of UIView subclass

I have an MVC architecture of a certain view within my app. Now I want to create a subclass of the View and Controller part. The original UIViewController subclass is loaded with a UIView subclass from storyboard. How can I make my subclass of this UIViewController subclass use my subclass of the UIView subclass code when it loads its view?
EDIT
Here's some more details about what I want to do. I currently have these classes:
ControlView
ControlViewController
which are connected with storyboard. I load an instance of ControlViewController using:
self.storyboard!.instantiateViewControllerWithIdentifier("ControlViewController")! as! ControlViewController
Now what I want to do is subclass ControlView so that I can change some constraints and add a few extra subviews. Let's call this subclass ExpandedControlView. I also want to subclass ControlViewController because I want to add some extra actions from ExpandedControlView to the controller. This can be called ExpandedControlViewController.
Then I want to be able to instantiate ExpandedControlViewController and use ExpandedControlView like ControlViewController would with ControlView.
In storyboard, select the hierarchy view.
Then select your UIViewController's View in the hierarchy on the left, and select that view's class in the identity inspector on the right.
Or if you want to do it in code. Override viewDidLoad on ControlViewController, instantiate your custom view and set your ControlViewController's view property to your custom view.
-(void)loadView{
ControlView *myCustomView = [[ControlView alloc]initWithFrame:[UIScreen mainScreen].applicationFrame];
self.view = myCustomView;
}
One caveat when doing this is that the layout of any subviews might change from the time loadView is called. So if you have subviews in your custom view, you should also override layoutSubviews in your custom view and set all your view's subviews' frame property again there.
Implement loadView in your view controller subclass and set the view property with instance of your custom view subclass.

what is the difference between subview and subclass

Well, the title says it all. What is the difference (if any) between subview and subclass? Is a subview also a subclass? e.g. when the app launches, the main View is a subview of UIWindow, but UIWindow is a subclass of UIView.
The UIWindow is a subview of UIView becuase the UIWindow is a subclass of UIView. The same concept holds true in other object oriented languages. I can have a super class called Vehicle with subclasses car and motorcycle. The car and the motorcycle are 'subVehicles' of Vehicle...just like UIWindow is a subclass and therefore 'subView' of UIView.

Should i create a view ( consisting UIButton, UILabel etc) in a separate UIView class or inside UIViewController?

I have a UIViewController say viewControllerA which contains some view element like UIButton, UILabel etc. Now my question is should I create those view elements in a separate UIView class and then add in UIViewController, or should I create those view elements directly inside the UIViewController. Accordingly to MVC isn't it appropriate to create view elements inside a separate UIView class and then add this in UIViewController?
The standard place to build the view hierarchy in a UIViewController is in the -viewDidLoad method. That method gets called whenever the UIViewController's view is created. The view controller's view will be loaded from the NIB/Storyboard if applicable; your outlets will be wired up; and then -viewDidLoad is called for you to perform further customization:
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *aLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0,0.0,100.0,40.0)];
[self.view addSubView:aLabel];
}
In Cocoa/Cocoa Touch you don't always want to subclass everything the way you would in, say, Java. There are often other preferred means of extending the functionality in built-in classes such as Objective-C categories, delegation, and pre-defined properties.
It's certainly possible to do this sort of thing another way, but this is the most "Cocoa-like" way to do it. Actually, the most "Cocoa-like" way would be to create the view hierarchy in Interface Builder, but if you want to do it programmatically this is the usual way.

Programmatically set an IB object's Class

When using Interface Builder, a lot of the time I'd set the Class property to one of my custom classes. Say I have a UIView in the nib and I set the class to my MyView class.
That's all well and good, even when loading the nib programmatically.
But, is there a way to set the Class of a UI control when programmatically loading a nib? The reason being that I want to sometimes use the same nib created in IB, but have it associated with a different Class.
I don't think there is a proper way to achieve that programmatically.
You could create a naked UIView object in IB and give it a tag or assign it to an IBOutlet for its identification so taht you can access it programmatically in viewDidLoad.
In viewDidLoad you access it and fetch its frame and superview and probably background colour, alpha, hidden status etc, so that you can set all those values in IB. Then remove the UIView from its superview and nil the property (if any) or release the object respectively (depending on ARC or not). Then create the UI Element that you need, assign it to the property (if any) add it to the superview of the former UIView, set its frame and properties accordingly and go from there.
(There are ways in Obj-C to change an object's class after its instanciation, but I would not recommend doing that in this case, especially when your subclasses come with additional properties and ivars.)
Normally you create a UIView object on your UIViewController's class XIB file using Interface Builder and then you use the Custom Class tool in the Identity Inspector to associate the UIView with a class (The class is a UIView class containing the code for drawing on the UIView object.). Then you have to use #property and #systhesize in your UIViewController class to hook the UIView (using the connections inspector) to your class. This method is OK but in certain circumstances it has limitations.
You can get around all of this pragmatically.
Create the UIView class that will be used to draw on a UIView object. In this class you create the context reference (CGContextRef) to give the drawing tools a context (where to draw) for such things as strings, lines, circles, etc. i.e.
CGContextRef gg = UIGraphicsGetCurrentContext();
In the UIViewController class, in the .h file you need to import a reference to your UIView class. Let's call it: DrawOnView
#import "DrawOnView.h"
Then in the brackets encompassing the #interface place this line:
UIView * draw; // draw can be changed to any name that suits your needs
Then in the .m part of the class inside the viewDidLoad method you need to insert this code:
// Make the size and location that suits your needs
// You can change this on the go in your code as needed, such as if the
// device orientation is changed.
draw = [DrawOnView alloc] initWithFrame:CGRectCreate(50, 50, 100, 200)];
// You can change the background color of the view, if you like:
[draw setBackGroundColor:[UIColor greenColor]];
// Now add the view to your primary view
[self.view addSubview:draw];
Now, in other parts of our program, you can call methods you have declared in the DrawOnView class and refresh (which calls the drawRect method, the primary entry point in your UIView class) by using this reference:
[(DrawOnView*) draw setNeedsDisplay];
This is very important. Do not use:
[draw setNeedsDisplay]; // This will not work!
Let's say you have other methods defined in DrawOnView and want to call them.
Here's an example method (in the .h file):
-(BOOL) wasHotSpotHit: (CGPoint) p;
The actual method could look like this (in the .m file):
-(BOOL) washHotSpotHit: (CGPont) p
{
if(CGRectContainsPont(hotspot.frame, p))
{
return true;
}
return false;
}
Use code like this:
if([(DrawOnView*) draw testIfSpotHit:p])
{
// Do something for when user touches hot spot.
}
Try using "object_setClass(id object, Class cls)" method of Objective c runtime. GoodLuck:)

Resources