How can I use multiple items in one if statement? - objective-c

in this case, i'm using:
- (IBAction)reset:(id) sender {
if ((boxHide1.hidden = YES) && (boxHide2.hidden = YES)) {
resetHide.hidden = NO;
}
}
How can I do this? I have 12 items all together I need in the statement. Thanks!

You could use the solution #Joe posted but as you can tell the code for hiding / unhiding could get very messy and hard to read.
If you want to keep your code clean and easy to understand / maintain, I'd put all these buttons into a NSMutableArray and iterate through it to determine whether you want to show the reset button or not.
BOOL showResetButton = YES;
for (UIButton *button in buttonsArray)
{
if (button.hidden == NO) // If any of the buttons is not hidden do not show the reset button
showResetButton = NO;
}
resetButton.hidden = showResetButton;

Make sure you use == to compare values but since they are already booleans you do not need to compare against YES. If all the comparisons are AND(&&) that is correct and you can drop the parenthesis, otherwise if there are any OR(||) operations then you would need to group the appropriate operations.
if (boxHide1.hidden &&
boxHide2.hidden &&
... &&
boxHide12.hidden)
{
resetHide.hidden = NO;
}

Related

How do I check if there is a selection?

I have a NSTextView and I need to check if there is a selection, (blue highlight) of a word (or anything really), and not just a cursor. How can I do this. nil doesn't work, and I can't figure it out.
There can be multiple selection in an NSTextView, the methods selectedRanges returns an array of all the selections. If there is just a cursor this method returns a single NSRange with the location giving where the cursor is and the length set to zero.
So your question can be answer with:
NSArray *allSelections = myTextView.selectedRanges;
BOOL hasSelection = allSelections.count > 1
|| (allSelections.count == 1 && allSelections[0].length != 0);
HTH
You can use [NSTextView selectedRanges] method to see if there is a selection.
if (self.textView.selectedRanges.count > 0) {
NSLog(#"Some text is selected!");
}
You may want to read the documentation for more information.

How to do an on-item-changed for an NSPopUpButton?

I'm trying to implement a system that changes a label based on the state of an NSPopUpButton.
So far I've tried to do what's displayed in the code below, but whenever I run it, the code just jumps into the else clause, throwing an alert
- (IBAction)itemChanged:(id)sender {
if([typePopUp.stringValue isEqualToString: #"Price per character"]) {
_currency = [currencyField stringValue];
[additionalLabel setStringValue: _currency];
}
else if([typePopUp.stringValue isEqualToString: #"Percent saved"]) {
_currency = additionalLabel.stringValue = #"%";
}
else alert(#"Error", #"Please select a calculation type!");
}
So does anyone here know what to do to fix this?
#hamstergene is on the right track, but is comparing the title of the menu item rather than, say, the tag, which is wrong for the following reasons:
It means you cannot internationalize the app.
It introduces the possibility of spelling mistakes.
It's an inefficient comparison; comparing every character in a string takes way longer than comparing a single integer value.
Having said all that, NSPopUpButton makes it difficult to insert tags into the menu items, so you need to use the index of the selected item:
Assume you create the menu items using:
[typePopUp removeAllItems];
[typePopUp addItemsWithTitles: [NSArray arrayWithObjects: #"Choose one...", #"Price per character", #"Percent saved", nil]];
Then create an enum that matches the order of the titles in the array:
typedef enum {
ItemChooseOne,
ItemPricePerCharacter,
ItemPercentSaved
} ItemIndexes;
And then compare the selected item index, as follows:
- (IBAction)itemChanged:(id)sender {
NSInteger index = [(NSPopUpButton *)sender indexOfSelectedItem];
switch (index) {
case ItemChooseOne:
// something here
break;
case ItemPricePerCharacter:
_currency = [currencyField stringValue];
[additionalLabel setStringValue: _currency];
break;
case ItemPercentSaved:
_currency = #"%"; // See NOTE, below
additionalLabel.stringValue = #"%";
break;
default:
alert(#"Error", #"Please select a calculation type!");
}
}
NOTE the following line was incorrect in your code:
_currency = additionalLabel.stringValue = #"%";
Multiple assignment works because the result of x = y is y. This is not the case when a setter is involved. The corrected code is above.
EDIT This answer was heavily edited following more info from the OP.
To query the title of currently selected item in NSPopUpButton:
NSMenuItem* selectedItem = [typePopUp selectedItem];
NSString* selectedItemTitle = [selectedItem title];
if ([selectedItemTitle isEqualTo: ... ]) { ... }
Note that comparing UI strings is a very bad idea. A slightest change in UI will immediately break your code, and you are preventing future localization. You should assign numeric or object values to each item using -[NSMenuItem setTag:] or -[NSMenuItem setRepresentedObject:] and use them to identify items instead.

Dynamically created textfield validation

I'm trying to validate dynamically created text fields. The total number of textfields may vary.
The idea is to populate the empty fields with string like player 1, player 2 etc.. Here is what I try
-(IBAction)validateTextFields:sender
{
self.howManyPlayers = 3;
int emptyFieldCounter = 1;
NSMutableArray *playersNames = [NSMutableArray arrayWithCapacity:self.howManyPlayers];
while (self.howManyPlayers > 1)
{
self.howManyPlayers--;
UITextField *tmp = (UITextField *) [self.view viewWithTag:self.howManyPlayers];
if (tmp.text == nil)
{
[tmp setText:[NSString stringWithFormat:#"Player %d", emptyFieldCounter]];
emptyFieldCounter++;
}
[playersNames addObject:tmp.text];
}
}
The problems is that if I touch the button which invoke validateTextFields method. The first and the second textfield are populated with text Player 1 and Player 2, but the third field is not populated.
I notice also that if I type a text let's say in the second field touch the button then remove the text and again touch the button that field is not populated with text Player X.
How to make all that things to work correctly ?
change your code for two lines like this:
while (self.howManyPlayers >= 1) //edited line
{
UITextField *tmp = (UITextField *) [self.view viewWithTag:self.howManyPlayers];
if (tmp.text == nil)
{
[tmp setText:[NSString stringWithFormat:#"Player %d", emptyFieldCounter]];
emptyFieldCounter++;
}
[playersNames addObject:tmp.text];
self.howManyPlayers--; // moved line
}
I forgot ur second question, so edited my answer.
For that try with this. Change if (tmp.text == nil) with if (tmp.text == nil || [tmp.txt isEqualToString:#""])
The reason only two fields are populated is that you are only going through the while loop twice. It should be
while (self.howManyPlayers >= 1)
You should also move the decrement to the end of your while loop
while (self.howManyPlayers >= 1)
{
// other code here
self.howManyPlayers--;
}
For the second part of your question, I think when you delete the text from the control, it stops being nil and now becomes an empty string. So you need to check for an empty string as well as nil in your code.
if (tmp.text == nil || [tmp.txt isEqualToString:#""])

For loop variable always evaluating to true

Annoying newbie problem here. This variable isPlayerTouchingAnotherPlayer is being set to true as soon as I touch the piece. I'm almost positive I know why but I can't find a way to display this in log to confirm. I could probably do it by setting different flag numbers for each of the objects but I was hoping there is another way.
The problem is that piece is an object that is also located in p1Array so as soon as I touch it it hits itself and isPlayerTouchingAnotherPlayer is evaluated to true.
Is there a way I could print out the view or image name of the objects touching somehow to confirm this? And furthermore, is there a way to somehow avoid this annoying conflict.
for (int i = 0; i <[p1Array count]; i++) {
UIImageView *tempP1;
tempP1 =[p1Array objectAtIndex:i];
if (CGRectIntersectsRect(piece.frame, tempP1.frame)) {
NSLog(#"selected piece: %#, touched piece: %# ", piece, tempP1);
isPlayerTouchingAnotherPlayer = TRUE;
}
}
why not use fast enumeration and skip the image view you are not interested in checking.
for (UIImageView *imageView in p1Array) {
if (imageView == piece)
continue;
if (CGRectIntersectsRect(imageView.frame, piece.frame)) {
// do whatever
}
}
it seems like you are already printing out the names of the objects touching in the code sample you have provided. if you want to print out specific properties of the objects you can do that to.
as soon as i touch it it hits itself and isPlayerTouchingAnotherPlayer
is evaluated to true.
Then you should get a log message that shows the same object for the selected piece and the touched piece. If that's what's happening, then just add a condition to your if to prevent it:
if (piece != tempP1 && CGRectIntersectsRect(piece.frame, tempP1.frame)) {
Simply
NSLog(#"%# %#", piece, tempP1);
or
NSLog(#"%ld %ld", (NSInteger) piece, (NSInteger) tempP1);
The first will show you the description of the object, the second the address in memory, if it's same address, it's the same object.
You can simply check if it's the same object (pointer) with a simple equal check to exclude the same object :
if (piece != tempP1) {
if (CGRectIntersectsRect(piece.frame, tempP1.frame)) {
...
}
Furthermore, you would like to write this:
for ( int i = 0;
( ( i < [p1Array count] )
&& ( ! isPlayerTouchingAnotherPlayer )
);
i++
) {
...
}

NSTextField on my UI and need to access them by tag

I have 8 NSTextFields and I need to access them by UI to determine if the NSTextField has any data. If it's empty then I mark a bool as NO and check the next field. Eventually I'll highlight all the required fields and present it to the user.
Here's my pseudocode
-(BOOL)isFormValid
{
for(int i=0; i< 9; i++)
{
if <tag>.text != nil or <tag>.text != #"" then
return NO
}
return YES;
}
Probably this will help:
[superviewOfTextFields viewWithTag:tag];
Why don't you use an NSForm? As the name suggests, it's designed for text forms. You have one outlet to the form as a whole and can get each field in the form with cellAtIndex: