Programmatically change the state of a UIButton - objective-c

I've got a pop-up view that loads when a user clicks on a TableView with Core Data elements. On the pop-up view I have a label that represents an int value.
The pop-up view has two butons, one for decreasing the value of the label by 1 and one for increasing it by one. So + and -
What I want to do is to disable the minus button if the label's value is 0. What I've tried is:
-(void)viewDidLayoutSubviews{
NSString *daString = currentVal.text;
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * myNumber = [f numberFromString:daString];
int number = [myNumber intValue];
if (number==0)
minus.enabled = NO;
else
minus.enabled = YES
}
The problem with my code is that the button stays disabled after I increase the label's value, and it's no longer equal to 0.
Any suggestions?

You should keep a reference to minus button e.g.
#property (strong, nonatomic) IBOutlet UIButton *minusButton;
Set it with a value of your minus button, or connect outlet in Interface Builder
in your action handler for plusButton, do something like that
-(IBAction)plusAction:(id)sender {
//Do your business logic
...
self.minusButton.enabled = YES;
}
//In your minusButton action handler
-(IBAction)minusAction:(id)sender {
//Do your business logic
...
NSString *daString = currentVal.text;
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * myNumber = [f numberFromString:daString];
int number = [myNumber intValue];
if (number==0)
self.minusButton.enabled = NO;
else
self.minusButton.enabled = YES
}

It seems like you have things the other way around. I would take a totally different approach:
Keep an instance variable (which we'll call 'count') in this viewController which holds the number. it can be an NSInteger. now add a target (self) to both buttons with a #selector(buttonPressed:). now this is how this selector should look like:
- (void)buttonPressed:(id)sender{
if (sender==plusButton)
self.count++;
if (sender==minusButton)
self.count--;
label.text = [NSString stringWithFormat:#"%d",self.count];
minusButton.enabled = (self.count>0);
}

I would just do this with a UIStepper, instead of the 2 buttons. You can set properties right in your storyboard/IB file that specify the max and min, increments, and a bunch of other useful things too. There are a couple video tutorials posted on YouTube that probably cover everything you'll need to know to use it.

Also, I have noticed one thing that...
If the button in disabled state and you are trying to change the title of normal state, it wont work.
I had to change the state to enabled and then I could manipulate title and set back to disabled.

Related

Test Application by looping through a pattern of values in UITextField

I want to test my application by entering values from 1 to 10000 in a UITextField and pressing a "Go" UIButton.
And know conditions where a segue is getting performed.
How do I define the test criteria for automating testing with values 1 - 10000 being entered into the UITextField?
Another situation exactly matching my problem:
While testing a calculator application, I need to check all the possible operations and numbers. Can we do automation to test random clicks on calculator and check the output?
You can use a loop to try each value between 1 and 10000. For each value, type it into the text field, press the button and see what happens. I'm not sure what you're expecting to happen, so I have just written code which checks that a label appears - you should change this to whatever you think would assert that the correct outcome has happened.
XCUIApplication *app = [[XCUIApplication init] alloc];
XCUIElement *textField = [[app.textFields matchingIdentifier: "myTextField"] elementBoundByIndex: 0];
XCUIElement *goButton = [[app.buttons matchingIdentifier: "goButton"] elementBoundByIndex: 0];
for (NSNumber i = 1; i <= 10000; i++) {
NSString *n = [NSString stringWithFormat:#"%d", i];
[textField tap];
[textField typeText: n];
[goButton tap];
// Define what it is you expect to happen
BOOL expectedOutcome = [[app.staticTexts matchingIdentifier: "myLabel"] elementBoundByIndex: 0].exists;
XCTAssert(expectedOutcome, [NSString stringWithFormat:#"Unexpected result for %d", i])
}

(xcode objective-c) Array - finding a center of a object in an array

I'm pretty nooby when it comes to Xcode but here goes.
I have an NSArray with 5 UIImageView's, I have a script which will pick a random UIImageView, but I need it to then output the center of the image that was chosen.
My code looks like this:
NSMutableArray *Invader = [[NSMutableArray alloc] init];
[Invader addObject:H1];
[Invader addObject:H2];
[Invader addObject:H3];
[Invader addObject:H4];
[Invader addObject:H5];
Then like this to choose where to move a new UIImageView to:
if (FIRE1 == YES){
NSObject *Inv1 = [Invader randomObject]; //randomObject picks a random Invader
InvaderBullet1.hidden = NO;
InvaderBullet1.center = CGPointMake(Inv1.center.x, Inv1.center.y)
}
The error it's giving me is Property 'center' not found on object of type 'NSObject *'
I'm hoping this makes sense to anyone and that anyone can help me.
Thanks
NSObject obviously doesn't have a center property. Though you're not adding NSObjects to your array, you're adding (I assume) UIImageViews. So if you're adding UIImages, you can remove UIImages as well.
if (FIRE1 == YES){
NSObject *Inv1 = [Invader randomObject];
if ([Inv1 isKindOfClass:[UIImageView Class]]) //randomObject picks a random Invader
((UIImageView*)InvaderBullet1).hidden = NO;
((UIImageView*)InvaderBullet1).center = CGPointMake(Inv1.center.x, Inv1.center.y)
}
You simply need to specify the correct type for your variable:
if (FIRE1 == YES){
UIImageView *Inv1 = [Invader randomObject]; //randomObject picks a random Invader
InvaderBullet1.hidden = NO;
InvaderBullet1.center = CGPointMake(Inv1.center.x, Inv1.center.y)
}
This is assuming that your randomObject method (looks like a category method on NSArray) has a return type of id. If its return type is NSObject * then you need to do a cast:
UIImageView *Inv1 = (UIImageView *)[Invader randomObject]; //randomObject picks a random Invader
(Minor note: I recommend to stick to the established naming conventions. In this case: variables usually start with a lower-case character. You're doing other people that need/want to work with your code a favor.)

NSMenuItem toggle Bold Font style

I have to implement NSMenuItem such a way that selected NSMenuItem should have Bold Text , this is what i have done,
#implementation NSMenuItem (Font)
-(void)setBoldStyle:(bool)bBold{
NSString* title = [self title] ;
NSFont *pFont = (bold)?[NSFont boldSystemFontOfSize:14]:[NSFont menuFontOfSize:12];
NSDictionary* fontAttribute = [NSDictionary dictionaryWithObjectsAndKeys:
pFont, NSFontAttributeName,
nil] ;
NSMutableAttributedString* newTitle = [[NSMutableAttributedString alloc] initWithString:title
attributes:fontAttribute] ;
[self setAttributedTitle:newTitle] ;
[newTitle release] ;
}
#end
With Above peiece of code, i am able to set the bold text when a particular NSMenuItem gets selected,
but if it needs to be toggled ( Means if an item was bold earlier, it should be normal now), then its not happening,
This is the way i am calling it,
// have we selected any menuitem yet
if ( prevStatusIndex >0){
// then deselect it
pTempMenuItem = [pMenu itemAtIndex:prevStatusIndex];
[pTempMenuItem setBoldStyle:NO];
}
prevStatusIndex = clientStatus+1;
pTempMenuItem = [pMenu itemAtIndex:prevStatusIndex]; // 1 because a separator added
[pTempMenuItem setBoldStyle:YES];
Any idea whats going wrong ?
You need to use similar to this :
if ([pTempMenuItem boldStyle]) {
NSLog(#"currently bold. change it");
[pTempMenuItem setBoldStyle:NO]);
}
else{
[pTempMenuItem setBoldStyle:YES]);
NSLog(#"currenlty normal. change it");
}
We can only guess as there is a lot of information missing from your question - where are prevStatusIndex, pMenuItem, pMenu and clientStatus declared and given values? What is the valid range of clientStatus? Etc.
In the comments you've said you have used the debugger and breakpoints, but gave no indication of what values you saw.
You really need to provide more detail so folk can help you.
Provided the selected index is never 0 (i.e. prevStatusIndex is not 0 or clientStatus is not -1) and pMenu points to the correct menu then your code works. If the selected index can be zero then you need to change your test for de-bolding to prevStatusIndex >= 0 otherwise the first entry in the menu can be bolded but not unbolded.
HTH.

Xcode - Multiple values from single input

I'm trying to learn a little about Xcode, and I'm stuck on trying to get multiple values from a single input.
- (void)degreeConvert:(id)sender
{
double timelonn = [tempTextBox.text doubleValue];
double monedslonn = (timelonn * 162.5);
// double arslonn = (timelonn * 1950);
[tempTextBox resignFirstResponder];
NSString *convertResult = [[NSString alloc] initWithFormat: #"Månedslønn: %0.f", monedslonn];
// NSString *convertResult = [[NSString alloc] initWithFormat: #"Årslønn: %0.f", arslonn];
calcResult.text = convertResult;}
This takes my input 'timelonn' (hourly wage/income) and returns 'monedslonn' (monthly wage/income). The double-dashed comments is my rookie idea of how I could get it to display 'arslonn' (yearly wage/income) as well.
Am I far off here?
You're not too far off. If you uncomment your first commented line, and then change your line where you set your convertResult, you can set the convertResult string to something with multiple lines, like so:
- (void)degreeConvert:(id)sender
{
double timelonn = [tempTextBox.text doubleValue];
double monedslonn = (timelonn * 162.5);
double arslonn = (timelonn * 1950);
[tempTextBox resignFirstResponder];
NSString *convertResult = [[NSString alloc] initWithFormat: #"Månedslønn: %0.f\nÅrslønn: %0.f", monedslonn, arslonn];
calcResult.text = convertResult;
}
Note here that in the format string, "Månedslønn: %0.f\nÅrslønn: %0.f", the \n stands for a newline.
Also note that you will have to edit your .nib and change a property of your UILabel. Click on the label and change the (I'm going off Xcode 4 here) Lines property to 2 (or however many lines you wanted). On Xcode 4 it should be the second from the top in the 4-th tab of the Utilities pane (Command-Option-4). While you're at it, resize your UILabel so that it has enough space to hold your multiple lines ;)

Using a variable inside a variable objective-C

EDIT: {
No longer need help!
I used tags and a bunch of loops to reference them at anytime.
I never knew you could store so many images in one UIImageView!
}
I have an application that deals with a a lot of images and what i want to do is use an integer inside the variable name so i don't have to write code for each image. Ex:
- (void)addIconClicked {
if (icons < 28) {
icons += 1;
}
if (icons == 2) {
UIImageView * iconImage2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon1.png"]];
//modify image view like setting the frame, setting the title, etc... (not important)
}
else if (icons == 3) {
// iconImage 3 set up
}
this continues all the way up to iconImage26!
so i was wondering if i could use the integer "icons" as part of the variable name so i don't have to run the code 26 different times!!
Ex:
- (void)addIconClicked {
if (icons < 28) {
icons += 1;
}
/*some how insert the "icons" int where (icons) is. Like NSString uses
stringWithFormat ([NSString stringWithFormat:#"%i", icons])*/
UIImageView * iconImage(icons) = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"icon%i.png", icons]]];
}
-----edit----- (to clarify what i want)
my problem is that i want to make an unlimited amount of image views but if i use the same variable more than once, it would show up on the view fine, but it would be released and i can't edit it anymore.
Ex:
- (void)addIconClicked {
if (icons < 28) {
icons += 1;
}
NSString * iconName = [NSString stringWithFormat:#"icon%i.png", icons];
//if i ran this 100 times, 100 images would show up, but i can no longer edit any of them except the newest.
iconImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:iconName]];
}
so i need to know how to make an unlimited amount of images that i can still edit individually.
i thought i might be able to use the integer's value inside a variable name when i create it, but i guess i can't:(
so if anyone knows, please explain!!
so to sum it up...
my exact problem is that i want to create an unlimited number of UIImageView's using a different image each time.
You think i could just use 1 variable for all of the images (which would show up) but then i can't edit them at all because they are released.
I just need a way to create an unlimited amount of Global UIImageViews that i can edit and access at any time.
The best way to do this is with an array.
NSMutableArray* allIcons = [NSMutableArray array]; //First, you'll need this empty array.
//Then, when you create your icon...
NSString* iconName = [NSString stringWithFormat:#"icon%lx.png",icons];
UIImageView * newIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:iconName]];
[allIcons addObject:newIcon]; //This adds the icon at the next index, starting at 0.
Then, when you use your icons, instead of icon1, icon2, and so on, use [allIcons objectAtIndex:0], [allIcons objectAtIndex:1], and so on.
This is a pretty common concept--you should consider checking out a few beginning Cocoa tutorials; you might find it in use.
You can use an array for storing UIImageView references. Or you can set their tags and find them later using viewWithTag.
EDIT: Ok I am home now and I can explain:
Use tagging:
UIImageView * anImageView= [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat#"icon%i.png",icons]]];
anImageView.tag=icons;
[parentView addSubview: anImageView];
UIImageView *theOneYouWant = (UIImageView)[parentView viewWithTag:someTag];
or use a c-array of UIImageView pointers to store references if you don't mind scope:
UIImageView * imageViews[28]; // put this into class interface
imageViews[icons]= [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat#"icon%i.png",icons]]];