IBOutletCollection and initializing Custom Class Instance - objective-c

I am using the MHRotaryKnob Class and having trouble configuring it so that multiple outlets have the same default settings. It is no problem to get it working with one instance using IBOutlet, but now it is looking for the properties of the MHRotaryKnob class in NSArray.
How exactly do I define rotaryKnob in the implementation so that the settings are relayed to all controls hooked up to IBOutletCollection? The properties in the implementation are defined in MHRotaryKnob.m but now the compiler is looking for it in NSArray.
ViewController.h
#import <UIKit/UIKit.h>
#import "MHRotaryKnob.h"
#interface CBViewController : UIViewController
#property (nonatomic, retain) IBOutletCollection (MHRotaryKnob) NSArray *rotaryKnob;
ViewController.m
#import "ViewController.h"
#import "MHRotaryKnob.h"
#implementation CBViewController;
#synthesize rotaryKnob;
- (void)viewDidLoad
{
[super viewDidLoad];
rotaryKnob.interactionStyle = MHRotaryKnobInteractionStyleSliderVertical;
rotaryKnob.scalingFactor = 1.5f;
rotaryKnob.defaultValue = rotaryKnob.value;
rotaryKnob.resetsToDefault = YES;
rotaryKnob.backgroundColor = [UIColor whiteColor];
rotaryKnob.backgroundImage = [UIImage imageNamed:#"knob_passive.png"];
[rotaryKnob setKnobImage:[UIImage imageNamed:#"knob_passive.png"] forState:UIControlStateNormal];
[rotaryKnob setKnobImage:[UIImage imageNamed:#"knob_highlighted.png"] forState:UIControlStateHighlighted];
[rotaryKnob setKnobImage:[UIImage imageNamed:#"Knob Disabled.png"] forState:UIControlStateDisabled];
rotaryKnob.knobImageCenter = CGPointMake(35.0f, 32.0f);
[rotaryKnob addTarget:self action:#selector(rotaryKnobDidChange) forControlEvents:UIControlEventValueChanged];

An IBOutletCollection is a collection hence why it is backed by an NSArray in this case.
So it might help to rename the ivar to rotaryKnobs to make this fact clear and then use it like this
for (MHRotaryKnob *rotaryKnob in self.rotaryKnobs) {
rotaryKnob.interactionStyle = MHRotaryKnobInteractionStyleSliderVertical;
rotaryKnob.scalingFactor = 1.5f;
rotaryKnob.defaultValue = rotaryKnob.value;
rotaryKnob.resetsToDefault = YES;
rotaryKnob.backgroundColor = [UIColor whiteColor];
rotaryKnob.backgroundImage = [UIImage imageNamed:#"knob_passive.png"];
rotaryKnob.knobImageCenter = CGPointMake(35.0f, 32.0f);
[rotaryKnob setKnobImage:[UIImage imageNamed:#"knob_passive.png"] forState:UIControlStateNormal];
[rotaryKnob setKnobImage:[UIImage imageNamed:#"knob_highlighted.png"] forState:UIControlStateHighlighted];
[rotaryKnob setKnobImage:[UIImage imageNamed:#"Knob Disabled.png"] forState:UIControlStateDisabled];
[rotaryKnob addTarget:self action:#selector(rotaryKnobDidChange) forControlEvents:UIControlEventValueChanged];
}

Related

Constraint in UIView class crash application

I have created a UIView class:
UIViewClass.h
#import <UIKit/UIKit.h>
#interface UIViewClass : UIView
#end
UIViewClass.m
#import "UIViewClass.h"
#implementation UIViewClass
- (instancetype)initWithFrame:(CGRect)frame
{
UIButton *doneBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[doneBtn addTarget:self action:#selector(doneAction:) forControlEvents:UIControlEventTouchUpInside];
[doneBtn setTitle:#"Done" forState:UIControlStateNormal];
[doneBtn.titleLabel setFont:[UIFont fontWithName:#"AvenirNext-Bold" size:20]];
doneBtn.frame = CGRectMake(0, 0, 75, 40);
doneBtn.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:doneBtn];
[self addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"H:|-180-[doneBtn]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(doneBtn)]];
return self;
}
#end
and I call it
UIViewClass *viewClass = [[UIViewClass alloc] initWithFrame:CGRectMake(0,0,150,150)];
When I try to build it, it built with no errors but when I launch the app, the app crashes. I know that the problem is the constraint because without it, it run smoothly. Can someone tell me what is wrong?
You're not invoking the superclass. Always invoke the superclass (super) initializer first.
Further Reading:
Concepts in Objective-C Programming
Example:
self = [super initWithFrame:frame];

How to create UIButton and its #selector in a NSObject

I'm trying to generate a class that can create a UIButton and take care of what happens when you press the button in any view where the button is located. Here is what I'm doing:
Header File:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface CreateButton : NSObject
- (UIButton *)createButton;
#end
Implementation:
#import "CreateButton.h"
#implementation CreateButton
- (UIButton *)createButton
{
// Instanciate the class
CreateButton *classInstance = [[CreateButton alloc] init];
UIButton *testButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 50.0, 50.0)];
[testButton setBackgroundColor:[UIColor redColor]];
[testButton addTarget:classInstance action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
return testButton;
}
- (void)buttonClicked:(UIButton *)sender
{
NSLog(#"Clicked");
}
#end
And finally, in the a view controller, I initialize the class and get the button:
CreateButton *create = [[CreateButton alloc] init];
UIButton *testButton = [create createButton];
[self.view addSubview:testButton];
Now everything is ok up to this point and I can see the button, however, nothing happens when I click it. Surprisingly, if I move the buttonClicked: method to my view controller it works just fine. I need to keep all the button wiring inside the NSObject. Any help would be greatly appreciated.
Ok, I solved the problem, interesting.
Implementation file will be modified as:
- (UIButton *)createButton
{
UIButton *testButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 50.0, 50.0)];
[testButton setBackgroundColor:[UIColor redColor]];
[testButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
return testButton;
}
Then, in the view controller, CreateButton class must be pre-defined in the header file #interface section. Then in the implementation:
create = [[CreateButton alloc] init];
and it works! That would be great if you kindly explains this to me.

Program a UIButton to change UILabel

I am trying to use Objective-C in iOS Single View app to program a UIButton to change the text in a UILabel. Is there a way to run a function for this to be implemented in my "ViewController.m" file?
Here is my Source Code:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)loadView {
//UIBUTTON
//allocate the view
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
//set the view's background color
self.view.backgroundColor = [UIColor whiteColor];
//create the button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//set the position of the button
button.frame = CGRectMake(50, 280, 280, 50);
//set the font size of the button
button.titleLabel.font = [UIFont systemFontOfSize:40];
//set the text color of the button, before it is pressed
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
//set the text color of the button, while it is pressed
[button setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
//set the button's title
[button setTitle:#"3" forState:UIControlStateNormal];
//listen for clicks
[button addTarget:self action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchUpInside];
//add the button to the view
[self.view addSubview:button];
//UILABEL
UILabel *Question=[ [UILabel alloc] initWithFrame:CGRectMake(10,200,350,60)];
Question.text=#"How many horns does a Triceratops have?";
Question.backgroundColor = [UIColor grayColor];
Question.textColor = [UIColor whiteColor];
Question.font=[UIFont fontWithName:#"Helvetica" size:18 ];
[self.view addSubview:Question];
}
-(void)buttonPressed { }
#end
Is it possible to trigger the change in text in my buttonPressed function? Thanks so much for anybody's help!
The problem is that when you create your label and add it to the interface...
UILabel *Question=[ [UILabel alloc] initWithFrame:CGRectMake(10,200,350,60)];
// ...
[self.view addSubview:Question];
...you didn't keep a reference to it. So now, in buttonPressed, you have no way to talk about the label.
Make a property:
#interface ViewController ()
#property (nonatomic, weak) UILabel* questionLabel;
#end
... and when you create the label, remember to set that property to that label. Now you will be able to access the text of that label later on, in buttonPressed (or anywhere else), through the property.

Custom UIButton not capturing touches after adding subview

I've got a UIButton declared in interface builder with an outlet set as follows:
#property (weak, nonatomic) IBOutlet UIButton *loginButton;
It works fine until I insert a subview. Then it stops responding. Here's the offending line:
[self.loginButton insertSubview:_gradientButtonView atIndex:0];
Commenting that out makes the button work again. Here's all the code involved (using the awesome SSToolkit and a custom category on UIColor):
SSGradientView *_gradientButtonView = [[SSGradientView alloc] initWithFrame:self.loginButton.layer.bounds];
_gradientButtonView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
_gradientButtonView.topBorderColor = [UIColor colorWithRed:0.558f green:0.599f blue:0.643f alpha:1.0f];
_gradientButtonView.topInsetColor = [UIColor colorWithWhite:1.0f alpha:0.3f];
_gradientButtonView.colors = [NSArray arrayWithObjects:[UIColor from_hex:#"E6E7E8"], [UIColor from_hex:#"A7A9AC"], nil];
_gradientButtonView.layer.cornerRadius = 5;
self.loginButton.layer.cornerRadius = 5;
self.loginButton.titleLabel.shadowOffset = CGSizeMake(0, 1);
[self.loginButton setTitleShadowColor:[UIColor whiteColor] forState:UIControlStateNormal];
self.loginButton.layer.masksToBounds = YES;
_gradientView.bottomBorderColor = [UIColor colorWithRed:0.428f green:0.479f blue:0.520f alpha:1.0f];
_gradientButtonView.clipsToBounds = YES;
_gradientButtonView.userInteractionEnabled = YES;
[self.loginButton insertSubview:_gradientButtonView atIndex:0];
self.loginButton.userInteractionEnabled = YES;
This was answered in the comments above:
Is there a specific reason you're writing
_gradientButtonView.userInteractionEnabled = YES;? To my knowledge, this prevents the view from sending touch events up the responder
chain

customize uibarbuttonitem without uiappearance

Is there a way to customize ALL uibarbuttonitems to have a background image without using UIApperance? Unfortunately our codebase has some limitations and we're not able to use UIAppearance so I'm looking for an alternative.
Thanks in advance.
Edit: I was able to do this by subclassing UIBarButtonItem and it works for most of my buttons...but I'm wondering specifically how to do it with default buttons like UITableView edit buttons and UINavigationController backbuttons.
Thanks!
You also can make subclass like this. First i go to make subclass of UIBarButtonItem. My CustomBarButtonItem.h should be like this.
#interface CustomBarButtonItem : UIBarButtonItem
+ (CustomBarButtonItem *)sharedInstance;
- (UIBarButtonItem *)backButtonwithTarget:(id)target andAction:(SEL)action;
#end
then inside my CustomBarButtonItem.m should like this.
#implementation CustomBarButtonItem
static CustomBarButtonItem * _sharedInstance = nil;
+ (CustomBarButtonItem *)sharedInstance
{
if (_sharedInstance != nil)
{
return _sharedInstance;
}
_sharedInstance = [[CustomBarButtonItem alloc] init];
return _sharedInstance;
}
- (UIBarButtonItem *)backButtonwithTarget:(id)target andAction:(SEL)action
{
UIImage *backImage = [UIImage imageNamed:#"back_btn_normal.png"];
UIImage *backPressed = [UIImage imageNamed:#"back_btn_hilight.png"];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[backButton setBackgroundImage:backImage forState:UIControlStateNormal];
[backButton setBackgroundImage:backPressed forState:UIControlStateHighlighted];
const CGFloat BarButtonOffset = 5.0f;
[backButton setFrame:CGRectMake(BarButtonOffset, 0, backImage.size.width, backImage.size.height)];
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, backImage.size.width, backImage.size.height)];
[containerView addSubview:backButton];
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:containerView];
return item;
}
#end
Then where ever you want to make custom NavigationItem (Button in the NavigationBar) you can put the code below for me it custom.
- (void)viewDidLoad
{
self.navigationItem.leftBarButtonItem = [[CustomBarButtonItem sharedInstance] backButtonwithTarget:self andAction:#selector(searchButtonTapped:)];
}
All of my code are working fine. Hopefully it will help you.
you can do something like this. just copied it out of my project.
_leftBarButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:[self imageButton]]
style:UIBarButtonItemStyleBordered
target:self
action:#selector(showLeftViewController)];
[navController.navigationBar.topItem setLeftBarButtonItem:_leftBarButton];
To do this: create category on UINavigationBar and override method drawRect
#implementation UINavigationBar (CustomBackground)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"background"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
This code allows you to change background for all UINavigationBar in a project.