Dynamic button selection - objective-c

Suppose I have two buttons that are ivar outlets. One is called "Blue" and the other "Red." Now, I have an NSString with the value of "Red." I want to set the button identified by the NSString to a selected state, without using if.
I do not want to do this:
NSString *button=#"Red";
if ([button isEqualtoString:#"Blue")
self.blue.selected=YES; //self.blue and self.red are UIButtons
else
self.red.selected=YES;
This is fine if you have two buttons, but I have quite a lot more than that, and it would be quite inelegant and cumbersome to do this for like 30 buttons.
I'd much rather find a way to directly link the name of a UIButton ivar to the value of an NSString.

Put the string lower case and
you can use KVC for that :
[self setValue:[NSNumber numberWithBool:YES]
forKeyPath:[NSString stringWithFormat:#"%#.selected", button]];

You can put the buttons in a dictionary :
[NSDictionaryName addObject: UIButtonName forKey: #"blue"];
or something like that :
[NSDictionaryName objectForKey:#"blue"].selected = YES;

Related

NSTextField Autocomplete / Suggestions

Since some days I am trying to code an autocompletion for a NSTextField. The autocompletion should look that way, that when the user clicks on the NSTextfield a list should be displayed under the TextField which possibilities are available. After typing one letter or number the list should refresh with the possibilities.
The suggestions in this list should come from an NSMutableArrayor a NSMutableDictionary
This autocomplete / autosuggestion method should be for a MAC application.
Just adding to #AbcdEfg's answer, to make NSComboBox case-insensitive, you can subclass it and override it's [completedString:] method like this:
- (NSString *) completedString:(NSString *)string {
NSUInteger l = [string length];
if (!!l)
for (NSString *match in [self objectValues])
if ([[match commonPrefixWithString:string options:NSCaseInsensitiveSearch] length] == l)
return [match stringByReplacingCharactersInRange:NSMakeRange(0, l) withString:string];
return nil;
}
You can use NSComboBox for that matter. You also need to set its Autocompletes attribute in IB or [comboBox setCompletes:YES] in code.
Keep in mind that it is case-sensitive.
However if you need it to be done in the exact way that you described, you need to make the list by subclassing NSWindowController and NSTableView and change them to look like a list or menu to show under you NSTextField. Set the NSTextField's delegate and do the search and list update on text changes.
Avoid the NSMenu in this case as it will take away the focus from the text field while you are typing.
Apple addressed it in WWDC 2010 Session 145.
They explained about a text field with suggestions menu and how to get it to work. They also provide the sample codes in their website.
You can find the sample code here.

Use BOOL as property of button

I have a boolean that I would like to set as a property of a button:
int tag = (int)[sender tag];
NSString* keyPath = [NSString stringWithFormat:#"addButton%d.hidden", tag];
[self setValue:YES forKey:keyPath];
I can't do this directly as the addButton's number changes according to the sender's tag.
I've already tried with:
setValue:[NSNumber numberWithBool:YES]
but doesn't work.
Where am I wrong?
This whole problem is based on bad architecture. Having properties addButton1, addButton2, addButton3 etc. is hard to work with in the first place. Every time you see yourself adding numbers at the end of your properties, use an array instead.
NSArray *addButtons = #[self.addButton1, self.addButton2, self.addButton3];
and then simply
[addButtons[sender.tag - 1] setHidden:YES];
Using KVC is good only for specific situations. If you are a beginner, try to not use it. It's a bad habit to overuse it. Access properties directly, not using string names.
It's probably setValue:forKeyPath:, the value must be an object
[self setValue:#(YES) forKeyPath:keyPath];

How to get current index of UIBarButtonItem to remove it by clicking event?

I'm in the process of learning Objective-C and iOS development. So, I implemented removing of UIBarButtonItem from UIToolBar on UIControlEventTouchDown event in the selector. But this works really bad and the code is not very declarative as you see:
- (void)barButtonClicked:(id)sender
{
NSArray * const itemsArray = userToolbar.items;
NSMutableArray * mutableItems = [NSMutableArray arrayWithArray:itemsArray];
[mutableItems removeObjectAtIndex:0];
[userToolbar setItems: mutableItems animated:YES];
}
So as you see I removed item accordingly to its index in the userToolbar items array. It's not what I really want. I have on my UIToolBar nearly 10-12 UIBarItemButtons and I want define one common event for them all: removing it from the bar by clicking on it. So I need something like this: [mutableItems removeObjectAtIndex:sender.currentIndexInToolBarItemsArray] So, the question how can I implement this?
Instead of removing the object at the constant index 0, use the removeObject: method of NSMutableArray:
[mutableItems removeObject:sender];

arraycontroller nsmutablearray add programmatically

I trying to add a data on table view via Array Controller thats bind to a NSMutableArray.
On the IB property it looks like this :
and on the code I tried to add the NSMutableArray dynamically then reload the view, bu nothings happened.
for(int i=0;i<10;i++){
NSMutableDictionary *group = [[NSMutableDictionary alloc]init];
[group setValue:[NSString stringWithFormat:#"%#-%d", #"Group", i] forKey:#"groupname"];
[contentArray addObject:group];
}
[tableContent reloadData];
I have been google it and browse the same question in stackoverflow, not found a useful one.
any idea ?
Thanks
updated
I wrote above code in File's owner class.
I think the problem is that the array needs to send a KVO notification to the array controller (or maybe it's the table view, I'm not sure). The way to do that is:
self.contentArray = contentArray; (or _contentArray if that's what your ivar is called). I'm assuming that contentArray is a property, if not, you should make it one.

comparing 2 UIButtons

I have an array full of buttons and when a use clicks one I would like to search the array for it.
Yes, I have given the buttons tags, but they are used for another purpose. So I am hoping that there is another way to check for equality.
I was hoping that I would be able to do something like button1.frame.origin == button2.frame.origin, but the compiler doesnt like that.
You can use the method bool CGRectEqualToRect(CGRect rect1, CGRect rect2). Just pass in both of the button's frames as parameters into this method and it'll return a bool stating whether they are equal.
UIButton (and UIView) inherits from NSObject so you should just be able to do isEqual.
if([button1 isEqual:button2])
{
// do whatever
}
you can compare memory addressed of those objects, same as isEqual method is using
NSArray *buttons=#[button1,button2,button3,button4];//your array of buttons
UIButton *b = (UIButton *)sender;//button to search
[buttons enumerateObjectsUsingBlock:^(UIButton * button, NSUInteger idx, BOOL *stop) {
if (button==b) {
//do your thing here...
*stop=TRUE;
}
}];