Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have an NSArray declared like this in my ViewDidLoad
animalz = [NSArray arrayWithObjects:#"rabbit",#"deer",#"ox", #"horse", #"cow", nil]; and I have a UIView subclass that I wrote which takes an NSString and rearranges it. The user presses a button and the number associated with the button is the number in the array that I need (Ex. if the number is three then I would need the value "horse" but if the button was 4 then I would need "cow"); Currently these numbers come in the form of long int and I can't get the corresponding value in the nsarray. I tried doing:
selectedani //this is the long int that represents the button
int indexani = [animalz objectAtIndex:selectedani];
NSString *anistr = [NSString stringWithFormat:#"%i",indexani];
[self rearrange:btistr];
This doesn't give me any compiler warnings or errors but when I press the button , the app crashes. What am I doing wrong and how can I fix it?
selectedani //this is the long int that represents the button
NSString *anistr = [animalz objectAtIndex:selectedani];
[self rearrange:anistr];
animalz is an array of NSString objects, but when you call [animalz objectAtIndex:selectedani], you assign the result to an int.
First of all, did you assigned selectedani before you used it? If not then you shouldn't use selectedani. It maybe the memory location or some other property of the button which may vary.
[animalz objectAtIndex:selectedani]
is returned an object, casting this object to an int not what you want and of course it's not an index too.
What can you do? Assign a tag number to the corresponding button dynamically, like
button.tag = 1;//or something like it
Then in the IBAction method retrieve the tag and use it to parse your array.
- (IBAction)buttonPressed:(id)sender
{
UIButton *pressedBtn = (UIButtton *)sender;
NSString *anistr = [animalz objectAtIndex:pressedBtn.tag];
//do what you want to do with the string
[self rearrange:anistr];
}
In this case, declare animalz as an iVar or property.
Related
I have a UIViewController, and in that I have an array of questions that I pull from a sqlite3 query. I am then using a for loop to iterate through each question in the array to change the UILabel.text to display the question on the screen. This is actually working for the first question in the array!
I then have four buttons for answers. I want to make it so if one of the buttons is pressed, the answer is saved and the next question in the loop updates the UILabel.text.
The four answers never change as it is more of a survey than answers, so one of the answers is "I agree" or "disagree", so the button text never changes.
Is this possible?
I have been on here and Google to find a way to link the button pressed with completing each iteration of the loop without any luck.
Why are you iterating through questions and changing UILabel's text? Shouldn't be it changed only on tapping one of the survey buttons?
If I got you correctly, you should do following:
1) Declare three properties in your controller: NSArray *questions, NSMutabelArray *answers, NSInteger currentIndex;
2) Init/alloc them in viewDidLoad (except currentIndex, of course, set it to 0).
3) Fill up questions array with your question strings.
4) Set text to UILabel, label.text = questions[currentIndex];
5) create IBAction method and link it to all survey buttons.
6) in IBAction method, insert button's title to answers array and show next question.
- (void)viewDidLoad {
[super viewDidLoad];
self.questions = {your questions array};
self.answers = [[NSMutableArray alloc] init];
self.currentIndex = 0;
}
- (IBAction)btnClicked:(id)sender {
UIButton *btn = (UIButton *)sender;
NSString *title = btn.titleLabel.text;
[self.answers addObject:title];
currentIndex++;
label.text = questions[currentIndex];
}
I hope you will understand the code.
In short, yes this is possible.
You'll first want to keep track of the question that your user is currently on. You can do this by storing an index in an instance variable or, if you plan on allowing the user to open the app and start from where they left off, you can use NSUserDefaults, which writes to disk and will persist.
// In the interface of your .m file
int questionIndex;
// In viewDidLoad of your controller, however this will start for index 0, the beginning of your questions array
questionIndex = 0
By storing the index in NSUserDefaults, you can grab it in ViewDidLoad, and start from where the user last left off:
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:questionIndex] forKey:#"questionIndex"];
To store your answer, you could add a method for your buttons called answerTapped:,
- (void)answerTapped:(UIButton *)answerButton
{
// Grab the answer from the text within the label of the button
// NOTE: This assume your button text is the answer that you want saved
NSString *answer = answerButton.titleLabel.text;
// You can use your questionIndex, to store which question this answer was for and you can then take the answer and store it in sqlite or where you prefer...
}
You can add this method to your buttons like so
[answerButton addTarget:self action:#selector(answerTapped:) forControlEvents:UIControlEventTouchUpInside];
You could then write a method to increment questionIndex now that an answer button has been pressed.
- (void)incrementQuestionIndex
{
// Increment index
questionIndex += 1;
// Update and save value in UserDefaults
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:questionIndex] forKey:#"questionIndex"];
}
You could then call a separate, final method to update the question label.
- (void)updateQuestionLabel
{
// Grab the question using the index (omit this line and go straight to the next if storing the index in an iVar)
questionIndex = [[[NSUserDefaults standardUserDefaults] objectForKey:#"questionIndex"] integerValue];
// Grab the question using the index. Assumes you have a questions array storing your questions from sqlite.
NSString *question = [questions objectAtIndex:questionIndex];
// Update the question UILabel
[questionLabel setText:question];
}
I am having a IBAction for 4 buttons which represent 4 available answers and each time I press a button I read the sender ID, then it figures out if answer is correct and so on.
Now I have a special case, when another button (nothing in common with those 4 buttons) is pressed, it waits for two of these answers, checks if one of them is correct( i know how to do that) and then the program continues running.
So for now, I have :
- (IBAction)answerButtonPressed:(id)sender {
NSString* answer= [[sender titleLabel] text];
//checks if answer key is equal to a1 ( which is always the correct answer )
if([[currentQuestionUsefulVariable valueForKey:#"a1"] isEqualToString:answer] ){
correctQuestionsCount1 ++;
}
//answer is wrong
else{
wrongQuestionsCount1 ++;
}
}
As you see I store the answer string in a variable called answer
And again - All I need is to store two answers and check the two of them when this special button is pressed. I will of course put a boolean variable to indicate when it is pressed and it will do the work.
EDIT:
The two answer thing is when I press a specific joker button and it gives the advantage to the user to chose two of four available answers. This is why I need to do that. For any other cases I need only one answer at a time.
Any ideas ?
Well you're going to need an instance variable, the value of which persists throughout the lifetime of the object, and perhaps using a mutable array of the answers is the way forward:
#interface MyViewController ()
{
NSMutableArray *_correctAnswers;
}
It must be initialised in viewDidLoad (other options are available):
-(void)viewDidLoad {
[super viewDidLoad];
_correctAnswers = [NSMutableArray new];
}
and then start collecting correct answers into this array:
- (IBAction)answerButtonPressed:(id)sender {
NSString* answer= [[sender titleLabel] text];
//checks if answer key is equal to a1 ( which is always the correct answer )
if([[currentQuestionUsefulVariable valueForKey:#"a1"] isEqualToString:answer] ){
[_correctAnswers addObject:answer];
}
//answer is wrong
else{
wrongQuestionsCount1 ++;
}
if ([_correctAnswers count] == 2) {
// Do something? It's not exactly clear what you want to do
// when 2 correct answers have been given.
}
}
Note: you can dump correctQuestionsCount1 as that will be [_correctAnswers count] now. Also you will need to reset the array at some point.
Note 2: You could also start collecting incorrect answers as well, for some analysis or perhaps to disable that button so the user cannot repeatedly answer the question wrong.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
I am quite new in iOS programming but I need it to test out a prototype.
I am receiving a value over bluetooth, which changes when a button is pressed on the physical prototype.
In my app a action has to follow when the button is pressed, therefore I need to know when the value has changed.
I have tried everything I could think of and looked everywhere but found no solution.
This is my current code:
-(void)bean:(PTDBean *)bean didUpdateScratchNumber:(NSNumber *)number withValue:(NSData *)data{
int value = *(int*)([data bytes]);
NSString *lastvalue = nil;
NSString *newValue = [NSString stringWithFormat:#"%d", value];
NSLog(#"ScratchWaarde: %d", value);
if ([newValue isEqualToString:lastvalue]) {
NSLog(#"Last Value: %#", lastvalue);
}else{
NSLog(#"Pushed");
lastvalue = newValue;
}
}
Thank you for helping!
Yeah, it looks like the OP expects lastValue to be kept as state on the object, so...
// in this class's interface
#property(strong,nonatomic) NSString *lastValue;
-(void)bean:(PTDBean *)bean didUpdateScratchNumber:(NSNumber *)number withValue:(NSData *)data{
// it looks like the OP is trying to get a string from the data, so...
NSString *newValue = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"ScratchWaarde: %d", value);
if ([newValue isEqualToString:self.lastvalue]) {
NSLog(#"Last Value: %#", self.lastvalue);
} else {
NSLog(#"Pushed");
self.lastvalue = newValue;
}
}
You code makes no sense. You are saying:
NSString *lastvalue = nil;
NSString *newValue = // ...
if ([newValue isEqualToString:lastvalue]) {
Under no circumstances will newValue ever be equal to lastValue, because lastValue is guaranteed to be nil, because that is the value you are setting it to in the first line (and newValue, because you are setting it to an actual NSString, is guaranteed not to be nil).
So, while I'm not clear on what exactly you are trying to accomplish, this obviously isn't it. It's not so much a programming matter as a matter of simple logical thought. The program can only do what you tell it to do, and what you are telling it to do is silly.
(In all probability what you are not grasping is that lastvalue is purely local to this method, so it is new every time your method is called. If you want a persistent lastvalue, you need a property global to the class, not a local variable.)
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to do something very simple, I'm trying to change a label to "I like to say hi" by clicking a button. I already know how to do it without NSString but I wanted to make it more harder, but I can't find what's wrong with this code. It's not working.
- (IBAction)button:(id)sender{
NSString *hi = #"hi";
_label.text = NSLog(#"I like to say %#", hi);
}
I'm also trying to do something even more complicated and use a void statement like this. Would this work, and if not what's wrong with it?
- (void)num{
int num = 42;
}
- (IBAction)button:(id)sender{
_label.text = NSLog(#"I like to say %i", num);
}
Why are you trying to use NSLog for this? That's for showing messages in the log.
You want NSString stringWithFormat:.
_label.text = [NSString stringWithFormat:#"I like to say %#", hi);
What you have won't even compile since the NSLog function does not return an NSString value.
NSLog is a function with a void return type, which means it does not return any value, so you can't use it to assign the value of a property. It is used only for printing messages to the debugging console or device logs. What you are probably looking for is stringWithFormat:
_label.text = [NSString stringWithFormat:#"I like to say %#", hi];
This is a method of the NSString class. It constructs strings similar to NSLog, but it actually returns a new NSString value that can be assigned to properties and so on.
Read its documentation here. You will be using this and other NSString methods all the time.
Regarding your other code:
If you want to construct a method named num that produces a value you can use elsewhere, you need to declare the type of the value it returns, instead of using void:
- (int)num{
return 42;
}
Now num is a proper instance method. You will need to tweak your code to be able to access this method correctly:
- (IBAction)button:(id)sender{
_label.text = [NSString stringWithFormat:#"I like to say %i", [self num]];
}
Here you are sending the message num to self. The keyword self is, loosely speaking, a reference to the current object instance. So [self num] will invoke the num method you have defined, and return its value. You may want to read Programming with Objective-C to learn more about these concepts.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
So I'm currently making a calorie tracker. In this app, you enter the recent meal you ate, and the amount of calories in that meal. Then you press the "add" button. This button will save the data to a TableView called HistoryTableViewController. To check if the person has left a textfield blank, I have 3 "if statement". One looks like this:
if ([[self.amountText.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] < 1)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning!" message:#"You have not entered the amount of Calories!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[amountHistory removeObjectAtIndex:0];
}
There is one line of code that I know is wrong which is the
[amountHistory removeObjectAtIndex:0];
I don't necessarily want to remove the first object on the tableview, I just want to make sure that the item doesn't get added.
Thanks in advance.
EDIT:
I add an object to the array at the top of the if statements:
total+= self.amountText.text.intValue;
self.totalLabel.text = [NSString stringWithFormat:#"%d", total];
NSNumber *calorieNumber = [NSNumber numberWithInt:self.amountText.text.intValue];
NSString *foodString = nameOfTheFood.text;
NSString *historyString = [NSString stringWithFormat:#"%# Calories in %#", calorieNumber, foodString];
[amountHistory addObject:historyString];
Sounds like you are thinking about it from the wrong angle.
Instead of adding the item to your array and then removing it if it is invalid, you should ensure the item is only added when it is valid.
So in your method you would only add the item at the end, after all validation has passed. You would add early return's in your if statements if the any validation fails so that you don't reach the code that adds the item to the array
The answer to your subject:
How to remove a specific object from an array
is
[array removeObject:obj];
Note, this uses the isEqual message on the object to determine equality. If you want specific object equality, use removeObjectIdenticalTo: instead.
Source: Apple Docs on NSMutableArray
If you are looking to remove the last item in the array use:
[amountHistory removeLastObject];
But if your issue is that you don't want to add blank items to the array why not check if they are blank before adding them?
You can only remove objects from an array if you are using NSMutableArray. Have a read of the NSMutableArray Class Reference