IBOutletCollection (UIbutton) - objective-c

in my .h I have
IBOutlet NSMutableArray *buttons;
#property (nonatomic, retain) IBOutletCollection(UIButton) NSMutableArray *buttons;
-(void)play:(UIButton *)theButton;
in my .m I have
-(void)initButtons{
buttons = [[NSMutableArray alloc] initWithCapacity:1];
UIButton *myBut = [UIButton alloc];
[buttons addObject: myBut];
[[buttons objectAtIndex:0] addtarget:self action#selector(play:) forControlEventTouchUpInside];
}
...
-(void)dealloc{
[buttons dealloc];
[super deallloc];
}
.....
-(void)viewDidLoad{
[super viewDidLoad];
[self initButtons];
}
I dragged the buttons IBoutletCollection in interface builder to a simple button, but when I test it it doesn't perform the expected action;
I should mention that if I turn my action into (IBAction) instead of (void) and link it to the button it works;
I don't understand very well NSArrays and outlet collections.

The array is set for you with whatever buttons you've connected to the collection in the NIB. It fails to do anything because you've reset the ivar here:
buttons = [[NSMutableArray alloc] initWithCapacity:1];
…or because you've not connected buttons to the collection.

You don't need outlets to connect buttons to methods.
Get rid of all your outlet and property and initButtons code and just have this:
//in .h
-(IBAction)play:(UIButton *)theButton;
//in .m
-(IBAction)play:(UIButton *)theButton
{
//the code for your play action
}
Then in Interface Builder, ctrl-drag from the button to the File's Owner and select the play: action.

Declare your UIButton myBut as an IBOutlet with property in .h file.connect your button outlet in xib to myBut.No need to declare NSMutableArray as an IBOutletCollection or IBOutlet.You simply declare it and No need to allocate myBut again inside initButtons method.
You can do like this.
viewController.h
#property (strong, nonatomic) IBOutlet UIButton *myButton;
#property (nonatomic,strong) NSMutableArray *buttons;
-(void)initButtons;
-(void)play:(id)sender;
inSide xib connect your button outlet to myButton
viewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self initButtons];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)initButtons{
buttons = [[NSMutableArray alloc] initWithCapacity:1];
[buttons addObject: myButton];
[[buttons objectAtIndex:0] addTarget:self action:#selector(play:) forControlEvents:UIControlEventTouchUpInside];
}
-(void)play:(id)sender
{
NSLog(#"button tapped");
}

Related

How to set values of subclassed UIView properties when loading subclass from a xib

I have a subclassed UIView called BannerHeaderView, and designed the way I want it layed out in an xib. I have set the xib class to BannerHeaderView. I have a UILabel and a UIImageView which I have connected in IB.
The problem is that when I go to set the values of these subViews after initialising my BannerHeaderView in a ViewController, the label and image view are null. I have tried setting them in init also.
Code for BannerHeaderView.h:
#interface BannerHeaderView : UIView
#property (strong, nonatomic) IBOutlet UIImageView *bannerImage;
#property (strong, nonatomic) IBOutlet UILabel *headerLabel;
-(void)setTitle:(NSString *)title;
-(void)setImageFile:(PFFile *)imageFile;
#end
Code for BannerHeaderView.m:
#implementation BannerHeaderView
#synthesize headerLabel, bannerImage;
-(id)init{
self = [super init];
if (self) {
[self customInit];
}
return self;
}
-(id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
[self customInit];
}
return self;
}
-(void)customInit{
UIView *contentView = [[[NSBundle mainBundle] loadNibNamed:#"BannerHeaderView"
owner:self
options:nil] objectAtIndex:0];
[self addSubview:contentView];
contentView.frame = self.bounds;
}
-(void)setTitle:(NSString *)title{
NSLog(#"HEADER = %#", headerLabel);
headerLabel.text = title;
}
And I am creating the BannerHeaderImage in my ViewController like so:
bannerHeader = [[BannerHeaderView alloc]initWithFrame:CGRectMake(0, 0, screenWidth, bannerHeight + segmentedHeaderHeight)];
[bannerHeader setTitle:#"I AM THE NEW TITLE"];
The log tells me that the headerLabel is null.
Questions:
How do I set the values of these subviews?
Should I just design the layout of this programatically?
Thanks for your time.
P.S. I have spent hours researching this and I can't find a solution. I did find similar questions on SO but none with suitable answers to enable me to solve my problem...
Please set the class BannerHeaderView to File's Owner like this

Submenu item isn't clickable

I want a dynamically submenu. Now I tried this way:
#interface AppController()
#property(strong) Accounts * accView;
#property (weak) IBOutlet NSMenuItem *serverMenu;
#end
#implementation AppController
-(void)awakeFromNib {
_accView = [[Accounts alloc] initWithNibName:#"Accounts" bundle:nil];
[self.viewk addSubview:[_accView view]];
[[_accView view] setFrame:self.viewk.bounds];
NSMenuItem * testItem = [[NSMenuItem alloc] initWithTitle:#"Test" action:#selector(test:) keyEquivalent:#""];
[[_serverMenu submenu] addItem:testItem];
}
- (void)test:(id)test {
}
Then it get's added but I can't click on it. It's like this:
How can enable it?
You also need to assign a target to your NSMenuItem, like
[testItem setTarget:self];

How can I reuse a UIView and methods - DRY code in iOS

I have 2 methods that add the Previous, Next & Done toolbar above the iOS Keyboard and handle these actions. I'm looking for a way to code these methods once and reuse it across multiple UITableViewControllers. (DRY Code)
I find myself copy and pasting these methods into each UITableViewController. If I make a small change, I have to copy and pastes that change everywhere. The code below is just an example, I seem to be repeating myself a lot in my code.
Here's an example of the code I'd like to reuse:
- (void) createInputAccessoryView
{
_inputAccView = [[UIView alloc] initWithFrame:CGRectMake(10,0,310,42)];
UIToolbar *keyboardToolbar = [[UIToolbar alloc] init];
keyboardToolbar.barStyle = UIBarStyleBlackTranslucent;
[keyboardToolbar sizeToFit];
_segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Previous", #"Next", nil]];
[_segmentedControl setSegmentedControlStyle:UISegmentedControlStyleBar];
[_segmentedControl addTarget:self action:#selector(nextPrevious:) forControlEvents:UIControlEventValueChanged];
UIBarButtonItem *nextPrevButton = [[UIBarButtonItem alloc] initWithCustomView:_segmentedControl];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(resignKeyboard)];
NSArray *barItems = [NSArray arrayWithObjects:nextPrevButton, flexSpace, doneBtn, nil];
[keyboardToolbar setItems:barItems];
[_inputAccView addSubview:keyboardToolbar];
}
- (void) nextPrevious:(id) sender
{
switch(_activeTxtField.tag) {
case 1:
//Recipe Name
if (_segmentedControl.selectedSegmentIndex == 1){
[_descriptionTextField becomeFirstResponder];
_activeTxtField = _descriptionTextField;
}
break;
case 2:
//Recipe Description
if (_segmentedControl.selectedSegmentIndex == 0){
[_nameTextField becomeFirstResponder];
_activeTxtField = _nameTextField;
}
default:
break;
}
}
Create a custom UIView that defines the common input accessory view. Should include a definition of a delegate to allow the class using the accessory view to handle, for example, previous/next button taps as appropriate. Here's a header file example for a keyboard accessory view:
#import <UIKit/UIKit.h>
#class KeyboardAccessoryView;
#protocol KeyboardAccessoryViewDelegate <NSObject>
-(void)accessoryNext:(id)sender;
-(void)accessoryPrevious:(id)sender;
#end
#interface InputAccessoryView : UIView
#property (nonatomic, weak) id<KeyboardAccessoryViewDelegate> delegate;
#property (nonatomic, setter = enablePrevious:) BOOL previousEnabled;
#property (nonatomic, setter = enableNext:) BOOL nextEnabled;
-(id)initPreviousNextAccessory;
#end
Edit - showing details of use in a UIViewController.
The .h file:
#import <UIKit/UIKit.h>
#import "KeyboardAccessoryView.h"
#interface MyViewController : UIViewController <KeyboardAccessoryViewDelegate>
//...
#end
The .m file:
#import "MyViewController.h"
#interface MyViewController () {
KeyboardAccessoryView *inputAccessoryView;
}
#end
#implementation MyViewController
//...
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
inputAccessoryView = [[KeyboardAccessoryView alloc] initPreviousNextAccessory];
inputAccessoryView.delegate = self;
//...
}
-(void)accessoryNext:(id)sender{
// handle Next
}
-(void)accessoryPrevious:(id)sender{
// handle Previous
}
//...
#end

iOS Passing (Retain) the value of an NSMutableArray to another NSMutableArray in another view

I'm using .XIB and without ARC. I'm passing the value of the NSMultableArray to another view, if I put [self presentModel...], it works, but if I call the AnotherView with a button the value of the NSMultableArray of the AnotherView is null!
AnotherView.h
#interface AnotherViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>{
NSMutableArray *otherAnother;
NSMutableArray *arrayOfTheAnotherView;
}
#property (retain, nonatomic) IBOutlet UITableView *tableView;
#property (retain, nonatomic) NSMutableArray *arrayOfTheAnotherView;
AnotherView.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
otherAnother = [[NSMutableArray alloc]init];
otherAnother = [[NSMutableArray alloc]initWithArray:self.arrayOfTheAnotherView];
//    [otherAnother addObjectsFromArray:arrayOfTheAnotherView];
NSLog(#"%#", self.arrayOfTheAnotherView);
}
The NSLog has written "null"
CurrentView.h
#interface CurrentViewController : UIViewController {
NSMutableArray * arrayCurrentView;
AnotherViewController *superAnotherView;
}
#property (retain, nonatomic) AnotherViewController *superAnotherView;
CurrentView.m
#synthesize superAnotherView;
NSString *x = [[NSString alloc]initWithFormat:#"%#",[label text]];
arrayCurrentView = [[NSMutableArray alloc]init];
[arrayCurrentView retain];
[arrayCurrentView addObject:x];
self.superAnotherView = [[AnotherViewController alloc]initWithNibName:nil bundle:nil];
self.superAnotherView.arrayOfTheAnotherView = [[NSMutableArray alloc]init];
[self.superAnotherView.arrayOfTheAnotherView retain];
[self.superAnotherView.arrayOfTheAnotherView addObjectsFromArray:arrayCurrentView];
I don't know how to retain the value of the NSMultableArray, thanks the help.
It is how I call the AnotherView:
UIButton *buttonAnother = [UIButton buttonWithType:UIButtonTypeCustom]; [buttonAnother setTag:5]; [buttonAnother addTarget:self action:#selector(switchTabBar:) forControlEvents:UIControlEventTouchDown];
[tabBarViewController.view addSubview:buttonAnother];
- (IBAction)switchTabBar:(id)sender { switch ([(UIButton *)sender tag]) { case 5: [self.tabBarController setSelectedIndex:0]; break; }
These should not be necessary:
self.superAnotherView.arrayOfTheAnotherView = [[NSMutableArray alloc]init];
[self.superAnotherView.arrayOfTheAnotherView retain];
Properties are already initialized when the class is initialized.
In fact, your explicit retain lines shouldn't be necessary at all; you're not releasing them as far as I can see and just making the retain count 2 so that it has to be released twice.
I think there's something going on here that the methods and view controllers are not being called in the order you want, probably something to do with the tab bar.
I dicoverd! I'm using the MVC
A array of the APP delegate don't lost its value.
AppDelegate
NSMutableArray *arrayDelegate;
View.m
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
[appDelegate.arrayDelegatePedido addObject:#"title"]; //for example

Using UIButtons to create/remove/save a NSMutableDictionary to NSUserDefaults

This is so basic that hopefully it will get a response. I could not find an example to model after. I essentially want to have a NSMutableDictionary that is cleared/deleted when the view is called. Have a button add an integer and a separate button remove the integer. There is a final button to save the dictionary to NSUserDefaults and return to the previous view. Do I need to call on the dictionary in each IBAction or in the viewDidLoad to first create it and then reference it? Please advise.
example.h
#interface example : UIViewController {
NSMutableDictionary *exampleDict;
UIButton *B1;
UIButton *B2;
UIButton *Bdone
}
-(IBAction)button1;
-(IBAction)button2;
-(IBAction)done;
#property (retain,nonatomic) IBOutlet UIButton *B1;
#property (retain,nonatomic) IBOutlet UIButton *B2;
#property (retain,nonatomic) IBOutlet UIButton *Bdone;
#property (retain,nonatomic) NSMutableDictionary *exampleDict;
#end
example.m
#implementation example
#synthesize exampleDict;
#synthesize B1;
#synthesize B2;
#synthesize Bdone;
#end
-(IBAction)button1{
[exampleDict setValue:[NSNumber numberWithInt:1] forKey:#"one"];
}
-(IBAction)button2 {
[exampleDict removeObjectforKey: #"one"];
}
-(IBAction)done {
[[NSUserDefaults standardUserDefaults] setObject:exampleDict forKey:#"dictionaryKey"];
[self.parentViewController dismissModalViewControllerAnimated:YES];
}
-(void)viewDidLoad {
}
- (void)dealloc{
[B1 release];
[B2 release];
[Bdone release];
}
I don't see any initialization of the array. You should initialize it before you can message to it. You will also have to check if the value exists in the user defaults. If it exists, you should use it otherwise create it.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
exampleDict = [[[NSUserDefaults standardUserDefaults] objectForKey:#"dictionaryKey"] mutableCopy];
if ( !exampleDict ) {
exampleDict = [[NSMutableDictionary alloc] init];
}
}
In addition to this, you might want to call synchronize on the user defaults and release exampleDict in the dealloc method.