IBOutletCollection of UIButtons is empty after viewDidLoad - ios

As said in the title, my IBOutletCollection of UIButtons is empty after viewDidLoad.
I created a IBOutletCollection of UILabels the same way, and this one is working perfectly.
Any idea how this can be fixed, or where i made a mistake?
Here is the Code:
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *lbl_save;
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *lbl_cancel;
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *lbl_edit;
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *btn_changeData;
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *btn_save;
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *btn_cancel;
The buttons are placed in a xib and linked correctly to the corresponding outlets. Just like the labels.
The time i press the one of the Buttons is the first time, i want to access the Buttons in Code.
for (UIButton *btn in _btn_changeData) {
btn.hidden = NO;
btn.userInteractionEnabled = YES;
}
for (UIButton *btn in _btn_save) {
btn.hidden = YES;
btn.userInteractionEnabled = NO;
}
for (UIButton *btn in _btn_cancel) {
btn.hidden = YES;
btn.userInteractionEnabled = NO;
}
for (UILabel *lbl in _lbl_save) {
lbl.hidden = YES;
}
for (UILabel *lbl in _lbl_cancel) {
lbl.hidden = YES;
}
for (UILabel *lbl in _lbl_edit) {
lbl.hidden = NO;
}
That is also where i got the following Exception and realized, that my Button OUtletcollection is empty.
-[UIButton countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0xa8a8850
I neither overwrite the outletcollection, nor do i change attributes of the buttons.
Its just that the labels are there in the collection and the buttons not. And i have no idea why.
Thx in advance for any help.
Mav

First idea that comes to my mind is that the properties are not correctly synthesized. Is _btn_changeData really the ivar behind btn_changeData property?
Second idea is something I saw while debugging someone else's code. When outlets are incorrectly connected, for example, if the controller references itself, two controller instances can be create. Obviously only of of them will have the outlets connected. Make sure only of instance is created.
For debugging, implementing the setter by yourself might be a good idea.
Edit:
After rereading, the problem is actually different they you say in your question. The error message -[UIButton countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0xa8a8850
doesn't mean that _btn_changeData is an empty array. It means there is a UIButton instead of an array.
Having said this, you should check if you are not overwriting the data in _btn_changeData somewhere.

Related

IOS IBOutletCollection UITextView

I want to implement something like cardslib with text inside (Title, description, footer).
I thought to use a IBOutletCollection TextView, but I am open for other solutions.
I've linked from my xib file the collection to my interface.
In my class implementation :
#synthesize myTextViewCollection;
- (void)viewDidLoad {
myTextViewCollection = [NSMutableArray arrayWithObjects:#"one", #"two", #"three", nil];
for (UITextView *myView in myTextViewCollection) {
NSLog(#"%#", myView);
myView.text = #"any text";
}
}
myView contain the three strings : "one", "two", "three".
Output Error :
-[__NSCFConstantString setText:]: unrecognized selector sent to instance 0x461b8
I don't understand why i get this error ...
Thanks !
What are the IBOutlets for your text views? You want something like this:
#property (nonatomic, weak) IBOutlet UITextView* textViewOne;
#property (nonatomic, weak) IBOutlet UITextView* textViewTwo;
#property (nonatomic, weak) IBOutlet UITextView* textViewThree;
Then:
for (UITextView *textView in #[ self.textViewOne, self.textViewTwo, self.textViewThree ]) {
textView.text = #"any text";
}
What you have done is add a bunch of NSString literals to an array, then you're trying to send the setText: selector to an NSString, which is not a selector NSString responds to.

SetHidden not working

I am trying to show a label for some seconds when i press a button. But the hide function is not working properly.
-(void) hide_label:(NSString *)value{
[value setHidden:YES];
}
Get the error: No Visible #interface for 'NSString' declares the selector 'setHidden:'.
In your example, value is an NSString, not the UILabel. NSString's have no setHidden: method, as the error message suggests.
Instead, you will want to pass in the label itself and then call setHidden:.
So, change the method to:
- (void) hide_label:(UILabel *)label {
[label setHidden:YES];
}
And change all parts of the code that call this method to pass in the UILabel.
NSString is not a subclass of UILabel and does not respond to setHidden: you must call that on the UILabel property itself.
How do you declare your UILabel? It should be something similar to the following if you connect via a nib:
#property (nonatomic, weak) IBOutlet UILabel *label;
or if its created programatically:
#property (nonatomic, strong) UILabel *label;
You can then call setHidden on the label, as it is a property you can use dot syntax:
label.hidden = YES;
You can check its state by using its accessor:
if ([label isHidden]) {
//... do something
}
It might be worth you reading some tutorials on iOS development, Look Here on raywenderlich.com

Unrecognized selector sent to instance (UIStepper)

Okay, I know there is a ton of these questions out there, because I've looked and tried some of the solutions. However, many of the ones I tried didn't work or the answer was too over my head for me to really grasp well - I'm a new developer and this is my first app. I learn by learning what not to do at this point.
I have the 'unrecognized selector sent to instance error' on a UIStepper stepperValueChanged setup. Here is the contents of the error message as it is given to me:
[DetailViewController stepperValueChanged]: unrecognized selector sent to instance 0x8637630
I will probably be ripped apart for this, but I can't really understand what's going on here - my only guess so far is to assume it has something to do with the only point in my code where stepperValueChanged exists - under the DetailViewController.h, as placed below:
#interface DetailViewController : UIViewController <UISplitViewControllerDelegate>
{
// Create GUI parameters for text fields, text labels, and the stepper:
IBOutlet UITextField *value1;
IBOutlet UITextField *value2;
IBOutlet UITextField *value3;
IBOutlet UISwitch *double_precision;
IBOutlet UILabel *value1_type;
IBOutlet UILabel *value2_type;
IBOutlet UILabel *value3_type;
IBOutlet UILabel *deriv_units;
IBOutlet UILabel *units;
IBOutlet UILabel *result;
IBOutlet UIStepper *stepper;
}
// Define properties of the above GUI parameters:
#property (nonatomic, retain) UITextField *value1;
#property (nonatomic, retain) UITextField *value2;
#property (nonatomic, retain) UITextField *value3;
#property (nonatomic, retain) UILabel *value1_type;
#property (nonatomic, retain) UILabel *value2_type;
#property (nonatomic, retain) UILabel *value3_type;
#property (nonatomic, retain) UILabel *deriv_units;
#property (nonatomic, retain) UILabel *units;
#property (nonatomic, retain) UILabel *result;
// Setup property as instance of UIStepper:
#property (nonatomic, strong) IBOutlet UIStepper *stepper;
// Setup NSString instance for segue linking:
#property (nonatomic, strong) NSString *equationName;
#property (strong, nonatomic) id detailItem;
#property (weak, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
// IBActions for the Calculate button and UIStepper instance:
- (IBAction)Calculate:(id)sender;
- (IBAction)stepperValueChanged:(id)sender;
- (IBAction)double_precision:(id)sender;
#end
Any ideas what is going on here? I don't have much of a clue, and if anyone can help explain to me what exactly is in play here while addressing it, I would be more than grateful.
If you need the contents of the implementation file, let me know; I'll edit it in.
Relevant areas of the .m file:
#interface DetailViewController ()
#property (strong, nonatomic) UIPopoverController *masterPopoverController;
- (void)configureView;
#end
#implementation DetailViewController
// Synthesize an instance of NSString for segue linking:
#synthesize equationName = _equationName;;
// Synthesize all other variables:
#synthesize value1 = _value1;
#synthesize value2 = _value2;
#synthesize value3 = _value3;
#synthesize value1_type = _value1_type;
#synthesize value2_type = _value2_type;
#synthesize value3_type = _value3_type;
#synthesize deriv_units = _deriv_units;
#synthesize result = _result;
#synthesize units = _units;
#synthesize stepper = _stepper;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
self.title = _equationName;
self.stepper.stepValue = 1;
self.stepper.autorepeat = NO;
self.stepper.continuous = YES;
self.stepper.wraps = YES;
int eqNum;
if ((_equationName = #"Energy-Frequency Relation"))
{
eqNum = 1;
self.stepper.minimumValue = 1;
self.stepper.maximumValue = 3;
}
else if ((_equationName = #"Energy-Frequency-Wavelength Relation"))
{
eqNum = 2;
self.stepper.minimumValue = 1;
self.stepper.maximumValue = 4;
}
// Take _equationName quantization and use it in a switch case to determine the formula that IBAction will use:
if (dflt)
{
switch (eqNum)
{
case 1:
if ((stepper.value = 1))
{
// Change deriv_units appropriately:
self.deriv_units.text = #"Energy (Joules)";
// This is a Planck's constant calculation, we hide the second variable as the constant
// is stored:
self.value2.hidden = YES;
self.value2_type.hidden = YES;
self.value3.hidden = YES;
self.value3_type.hidden = YES;
// Now we set up the parameters of the first entry variable:
self.value1_type.text = #"Frequency (in Hz)";
double frequency = [value1.text doubleValue];
double Planck = 6.626069e-34;
double energy = Planck * frequency;
// Now we set up the return field to return results:
NSString* resultIntermediate = [NSString stringWithFormat:#"%f", energy];
self.units.text = #"J";
}
// Identical function statements under ViewDidLoad truncated
}
bool dflt;
-(IBAction)KeyboardGoAway:(id)sender
{
[self.value1 resignFirstResponder];
[self.value1 resignFirstResponder];
[self.value1 resignFirstResponder];
}
-(IBAction)double_precision:(id)sender
{
// Sets double-float 'truth' value depending on state of UISwitch:
if (double_precision.on)
{
dflt = TRUE;
}
else
{
dflt = FALSE;
}
}
#pragma mark - Calculation runtime
-(IBAction)Calculate:(id)sender
{
// Assigns numerical information to _equationName data -
// switch case can only handle integer literals
// Also handles stepper incrementation and UILabel/UITextView hiding
NSString* resultIntermediate;
self.result.text = resultIntermediate;
}
The trailing colon makes the difference. Your action method is stepperValueChanged:,
but from the error message it seems that you connected the stepper to stepperValueChanged.
There are two reason for these kind of issues.
Probable case 1:
You first declared the function like - (IBAction)stepperValueChanged;
Connected the IBAction to stepper
Changed the method to - (IBAction)stepperValueChanged:(id)sender;
Solution:
Delete old connection in the interface builder and connect it again.
Probable case 2:
In your code you are calling the method using a selector where you written like: #selector(stepperValueChanged)
Solution:
Change the selector like: #selector(stepperValueChanged:)
Usually this means you are missing the method in your .m or you might of misspelled stepperValueChanged.
Edit: Actually, I believe it needs to be stepperValueChanged: with a semicolon.

Objective C: Modify Label with name containing string

I want to modify a label in objective C like this:
When pushing a button named "Car" I want the label "pushedCar" to unhide.
Right now it looks like this but its static...
if ([buttonName isEqualToString:#"Car"]) {
self.pushedCar.hidden = NO;}
How can I write something like:
if ([buttonName isEqualToString:#"Car"]) {
self.pushed%#.hidden , buttonName = false;}
It's kind of a stupid example but I need it for something too complex to write down here.
Thanks in advance.
Michael
Change all your button titles like, Car, Van , Bus etc.
then make this as touch up inside method of all them,
-(IBAction) buttonPressed:(UIButton *) pressedButton{
NSString *buttonName = pressedButton.titleLabel.text;
UILabel *label = [self valueForKey:[NSString stringWithFormat:#"pushed%#", buttonName]];
label.hidden = NO;
}
like this?
if ([ButtonName isEqualToString:#"Car"]) {
self.pushedCar.hidden = !self.pushedCar.hidden;
}
use KVC
id name = nil
if(myButtonCurrentTitle isEqualTo:#"Car"]) name = #"Car";
assert(name);
UILabel *label = [self valueForKey:[NSString stringWithFormat:#"pushed%#", name]];
assert([label isKindOfClass:[UILabel class]]);
If you mean "How could I get an object that is related to a string" it would probably be simplest to put the buttons into an NSDictionary so you could do something like
MyButton *button = [buttonDict objectForKey:#"Car"];
but to be honest, your example code doesn't make much sense so I'm finding it hard to know how to write a decent example for you
If I understand it correctly, you want different buttons and labels (e.g. car, horse, cat).
In that case make an NSDictionary with the key being the buttonName (#"Car") and the the object for it the label.
You can write then something like:
UILabel *label = [myDictionary objectForKey:buttonName];
label.hidden = NO; // or label.hidden = !label.hidden;
Hope this helps!
I think you are trying to use Key Value Coding to get the button instance based on some arbitrary string.
You firstly need to expose the button instances using properties:
#interface MyClass : UIView
{
// These are connected using Interface Builder
IBOutlet UIButton *carButton;
IBOutlet UIButton *busButton;
IBOutlet UIButton *bikeButton;
}
#property (string, nonatomic, readonly) UIButton *carButton;
#property (string, nonatomic, readonly) UIButton *busButton;
#property (string, nonatomic, readonly) UIButton *bikeButton;
#end
And you can get the instance of the button using:
NSString *thing = "#car";
UIButton *button = [self valueForKey:[NSString stringWithFormat:#"%#Button", thing]];
[button setHidden:YES];

Set title of a button there is selected from an array - Xcode iOS

I have a lot of buttons that i would like to give a title when the view is loaded.
The title of the buttons varies depending on what day of the month it is. Therefore I have created an array with the name of all the buttons. My code is as follows:
My interface:
#property (strong, nonatomic) IBOutlet UIButton *button1;
#property (strong, nonatomic) IBOutlet UIButton *button2;
#property (strong, nonatomic) IBOutlet UIButton *button3;
#property (strong, nonatomic) IBOutlet UIButton *button4;
#property (strong, nonatomic) IBOutlet UIButton *button5;
#property (strong, nonatomic) IBOutlet UIButton *button6;
#property (strong, nonatomic) IBOutlet UIButton *button7;
#property (strong, nonatomic) IBOutlet UIButton *button8;
#property (strong, nonatomic) IBOutlet UIButton *button9;
#property (strong, nonatomic) IBOutlet UIButton *button10;
My implementation:
#synthesize button1 = _button1;
#synthesize button2 = _button2;
#synthesize button3 = _button3;
#synthesize button4 = _button4;
#synthesize button5 = _button5;
#synthesize button6 = _button6;
#synthesize button7 = _button7;
#synthesize button8 = _button8;
#synthesize button9 = _button9;
#synthesize button10 = _button10;
NSArray *myArray = [NSArray arrayWithObjects: #"dummyButton", #"_button1", #"_button2", #"_button3", #"_button4", #"_button5", #"_button6", #"_button7", #"_button8", #"_button9", #"_button10", nil];
for (int i = varDefinedEarlier; i<=totalAmountOfNeededTitles; i++) {
NSString *theTitleSting = [NSString stringWithFormat:#"%i",i];
NSLog(#"arrayValue:%#", [myArray objectAtIndex:i]); //Works prints the button name (for example _button7)
[[myArray objectAtIndex:i] setTitle:theTitleSting forState:UIControlStateNormal];
//The line above is where the app crashes. Everything else works just fine.
}
The error provided to me is a "Thread 1: signal SIGABRT
Besides that, this is what the log says:
-[__NSCFConstantString setTitle:forState:]: unrecognized selector sent to instance 0x14a48
2012-07-10 22:57:49.649 Don't Break the Chain[10302:707] * * * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString setTitle:forState:]: unrecognized selector sent to instance 0x14a48'
* * * First throw call stack:
(0x3774788f 0x3544c259 0x3774aa9b 0x37749915 0x376a4650 0xdc2f 0x31454c8b 0x314611e9 0x31461059 0x31460f3f 0x3146070b 0x31460503 0x31454aff 0x314547d5 0x314cd903 0x31547627 0x37fb8933 0x3771ba33 0x3771b699 0x3771a26f 0x3769d4a5 0x3769d36d 0x33e5c439 0x31449cd5 0xb7cf 0xb774)
terminate called throwing an exception(lldb)
I think the error is the way i try to tell the app witch button it needs to set a title to, but I can not really figure out how to get it to take on the value of my array and use it as the button name.
I'm pretty new in iPhone iOS development, so bear with me if the answer is simple ;)
You are not referencing the button instances but some strings within that array. Now within your loop, you are trying to invoke the method setTitle:forState: on those strings which does not exist for NSString instances.
Try the following:
NSArray *myArray = [NSArray arrayWithObjects:_button1, _button2, _button3, _button4, _button5, _button6, _button7, _button8, _button9, _button10, nil];
This will place the actual button instances into your array, as intended and your code should work fine.
you should do something like [myButton setTitle:[myArray objectAtIndex:i] forState: UIControlStateNormal]
at the moment you are passing the setTitle message to a string type which - of course - should result in a crash...
hope it helps

Resources