I have a custom cell in a UITableView using an xib file. I programatically created a UILabel with a height of 200 and a width of 50. When I do an NSLog in the customCell.m of the label's width and height, it gives me w: 50 and h: 200. But when I do an NSLog in mainViewController.m it gives me 0 for the height and width.
Not sure why it does that. I need to get the real height of the label in the mainViewController.m
Here's my code:
customCell.m
- (void)awakeFromNib
{
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 200)];
[self.label setText:#"This is a label"];
[self.myView addSubview:self.label];
NSLog(#"%f", self.label.frame.size.height); // Results: 200.0000
}
mainViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
customCell *cellVC = [[cutsomCell alloc] init];
NSLog(#"%f, %f", cellVC.label.frame.size.height); // Results: 0.0000
}
Isn't awakeFromNib supposed to get called the mainViewController.m at viewDidLoad if I use an xib file? If not, how do I call it in viewDidLoad?
awakeFromNib is an initializer called when you load from nib..ie you add a view and change its class to your custom class in storyboard/nib and this porcess will call awakeFromNib method..not programatically
When done programatically use init method for the purpose or a custom initializer
-(id)init
{
//class super init calls
//then method calls
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 200)];
[self.label setText:#"This is a label"];
[self.myView addSubview:self.label];
//return self
}
Example
- (id) init {
// Call superclass's initializer
self = [super init];
if(self) {
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 200)];
[self.label setText:#"This is a label"];
[self.myView addSubview:self.label];
}
return self;
}
Related
I am creating a game using Sprite Kit, want to add a text field over scene. Here is the code:
#interface MKMainMenuScene ()
//...
#property (nonatomic) NSTextField *field;
#end
#implementation MKMainMenuScene
- (void)didMoveToView:(SKView *)view
{
[super didMoveToView:view];
[self.view addSubview:_field];
}
- (id)initWithSize:(CGSize)size
{
if (self == [super initWithSize:size])
{
//...
_field = [[NSTextField alloc] initWithFrame:
NSMakeRect(self.frame.size.width / 2, self.frame.size.height / 2 + 20,
100, 40)];
[_field setBackgroundColor:[NSColor whiteColor]];
[_field setStringValue:#"Enter smth"];
}
return self;
}
But text field doesn't appear, it is under the scene. Does someone know what is the problem and how to solve it?
Got it working.
Must set necessary views as Layer-Backed Views. Tried doing this in the Nib, didn't work for me. So I did it in code.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
/* Insert Label. FOR TESTING, may remove */
NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(50, 50, 300, 300)];
[label setStringValue:#"Hello All"];
[label setTextColor:[NSColor whiteColor]];
[label setBackgroundColor:[NSColor redColor]];
[label setFont:[NSFont fontWithName:#"Helvetica" size:20]];
[[self.window contentView] addSubview:label];
/* SET LAYER BACK VIEW
* This is the one line code to make it work.
*/
[self.window.contentView setWantsLayer:YES];
}
UPDATE:
The above code will cause a freeze or a problem on either a SCNView or SKView. To fix this, don't set the UI as a subview, but as a sibling to SKView. And then set the UI as Layer-Backed by setWantsLayer.
Window
-> Content NSView
-> SKView/SCNView
-> NSTextField <-- Layer-Backed
Code:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
/* Insert Label. FOR TESTING, may remove */
NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(50, 50, 300, 300)];
// . . . .
[[self.window contentView] addSubview:label];
/* UPDATE */
[label setWantsLayer:YES];
}
Hope this helps someone else who's following my steps.
Try this one:
- (void)didMoveToView:(SKView *)view
{
[super didMoveToView:view];
[view addSubview:_field];
}
I have this in my config.h
#define SomeImage [UIImage imageNamed:#"some_pic.png"]
I have a class named Something subclass of UIImageView, imported config.h in Something.h
In Something.m initWithFrame method:
self.image = SomeImage;
The problem is when i create a new Something and add it to superview , I can't see anything.
I think I can handle the problem with initWithImage but couldn't figure out why my code isn't working.
Did you mentioned frame for your Something.m ?
It should work fine, example
Something *something = [[Something alloc] initWithFrame:CGRectMake(10, 10, 200, 200)];
[self.view addSubview:something];
Something.m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
self.image = SomeImage;
return self;
}
I would like to create a custom class by subclassing the UIView that would look like the one below:
Oh and the text says the body view should be 80px tall, its 50px.
But I cant seem to get it right. I have the class header prepared like so:
#import <UIKit/UIKit.h>
#interface MessageView : UIView
#property (strong, nonatomic)UIImage *backgroundImage;
#property (strong, nonatomic)UITextView *messageView;
#property (strong, nonatomic)UILabel *titleLabel;
- (id)initWithBackgroundImage:(NSString*)background;
- (void)setTitle:(NSString*)titleMessage;
- (void)setBody:(NSString*)bodyMessage;
#end
Now I will create these views by calling initWithBackgroundImage where I will pass the background image file name. The example shows one of these images. How do I implement the init method so that init will create a body like on the example except the texts will be empty?
My futile attempt of the init method was this:
- (id)initWithBackgroundImage:(NSString*)background
{
self = [super init];//[super initWithFrame:CGRectMake(0, 0, 270, 100)];
if (self)
{
backgroundImage = [[UIImage imageNamed:background] retain];
messageView = [[UITextView alloc] initWithFrame:CGRectMake(10, 40, 250, 50)];
titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 250, 20)];
}
return self;
}
But nothing happened. When done I will set the text via setter methods. And I would like to set the position on the final view via setCenter(x, y). I want the class to have "fixed" width and height.
Thanks!
EDIT:
- (id)initWithBackgroundImage:(NSString*)background
{
self = [super init];//[super initWithFrame:CGRectMake(0, 0, 270, 100)];
if (self)
{
UIImageView *bg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:background]];
messageView = [[UITextView alloc] initWithFrame:CGRectMake(10, 40, 250, 50)];
titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 250, 20)];
[self addSubview:bg];
[bg release];
[self addSubview:messageView];
[messageView release];
[self addSubview:titleLabel];
[titleLabel release];
}
return self;
}
I have a UIView class, to create the structure, I do:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
//creo la view
CGRectMake(0, 0, 100, 100); //I would just like the frame size
self.clipsToBounds = YES;
}
return self;
}
so I make the location and size of the frame.
I call this class in the main UIViewController
is there a way to just create the size of frame in the class, and in the UIViewController set the position?
MyClass *myClass1 = [[Item alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; //I would just like the frame position
[self.view addSubview:myClass1];
thanks a lot!
I think you are looking at something like initWithOrigin:.
- (id)initWithOrigin:(CGPoint)origin {
CGSize size = CGSizeMake(100,100);
CGRect frame;
frame.origin = origin;
frame.size = size;
return [self initWithFrame:frame];
}
Now you can use it as,
MyClass *myClass1 = [[MyClass alloc] initWithOrigin:CGPointMake(0,0)];
[self.view addSubview:myClass1];
I create a custom view in cocoa touch that is superclassed by UIView and in my main controller I initialize it and then add it as a subview to the main view, but when I add it to the main view it calls my initializer method again and causes an infinite loop. Am I going about creating my custom view wrong?
Here is the mainView
- (void)loadView {
UIImage* tempImage = [UIImage imageNamed: #"image1.jpg"];
CustomImageContainer *testImage = [[CustomImageContainer alloc] initWithImage: tempImage andLabel: #"test image" onTop: true atX: 10 atY: 10];
[self.view addSubview: testImage];
}
and the CustomImageContainer
-(CustomImageContainer *) initWithImage: (UIImage *)imageToAdd andLabel: (NSString *)text onTop: (BOOL) top atX: (int) x_cord atY: (int) y_cord{
UIImageView *imageview_to_add = [[UIImageView alloc] initWithImage: imageToAdd];
imageview_to_add.frame = CGRectMake(0, 0, imageToAdd.size.width, imageToAdd.size.height);
UILabel *label_to_add = [[UILabel alloc] init];
label_to_add.text = text;
label_to_add.alpha = 50;
label_to_add.backgroundColor = [UIColor blackColor];
label_to_add.textColor = [UIColor whiteColor];
[self addSubview: imageview_to_add];
self.frame = CGRectMake(x_cord, y_cord, imageToAdd.size.width, imageToAdd.size.height);
if (top) {
label_to_add.frame = CGRectMake(0, 0, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
//[self addSubview: label_to_add];
}
else {
label_to_add.frame = CGRectMake(0,.2 * imageview_to_add.frame.size.height, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
}
[self addSubview: label_to_add];
[super init];
return self;
}
Why did you put the [super init] statement at the end of the initializer ? When subclassing, you usually put this statement at the start of method.
For UIView subclasses, the designated initializer when creating views in code is initWithFrame:, so you should call it before adding the label and the image. You can use the image to compute the frame needed by the custom view.
-(CustomImageContainer *) initWithImage: (UIImage *)imageToAdd andLabel: (NSString *)text onTop: (BOOL) top atX: (int) x_cord atY: (int) y_cord{
// The view will gets its frame to the size of the image
UIImageView *imageview_to_add = [[UIImageView alloc] initWithImage: imageToAdd];
// Call the designated initializer
CGRect frame = CGRectMake(x_cord, y_cord, imageToAdd.size.width, imageToAdd.size.height);
self = [super initWithFrame:frame];
[self addSubview: imageview_to_add];
UILabel *label_to_add = [[UILabel alloc] init];
label_to_add.text = text;
label_to_add.alpha = 50;
label_to_add.backgroundColor = [UIColor blackColor];
label_to_add.textColor = [UIColor whiteColor];
if (top) {
label_to_add.frame = CGRectMake(0, 0, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
}
else {
label_to_add.frame = CGRectMake(0,.2 * imageview_to_add.frame.size.height, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
}
[self addSubview: label_to_add];
return self;
}
If you still have an infinite loop, pause the debugger and search for the recurrent method pattern in the stack trace. This pattern will gives you where the code enters the infinite loop.