I am an objective C newb and relative programming novice in general, so your patience is appreciated. Inside a View Based Application template I am pulling this code out of myNameViewController.m and trying to insert it into a custom class. Everything transitions fine except this: [self.view addSubview:myImage]; I gather this is now calling the addSubview method of myObject, which does not exist....what is the correct way to insert the subview into the current view?
#import "myObject.h"
#implementation myObject
-(void)drawImage{
CGRect myImageRect = CGRectMake(0.0f, 0.0f, 70.0f, 70.0f);
UIImageView *myImage = [[UIImageView alloc] initWithFrame:myImageRect];
[myImage setImage:[UIImage imageNamed:#"test.png"]];
myImage.opaque = YES;
[self.view addSubview:myImage];
}
#end
Your myObject has to be a subclass of UIViewController for this to work, since this will give it the view property (same as the viewController you've copied the code from.
In myObject.h, your interface should read:
#interface myObject : UIViewController {
}
which means that it subClasses, or becomes a UIViewController at heart. It can do anything a regular UIViewController can do and will inherit all the same properties (such as a view), but since it only subclasses it you are able to add extra information that is specific to your own object.
The code you have copied is deriving from UIViewController (which is where the view property is defined). addSubview is a message on the UIView object.
So your myObject needs to be a subclass of UIViewController so that you can access its child view, or perhaps myObject is just a view on it's own (does myObject derive from UIView ?), in which case you can just add the UIImageView to the view hierarchy for myObject:
[self addSubview:myImage];
Update
You need to implement the drawRect message in your UIView subclass and draw on context. So something like:
#implementation ViewWhichDrawsItself
- (void)drawRect:(CGRect)rect
{
// get the drawing context
CGContextRef context = UIGraphicsGetCurrentContext ();
// draw on the context
...
}
Related
I'm trying to add UIImageView subviews to my viewController.view, with consideration for whether they go above or below an image.
Basically, my viewController has an image of a body. I allow the user to add accessories to the scene, for example a hat. I need to put some of these images above, some below the body view index.
However I'm having trouble figuring out how to add the image behind the body. I figured I could try and create a UIImageView property as a reference point on the viewController and do something like this:
//this is from my menuItem class which has a UIViewController property connecting it to the main scene
[self.viewController.view insertSubview:sprite belowSubview:self.viewController.body];
However this code doesn't work, as I get the warning "Property body not found on object of type 'UIViewController *'", even though I #property and #synthesize it.
Does anyone know what I'm doing wrong, or have a better design on how to implement this? Thanks
#shubhank:
//.h
#interface ViewController : UIViewController {
UIImageView *body;
}
#property (nonatomic, retain) UIImageView *body;
//.m (in viewDidLoad)
self.body = [[UImageView alloc] initWithFrame:CGRectMake(250, 300, 339, 562)];
self.body.image = [UIImage imageNamed:#"body.png"];
[self.view addSubview:body];
[self.view insertSubview:sprite belowSubview:body]. Don't insert viewController after self, 'cause self IS viewController.
there is two things happening that i can't seem to understand.
[self.viewController.view insertSubview:sprite belowSubview:self.viewController.body]
Here you are accessing body by self.viewController.body
and then where body is defined
[self.view addSubview:body]
so how come you can access it both by view controller and self.view.
There is something wrong here..
Also
self.body = [[UIImageView alloc] initWithFrame:CGRectMake(250, 300, 339, 562)];
change it to
self.body = [[[UIImageView alloc] initWithFrame:CGRectMake(250, 300, 339, 562)]autorelease];
the property retains the UIImage view..you should release it.
Problem Solved:
Silly issue. I simply needed to forward declare my ViewController class in my MenuItem class, rather than use UIViewController *.
Thanks for your help.
I am initializing a new UIViewCOntroller object.
then attempting to set its view's position of stage but I am having some trouble.
here is the code I am using
Note: this code is placed in the application main UIViewController's viewDidLoad method
UIViewController * cont = [[UIViewController alloc] init];
cont.view.backgroundColor = [UIColor redColor];
CGRect rect = CGRectMake(100, 0, 320, 480);
cont.view.frame = rect;
this code is still positioning the subview at (0,0) instead of (100,0)
However, if I introduce a decimal, such as using 320.01 (for the width value) or 480.01 (for the height value). The view would be positioned correctly.
It seems that if I use a size with an exact width:320.0 height: 480.0,
the origin will always be set to (0,0) !!!
This is a bit strange. I was hoping that someone could explain why this is happening, and possibly how it may be resolved.
Cheers ....
NSLog the value of cont.view and I think you will find it to be nil, which explains why nothing's happening. This is not the normal way to create a UIViewController -- it's not wrong to create one programmatically, but 99.99% of the time UIViewController subclasses are created with the main UIView in a .xib file. A freshly created UIViewController object has a nil "view" member, so you've got to initialize it somehow, either by loading a .xib:
MyViewController *vc = [[[MyViewController alloc] initWithNibName#"MyViewController" bundle:nil] autorelease];
or manually creating the view:
MyViewController *vc = [[[MyViewController alloc] init] autorelease];
UIView *theView = [[[UIView alloc] initWithFrame:viewframe] autorelease];
vc.view = theView;
Then you can move the view's frame to your heart's content, but moving the base view of a view controller is usually not what you want to do, you want to create sub-views and move those around.
[[UIViewController alloc]init] is wrong. The designated initializer for UIViewController is initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle. Even that does not necessarily initialize the view outlet to an actual UIView immediately. You need to subclass UIViewController and perform your customisations in the viewDidLoad method of that subclass.
In the interim is likely that view is nil so you can try setting whatever properties of it you like without anything ever happening.
I think you should be able to use
-(void) loadView {
[super loadView];
//create your views programmatically here
}
in order to create your viewController programmatically and avoid the IB. Normally the IB calls this method for you when your 'view' property is nil, however if you're avoid the IB make sure to include the above method so your view property is not nil.
I want to create a 'detail view' in my navigation-based app similar to the address book app.
I want to create a UIView that has an UIImageView and a UILabel that I can pass to a UITableVIew's tableHeaderView property when pushed by a navigation controller. The label text and image must take information from the managed object context when it loads.
I started trying to do this using IB, but go fed up when the label text wouldn't update, regardless of where I put the myView.UILabel.text = #"some new text". It just kept presenting the text I entered in the IB inspector window.
So without using IB, how would I go about creating a UIView that has a UILabel and a UIImageView in it?
Should I be creating a new class that is a sub-class of UIViewController or just UIView?
How do I go about creating the sub-views for the label and image?
Where should the text and image URL be set in code? (viewDidLoad or loadView or viewWillLoad)(UIView, UIViewController, detailViewController)?
If you started using IB and the UILabel text wouldn't update, sounds like the IBOutlet of your view controller isn't correctly connected to the label in IB.
Hopefully that will fix your problem with using IB. And in the viewController code, you should update that text in viewDidLoad.
But if you want to do this programmatically, I would make a subclass of UIView (not UIViewController).
And I would override initWithFrame and do all the setup there.
Something like the following:
myView.m
#implementation myView
#synthesize imageView, myLabel;
- (id) initWithFrame:(CGRect) frame
{
if (self = [super initWithFrame:frame]) {
// Setup your image view and add it to the view.
self.imageView = [[[UIImageView alloc] initWithFrame:initWithFrame:frame] autorelease];
self.imageView.image = ...
[self addSubview:self.imageView];
// Setup your label
self.myLabel = [[[UILabel alloc] initWithFrame:frame] autorelease];
self.myLabel.text = #"whatever you like";
[self addSubview:self.myLabel];
}
return self;
}
Make sure to clean up memory properly in the dealloc method of course depending on whether you like make class properties vs class variables.
In my viewbased application i loaded oneview as mainview and another view as subview of mainview. Its work well the code snippet is ,
In mainviewcontroller,
IBOutlet UIView *subView;
#property(nonatomic,retain) UIView *subView;
#synthesize subView;
[subView release];
//add subview
[self.view addSubview:subView];
//removefromsubview
[subView removeFromSuperview];
This code works fine.....
I dont want to create subview in mainviewcontroller, so i created a new UIView class and its named as subView, now i deleted all declarations of subView from mainviewcontroller and just import subView class in mainviewcontroller. And using this [self.view addSubview:subView];
This things not work great. Can anyone help me ... How can i interact a separate UIView class with UIViewcontroller.One more thing is that UIView class have labels and textboxes can i set values from UIViewController to UIView labels and textboxes ......
Is it possible ?
Thanks in advance.......Sorry for my bad english
You have a sub-class called Subview which is declared as a UIView, i.e.
#interface Subview : UIView {
UILabel *foo;
}
#property (nonatomic, retain) UILabel *foo;
#end
Now you want to use this sub-class inside of your main UIView, which you had from the start. There are a few things you need to do.
#import the Subview in your header file, and add an instance of it to your class.
#import "Subview.h"
and inside of your #interface's {}'s,
Subview *mySubview;
In the viewDidLoad class for your main view controller, around the bottom, add something like:
mySubview = [[Subview alloc] init];
[self.view addSubview:mySubview];
[mySubview release];
First line will allocate a new "Subview" for you, second line will add this to your view so you get the stuff it has, and third line will release it. It's okay to release it here, because "self.view" will now be responsible for it, so it won't vanish.
Lastly you need to set the view up in the init method for Subview. In Subview.m, do something like:
- (id)init
{
if (self = [super init]) {
foo = [[UILabel alloc] init];
foo.text = #"Hello!";
[self addSubview:foo];
}
return self;
}
And I think that should take care of it. You also want to release foo in -dealloc for Subview but you probably know how to do that stuff already.
Just beginning with iPhone development i seem to miss something fundamental.
In a View based application i'm adding programaticaly a UIView subclass in the ViewController implementation file and can set a value:
- (void)viewDidLoad {
[super viewDidLoad];
CGRect myRect = CGRectMake(20, 50, 250, 320);
GraphView *graphView = [[GraphView alloc] initWithFrame:myRect];
[self.view addSubview:graphView];
graphView.myString = #"Working here";
}
When i try to change the same value with an action in the same file, the Build fails because graphView is undeclared:
- (void)puschButton1 {
graphView.myString = #"Not working here";
}
Because I use a UIView subclass there is no outlet for my GraphView instance.
How can i get a reference to my subview? Or should this be done in another way?
Thanks in advance
Frank
The easiest solution is to make graphView an instance variable for your view controller, instead of declaring it in viewDidLoad.
Put something like this in your .h file:
#class GraphView;
#interface MyViewController : UIViewController {
GraphView *graphView;
}
// ... method declarations ...
#end
If you don't want to do that, another way is to set graphView's tag property, and then call the superview's viewWithTag: method to retrieve the view when you need it.
I'm not sure what you mean by "Because I use a UIView subclass there is no outlet for my GraphView instance." You generally declare outlets on your controller class, and it doesn't matter whether you are using a subclass of UIView.
As an aside, I'll note that you should probably release that GraphView at some point, or you'll have a memory leak.
You could store graphView as a class variable.
EDIT: note that addSubview will increase the retain count of the object, somewhere in your class you will need to balance the alloc with a release and the addSubview with a removeFromSuperview or a release.