Yet another custom UIView subclass - objective-c

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;
}

Related

Calling awakeFromNib from xib file in the main ViewController

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;
}

Greedy NSProgressIndicator Allocation

I'm using a bunch of NSProgressIndicators at once (32 to be exact) and it looks like when they're animating they start allocating memory like no one's business
I've got reports that the app will slowdown and eventually crash after days of uptime, and this looks like the most likely culprit, but it's hard to pinpoint bugs that take days to appear.
I simply comment out the call to start animating, all memory behaves as expected. Could this be a result of multiple NSProgressIndicators alloc'ed on the same thread? or maybe sandboxing? All of the constant allocations are coming from Core Animation threads, I don't know what else could be going on.
Custom NSView that the progress indicator lives in
#interface MyView ()
#property (nonatomic, strong) NSImageView *imageView;
#property (nonatomic, strong) NSTextView *numberTxt;
#property (nonatomic, strong) NSProgressIndicator *progress;
#end
#implementation MyView
- (id)initWithFrame:(NSRect)frameRect {
self = [super initWithFrame:frameRect];
if (self) {
// Image
NSImage *image = [NSImage imageNamed:#"bg.png"];
CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
self.imageView = [[NSImageView alloc] initWithFrame:NSRectFromCGRect(rect)];
self.imageView.image = image;
[self addSubview:self.imageView];
// Number
CGRect numberRect = CGRectMake(0, 30, image.size.width, 40);
self.numberTxt = [[NSTextView alloc] initWithFrame:NSRectFromCGRect(numberRect)];
[self.numberTxt setBackgroundColor:[NSColor clearColor]];
[self.numberTxt setEditable:NO];
[self.numberTxt setFont:[NSFont systemFontOfSize:30]];
[self.numberTxt setTextColor:[NSColor redColor]];
[self addSubview:self.numberTxt];
// Progress
CGRect progressRect = CGRectMake(self.frame.size.width * 0.5 - 20, self.frame.size.height * 0.5 - 20, 40, 40);
self.progress = [[NSProgressIndicator alloc] initWithFrame:NSRectFromCGRect(progressRect)];
[self.progress setStyle:NSProgressIndicatorSpinningStyle];
//This line, when commented, fixes things
[self.progress startAnimation:self];
//
[self addSubview:self.progress];
}
return self;
}

Why doesn't this UIImageView Show up?

If I set this UIImageView as an IBOutlet it works fine and shows up in the sim. But programmatically it isn't working. I think I am missing a step or forgetting a line of code.
It is declared as
#property (nonatomic,retain) UIImageView *circleView;
and the implementation
self.circleView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
self.circleView.center = self.view.center;
[self.view addSubview:circleView];
You just forgot to initialize your UIImageView that's why it's not working ...
self.circleView = [[UIImageView alloc] init];
self.circleView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
self.circleView.center = self.view.center;
[self.view addSubview:circleView];

How to hide the keyboard if I have a UIView(contains several textview) in Scrollview

I have several textview in my UIVIew which contained in a scrollview.
First the scollview doesn't not actives when I touched it and want to hide the keyboard after finished the textview editing. So I had build a class name subUIView inherit from scrollview. In that class I overwrite the touch touchbegan events. like the code blow.
But after that the textviewbeingediting function didn't action any more. It's all about touchbegan events calling even when I want to edit the textview.
Could you offer me some advise to solve the problem?Thanks
//
// **subUIView.h**
#import <UIKit/UIKit.h>
#interface subUIView : UIScrollview
{
}
#end
// **subUIView.m**
#import "subUIView.h"
#implementation subUIView
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
self.delegate=self;
//return [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;}
NSInteger a=0;
- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) event { NSLog(#"touch began ");
// If not dragging, send event to next responder
if (!self.dragging)
{
[self.nextResponder touchesBegan: touches withEvent:event];
}}
in the code blow I alloc scrollview from subUIView and code the textviewbeginediting function.
//
// **ReadExperienceInfoViewController.h**
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#define ExperienceTableName #"pockets"
#class subUIView;
#interface ReadExperienceInfoViewController : UIViewController <UITextFieldDelegate,UITextViewDelegate> {
subUIView *scrollView;
UIView *upView;
UITextField *bookNameTextField;
UITextView *bookExprection;
NSString *getFullDateStr;
BOOL dragging;
}
#property (nonatomic, retain) UIView *upView;
#property (nonatomic, retain) subUIView *scrollView;
//
// **ReadExperienceInfoViewController.m**
//- (void)loadView{
scrollView=[[subUIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
scrollView.contentSize=CGSizeMake(320, 960);
scrollView.backgroundColor=[UIColor colorWithPatternImage :[UIImage imageNamed:#"infomation.png"]];
scrollView.showsVerticalScrollIndicator=YES;
upView=[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
upView=[[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 960)];
[upView setUserInteractionEnabled:YES];
UILabel *bookName = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 100, 30)];
bookName.backgroundColor = [UIColor clearColor];
bookName.text = #"Title";
bookName.font=[UIFont boldSystemFontOfSize:16];
[upView addSubview:bookName];
[bookName release];
bookNameTextField = [[UITextField alloc] initWithFrame:CGRectMake(20, 50, 280, 30)];
bookNameTextField.backgroundColor = [UIColor whiteColor];
bookNameTextField.returnKeyType=UIReturnKeyDone;
bookNameTextField.delegate=self;
[upView addSubview:bookNameTextField];
//lowerView=[[UIView alloc] initWithFrame:CGRectMake(0, 90, 320, 170)];
UILabel *bookExprectionLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 80, 200, 30)];
bookExprectionLabel.text = #"Content";
bookExprectionLabel.font=[UIFont boldSystemFontOfSize:16];
bookExprectionLabel.backgroundColor = [UIColor clearColor];
[upView addSubview:bookExprectionLabel];
[bookExprectionLabel release];
bookExprection = [[UITextView alloc] initWithFrame:CGRectMake(20, 110, 280, 140)];
bookExprection.backgroundColor = [UIColor whiteColor];
bookExprection.font = [UIFont systemFontOfSize:14];
bookExprection.delegate=self;
[upView addSubview:bookExprection];
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:#"Save"
style:UIBarButtonItemStylePlain
target:self action:#selector(updateExperience)]
autorelease];
self.title= bookNameStr;
self.view=scrollView;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
upView.frame=CGRectMake(0, 0, 320, 960);
[UIView commitAnimations];
[bookExprection resignFirstResponder];
[bookNameTextField resignFirstResponder];
}
-(void)textViewDidBeginEditing:(UITextView *)textView{
NSLog(#"texview dig begin editing");
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
if (textView==bookExprection) {
upView.frame=CGRectMake(0, -80, 320, 0);
}
[UIView commitAnimations];
}
Your subUIView.h File must implement the UITextFieldDelegate Protocol, so your viewcontroller responds to the delegate methods for the text field.
Same for the Scroll view, you have to implement the ScrollView
//subUIView.h
#interface subUIView : UIViewController <UIScrollViewDelegate, UITextFieldDelegate>{
//do stuff
}
Then of course you must write scrollView.delegate = self; so that the viewcontroller responds to the delegatemethods for the scroll view.
Hope this helps

How to perform a [self.view addSubview: lbl] outside of ViewController Class scope?

How to perform a [self.view addSubview: lbl] outside of ViewController Class scope ?
or:
How do I add a label or another view in the mainview, outside of the ViewController class, in a different class?
thanks
- (void)viewDidLoad {
[super viewDidLoad];
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[lbl setText:#"hi there"];
[self.view addSubview:lbl];// <-- this works, but ...
// what is "self" referring to?
// and how can I declare and call from another class?
...
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[lbl setText:#"hi there"];
calcRomanAppDelegate *v = [[calcRomanAppDelegate new] init];
[v.viewController.view addSubview:lbl]; // this compiles, but...
// fails to shows a label on the form
...
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[lbl setText:#"hi there"];
calcRomanViewController *v = [[calcRomanViewController new] init];
[v.view addSubview:lbl]; // this just makes a call back to viewDidLoad... endless loop
}
Well, view is just a property of the UIViewController class. Assuming that you have your UIViewController *controller variable somewhere, you can just use
[controller.view addSubview:subview]
The reason that [v.viewController.view addSubview:lbl]; doesn't work is that v is a new instance of calcRomanAppDelegate. Every application has a shared instance of the app delegate, that can be accessed via [[NSApplication sharedApplication] delegate]. Therefore, your code would become:
calcRomanAppDelegate *v = (calcRomanAppDelegate *)[[NSApplication sharedApplication] delegate];
[v.viewController.view addSubview:lbl]; // this compiles but shows a blank form
Also In the code that you wrote, I will point out that the new method returns an initialized object, so you do not need the extra call to init in [[calcRomanAppDelegate new] init]. Instead of using the new method, I suggest using alloc, which doesn't call the initializer. Obviously that is not the issue in this particular case, but it's an important thing to know.
Not sure what you tried to accomplish.
But let's say you are in the view1 and want to create another view (view2) with your UILabel lbl added to this view2. Here are what you would do:
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(x, y, w, h)]; //x,y, w h are for your view2
[view addSubview:lbl];
[self.view addSubview:view2]; //self is your current viewcontroller - you add view2 on top of view1
On the other hand if you already have a ViewController class ViewController2.h, ViewController2.m and a ViewController2.xib defined. Here are what you would do:
ViewController2 *viewController2 = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
[viewController2.view addSubview:lbl];
[self.view addSubview:viewController2.view]; //same as before, you need to add viewController2's view to the current view
Hope this help.