iOS: How to add more views after viewDidLoad - ios

I am new to IOS programming. I am starting from the basic application created by XCode 4.3 (SingleView application).
Continuing from my above question, I was able to add Views programmaticaly to the main ViewController in the Appdelegate but If I want to do the same after the view has loaded (inside viewDidLoad), I am facing the trouble. I tried using the same logic of adding subviews but I am not sure if the view needs a refresh after adding inside 'viewDidLoad'
My views are very simple, here is the code
-(void)viewDidLoad
{
[super viewDidLoad];
UIBUtton *btn = [UIBUtton] alloc] initWithFrame:CGRect(10,10,50,50)];
[self.view addSubView:btn];
[self.view setNeedsDsiplay];
}
Can someone please help?

You are not instantiating the UIButton correctly. You should use buttonWithType: method.
For example:
- (void)viewDidLoad {
[super viewDidLoad];
UIButton * btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setFrame:CGRectMake(10.0, 10.0, 50.0, 50.0)];
[[self view] addSubview:btn];
}

You have placed square brackets at wrong places. Probably you are new to Objective-C. You should pay more attention to learning syntax before creating UI based apps.
UIBUtton *btn = [UIBUtton] alloc] initWithFrame:CGRect(10,10,50,50)];
Should be:
UIBUtton *btn = [[UIBUtton alloc] initWithFrame:CGRect(10,10,50,50)];
Also
[self.view setNeedsDsiplay];
is not needed.

Related

understanding uibutton target self superview

Can someone please explain to me the uibutton target functionality from this example:
I have a ViewController. I add a uiview with two buttons to this viewcontroller. One button is crated in the init and the other one is created by a method 'addSecondButton'. Both buttons have the same action on [self superview] target which is the ViewController. The code:
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
MySpecialView *myspecialview = [[MySpecialView alloc] initWithFrame:self.view.frame];
[self.view addSubview:myspecialview];
[myspecialview addSecondButton];
}
- (void)specialMethod { NSLog(#"right here!"); }
MySpecialView.m
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 30, frame.size.width, 50)];
[button addTarget:[self superview] action:#selector(specialMethod) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor = [UIColor blueColor];
[self addSubview:button];
}
return self;
}
- (void)addSecondButton {
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 90, self.frame.size.width, 50)];
[button addTarget:[self superview] action:#selector(specialMethod) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor = [UIColor redColor];
[self addSubview:button];
}
So when tapping the blue button which is created in the init, specialMethod does execute. When pressing the red one which is added after the init, the app crashes with the warning - unknow selector for uiview.
What I really don't understand is when I NSLog [self superview] in the init, it is null, because the object is not yet created and returned to the superview, but the action does get executed for some reason.
Thanks for the help!
You have indeed added a nil target for the blue button in initWithFrameMethod. According to the Apple's Event Handling Guide, when you add a nil target, the message (specialMethod in your case) will be passed through the responder chain:
When the user manipulates a control, such as a button or switch, and the target for the action method is nil, the message is sent through a chain of responders starting with the control view.
As your ViewController is a part of the responder chain, it will receive this message and call its specialMethod.
[self superview] is a pointer to ViewController's view, not ViewController itself. The selector you are defining as the action for the button should target the instance of ViewController, not the ViewController's view since you have the method specialMethod defined in ViewController. If you really wanted to use [self superview] as the target for the action, then you'll need to subclass UIView, implement specialMethod and set that new UIView subclass as the view of the view controller (not a subview). This way, [self superview] will refer to a class that actually has the selector specified on the target.
I didn't actually try your code sample, but it's so obviously wrong, if it does work, it's coincidence and shouldn't be relied upon.

Xcode 6 button target not working

I just installed xcode 6 to test out how my app works with it.
The facebook login button on the initial page does not appear to be working.
Here is my code:
#property (nonatomic, strong) UIButton *loginButton;
- (void)viewDidLoad
{
[super viewDidLoad];
self.loginButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 200, 70)];
self.loginButton.center = self.view.center;
[self.loginButton setImage:[UIImage imageNamed:#"login_fb.png"] forState:UIControlStateNormal];
[self.view addSubview:self.loginButton];
[self.loginButton addTarget:self action:#selector(loginButtonPressed) forControlEvents:UIControlEventTouchUpInside];
}
-(void)loginButtonPressed
{
// perform login
}
It is important to note that the app starts off on a different view. In that view controller I check to see if a user exists or not, and if not I present the login view. Here is that code:
if ([DCTUserIdentity currentIdentity] == nil) {
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:[NSBundle mainBundle]];
DCTInitialLoginVC *vc = [sb instantiateViewControllerWithIdentifier:#"InitialLogin"];
vc.delegate = self;
[self presentViewController:vc animated:NO completion:^{}];
}
I put a breakpoint in the loginButtonPressed function and it never gets hit when I try clicking on the button....any idea whats going on?
It appears that this is not actually a bug, but an incompatibility issue of targeting iOS 7 devices using Xcode 6. ecotax's post describes this in more detail, but here is the response from Apple DTS:
In iOS 7, cells’ content views sized themselves via autoresizing masks. In iOS 8, this was changed, cells stopped using the autoresizing masks and started sizing the content view in layoutSubviews. If a nib is encoded in iOS 8 and then decode it on iOS 7, you’ll have a content view without an autoresizing mask and no other means by which to size itself. So if you ever change the frame of the cell, the content view won’t follow.
Apps being deploying back to iOS 7 will have to work around this by sizing the content view itself, adding autoresizing masks, or adding constraints.
Workaround:
- (void)awakeFromNib
{
// Fix for iOS 7 devices targeted using Xcode 6.
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
Try this code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.loginButton.frame = CGRectMake(0, 0, 200, 70);
self.loginButton.center = self.view.center;
[self.loginButton setImage:[UIImage imageNamed:#"login_fb.png"]
forState:UIControlStateNormal];
[self.view addSubview:self.loginButton];
[self.loginButton addTarget:self action:#selector(loginButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
}
And hold your DCTInitialLoginVC object with strong pointer.

UIButton target action not being called

Forgive me if this is trivial, I am still honing my programing skills. I am trying to set this button as a target. Should be easy but I dont know why it's not working! I inserted a NSLog to test and the method is not being called! Thanks for your help.
//ShareView.h
#property (strong,nonatomic) UIButton *cancelBtn;
//ShareView.m
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
UIImage *shareImage = [UIImage imageNamed:#"shareBox.png"];
[self setFrame:CGRectMake(10, 170, shareImage.size.width, shareImage.size.height)];
self.shareIV = [[UIImageView alloc] initWithImage:shareImage];
self.shareIV.userInteractionEnabled = YES;
[self addSubview:self.shareIV];
[self shareBtnsInit];
[self.shareIV addSubview:self.cancelBtn];
self.userInteractionEnabled = YES;
}
return self;
}
-(void)shareBtnsInit{
UIImage *cancelImg = [UIImage imageNamed:#"cancel27.png"];
self.cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[self.cancelBtn setImage:cancelImg forState:UIControlStateNormal];
[self.cancelBtn setFrame:CGRectMake(277, 3, cancelImg.size.width, cancelImg.size.height)];
}
//MainViewController.m
-(IBAction)settingsButtonPressed:(id)sender{
self.shareVC = [[ShareView alloc] initWithFrame:CGRectMake(0, 0, 0,0)];
[self.view addSubview: self.shareVC];
[self.shareVC.cancelBtn addTarget:self action:#selector(settingsCancel:) forControlEvents:UIControlEventTouchUpInside];
}
-(IBAction)settingsCancel:(id)sender{
NSLog(#"TEST!!!");
[self.shareVC removeFromSuperview];
}
Based on comments, your settingsButtonPressed: method wasn't being called, so the button you were looking for the action on was never being set up.
Try adding [self.cancelBtn addTarget:self action:#selector(settingsCancel:) forControlEvents:UIControlEventTouchUpInside]; to your shareBtnsInit method.
Here's more information on making UIButtons programatically: How do I create a basic UIButton programmatically?
[self.cancelBtn addTarget:MainViewController action:#selector(settingsCancel:) forControlEvents:UIControlEventTouchUpInside];
In ShareView you have to import class in which you want your event should get triggered.
Here in ShareView you can import MainViewController class and can use it.

How can I create an array of buttons in xcode?

I have a view containing 80 UIButtons, and 80 UIImages. Rather than refer to these by individual outlet references, I would like to refer to them as indexes in an array, and so be able to change the Image, and work out which UIButton is sending a message without specific references.
I am sure this must be possible, as there is no way having 80 different versions of the same code is correct way to do this!
Is this possible?
You may be better served by looking into UICollectionView, but to answer the question as asked:
- (void)viewDidLoad {
[super viewDidLoad];
self.buttonArray = [NSMutableArray array];
for (int i = 0; i < 80; i = i + 1) {
// However you wish to get your button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, i * 20, 20, 10);
[self.view addSubview:button];
// Other button-specific stuff (like setting the image, etc.)
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.buttonArray addObject:button];
}
}
- (void)buttonPressed:(UIButton *)sender {
int index = [self.buttonArray indexOfObject:sender];
// Now handle the button press based
}
It is possible, it’s called outlet collection.
#property(nonatomic,retain) IBOutletCollection NSArray *buttonsArray;

UIToolbar precise size

I'm trying to customize my NavigationBar with the help of a toolbar.
I've implemented it programmatically as follows:
UIToolbar* tools = [[UIToolbar alloc] initWithFrame: CGRectMake(0, 0, 100, 44.01)];
and then I added it to my NavigationBar. The problem is that I have this ugly effect on the borders:
I've tried to change the y and the height values, with no results.
Do you have any ideas to avoid this?
Thanks in advance, yassa
I wouldn't do it this way.
You can achieve the same effect by adding a view with 2 buttons to the navigationItem.rightBarButtonItem. it is very simple:
// view that will hold the buttons
UIView* container = [[UIView alloc] init];
// create 1 button and add it to the container
UIButton* button = [[UIButton alloc] init........];
[container addSubview:button];
//create 2 button and add it to the container
button = [[UIButton alloc] init.........];
[container addSubview:button];
// now create a Bar button item
UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:container];
// set the nav bar's right button item
self.navigationItem.rightBarButtonItem = barButtonItem;
I partially agree with previous answers and comments.
The solution you suggested works fine for custom buttons. But what if I want to implement standard Edit button?
Access to the standard buttons/icons is through the UIBarButtonItem class, not UIButton. And you can't add UIBarButtonItem objects to a UIView.
After many research on the web, I've found the solution that completely cover my requirement. The toolbar must be created in the following way:
UIToolbar *tools = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 95.0f, 44.01f)];
tools.tintColor = self.navigationController.navigationBar.tintColor;
tools.barStyle = -1;
And this is the result:
Hope it helps!
yassa
Or you can do it in this way.
Just create new subclass of UIToolbar like this
#interface MyToolbar : UIToolbar
#end
#implementation MyToolbar
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
self.clearsContextBeforeDrawing = YES;
}
return self;
}
- (void)drawRect:(CGRect)rect {
// do nothing
}
- (void)dealloc {
[super dealloc];
}
#end
And use it as normal UIToolbar. I don't know why but it just works.

Resources