so I'm creating a contact list app and I'm storing everything into an NSMutableArray. I've managed to get add function working perfectly. But I'm struggling with the Previous/Next functions.
I can get it to go back one object in the array when pressing previous, but i Can't get it to go back any further? here's my code: I have two extra classes, PhoneBookEntry which is a subclass of the Person class. These classes contain three strings, Firstname,lastname and studentID
- (IBAction)addPerson:(id)sender {
PhonebookEntry *person = [[PhonebookEntry alloc] init];
NSLog(#"%#",self.firstName.text);
person.firstName = self.firstName.text;
person.lastName = self.lastName.text;
person.phoneNumber = self.phoneNumber.text;
[self.entries addObject:person];
Here's my Previous button:
int length;
length = [self.entries count];
if (length > 0) {
int index;
index = [self.entries count] - 1;
NSLog (#"%d the index is", index);
NSLog(#"object %#", [self.entries objectAtIndex:index]);
} else {
NSLog (#"No contacts have been entered. No");
}
//NSLog(#"%d is the length - 1 hopefully", length);
//NSLog (#"index at %d is ", length);
I've tried removing the - 1 here:
index = [self.entries count] - 1;
and changing then on the next line putting index--; but nothing seems to work. it just goes back once.
I understand that length is getting the amount of objects in the index, and then -1 but shouldnt i-- at the end of the count / - 1 keep removing it everytime its pressed??
Any ideas? Cheers
You're going to keep hitting the same index with that piece of code - you need to store the state somewhere. Who is going to hold onto what the current index is? With a good designed system the model should really take care of this.
You are best off storing the current index into an ivar and updating that every time the button is pressed.
#interface OKAClass ()
#property (nonatomic, assign) NSInteger currentIndex;
#end
//... initialise the property with a default value
self.currentIndex = [self.entries count] - 1;
//... when the button is pressed decrement the index (you might want some min / max validation or use modulus to loop over and start from the top again)
NSLog(#"%#", self.entries[self.currentIndex--]);
Related
I am using buttons and I assigned tag 0 to 10 . Then I made an action to get the clicked button's tag, and now I want to display the tag in a label . Also I have a cancel button C. If user wants to delete any number, he can click C button that I want to remove number from the label .
This is my screenshot to touch the number
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Ezywire";
addnum=[[NSMutableArray alloc]init];
numbber=[[NSString alloc]init];
}
- (IBAction)NumberAction:(id)sender {
NSInteger tagvalue = [sender tag];
NSString *current=[NSString stringWithFormat:#"%ld", (long)tagvalue];
[addnum addObject:current];
NSString *temp;
for ( int i=0; i<[addnum count]; i++) {
numbber=[numbber stringByAppendingString:[addnum objectAtIndex:i]];
}
NSLog(#"data===%#",numbber);
ValueLable.text= numbber;
}
But in the label I am getting repeated number like this. How to implement this.
For example if user enters 2 then in the label
2
then he enters 7 then in the label
27
then he entered 9 then in the label
279
........ like this .
If user clicks C, then it remove from label last value is (last value removed)
27
The problem in your code is that numbber is initialized when the view is loaded, and never gets cleared again. However, each time a button is pressed, the whole addnum of digits gets appended to num again, creating repeated digits.
Fix this by removing num as an instance variable, making it a local to NumberAction: method, and setting it to an empty string every time the number is pressed.
Since you are planning to support the clearing action as well, you should make a private method that combines the digits from addnum array into a string. This way your NumberAction: and ClearAction would share the code that formats the array and sets the label. Your NumberAction: method would append a number and call FormatAndSetLabel, while the ClearAction method would remove the last digit if it is available, and call FormatAndSetLabel as well:
- (IBAction)NumberAction:(id)sender {
NSInteger tagvalue = [sender tag];
NSString *current=[NSString stringWithFormat:#"%ld", (long)tagvalue];
[addnum addObject:current];
[self FormatAndSetLabel];
}
- (IBAction)ClearAction:(id)sender {
if (!addnum.count) return;
[addnum removeLastObject];
[self FormatAndSetLabel];
}
-(void)FormatAndSetLabel {
NSMutableString *temp = [NSMutableString string];
for ( int i=0; i<[addnum count]; i++) {
[temp appendString:addnum[i]];
}
ValueLable.text= temp;
}
Also it might be interesting for you to have a look at Paul's Hegarty Stanford iOS development course (iPad and iPhone Application Development, Fall 2011)
https://itunes.apple.com/ru/itunes-u/ipad-iphone-application-development/id473757255?mt=10
Calculator app is used here as an example. Must see for the beginners.
I am working on a picker view with 3 columns. I want to determine the 3rd column value from the second column. Here is part of my code
- (void)viewDidLoad {
[super viewDidLoad];
Number=#[#"Trans",#"1st",#"2nd",#"3rd",#"4th",#"5th",#"6th",#"7th",#"8th",#"9th",#"10th",#"11th",#"12th"];
Season=#[#"Spring",#"Summer",#"Fall"];
Course=#[#"CHEM1100 General Chem I",#"CHEM2100 General Chem II",#"CHEM3511 Org Chem",#"CHEM3521 Org Chem II"];
// Course=#[#"Summer1",#"Summer2",#"Summer3"];
Course = [Course sortedArrayUsingSelector:#selector(compare:)];
Number =[Number sortedArrayUsingSelector:#selector(compare:)];
Season =[Season sortedArrayUsingSelector:#selector(compare:)];
}
Here is my question, how can I achieve the goal like
if (Season==#"Spring")
Course= #[#"CHEM1100 General Chem I",#"CHEM2100 General Chem II",#"CHEM3511 Org Chem",#"CHEM3521 Org Chem II"];
else if (Season==#"Summer")
Course=#[#"Summer1",#"Summer2",#"Summer3"];
Sorry, I don't know what method to use to complete the code. Any idea please?
To show the column value, I use the following code:
- (IBAction)addCourse:(UIButton *)sender {
NSInteger numRow=[picker selectedRowInComponent:kNumComponent];//0=1st,1=2nd,etc
NSInteger SeaRow=[picker selectedRowInComponent:kSeaComponent];//0=fall,1=spring,2=summer
NSInteger CourseRow=[picker selectedRowInComponent:kCourseComponent];
NSString *num=Number[numRow];
NSString *season=Season[SeaRow];
NSString *course=Course[CourseRow];
NSString *msg=[[NSString alloc ]initWithFormat:#"%# ",course];
_courseLabel.text=[msg substringToIndex:8];
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
if (component==kNumComponent)
return [Number count];
else if(component==kSeaComponent)
return [Season count];
else return [Course count];
}
According to the documentation, you must provide your UIPickerView with a datasource and a delegate. The datasource tells the view how many components and rows there are, while the delegate tells it the content of the components row. Let us suppose that you implement titleForRow: in your delegate. Since this is going to change based on a selection, you will need to do two things: (i) make sure your delegate object knows which selection was made (e.g. #"Spring") and (ii) you will then need to call the UIPickerView reloadComponent: method so that your delegate's titleForRow: method will be called.
Example: suppose your action method is componentSelected:
-(void)componentSelected:(id)sender
{
NSInteger row = [myPicker selectedRowInComponent:seasonComponent];
myDelegate.season = row;
[myPicker reloadComponent:courseComponent];
}
By the way, it is worth getting into the habit of being very careful with "=", "==", isEqualToString: etc. to avoid bugs. Your question has several basic syntactical errors. The line
if(season = #"spring")
should be
if([season isEqualToString:#"spring"]);
not just because "=" is assignment, but because "==" makes no sense if one of the arguments is a literal (it is essentially pointer comparison). isEqualToString will compare the target string with the argument string.
I'm new to objective-c and have already released the first version of my app in the App Store but I want to improve my app because in the current version, I can only enter 4 player names.
In my new iOS app, I have a table view that lists all names that a user can enter in another view controller.
When the user presses play, I want to display a UIAlertView with the name of a random person.
at this moment, I would like to display all names in the NSLog, but I can't figure out how to do that. with my current code, the app keeps crashing.
I have a class, Zoep, which is a subclass of NSObject. and has the following properties:
#property (strong, nonatomic) NSString *playername;
#property BOOL *checked;
In the tableview controller, I have the following code to display items in the NSMutableArray and to display all names in NSLog. I think i'm that i'm almost doing it right now:
- (IBAction)play:(id)sender {
NSString *aantal = [NSString stringWithFormat: #"%ld", (long)[self.zoepers count]];
NSLog(#"array count: %#", aantal);
for (int i = 0; i < 2; ++i) {
NSLog(#"Naam: %lu", (unsigned long)[self.zoepers indexOfObject:[i]]);
}
}
with the above code, i'm still getting the following error and can't compile:
Expected identifier
Could someone point me in the right direction? When you have any tips for me, I would also like to know them.
Thanks a lot in advance!
NSString is an object and can be print with %# and not %lu. Update your code and you're with your name.
for (int i = 0; i < 2; ++i) {
Zoep *player = (Zoep *)[self.zoepers objectAtIndex:i];
NSLog(#"Naam: %#", player. playername);
}
Conclusion: You're storing Zoep class object into your zoepers array, so at the time of accessing zoepers you would first make reference of Zoep class object and then can access properties of that class.
BTW, indexOfObject: takes an object and will return index (position in array).
Change ur code as below..
indexOfObject refers to Object of type id..Actually u are passing int instead of object..
U can get the value of some property of object using (.) like obj.propertyname..
for (int i = 0; i < 2; ++i)
{
Zoep *zoepObj=[self.zoepers objectAtIndex:i];
NSLog(#"Naam: %#",zoepObj.playename);
}
Hope it helps u..
so I'm creating a contact list app and I'm storing everything into an NSMutableArray. I've managed to get add function working perfectly. But I'm struggling with the Previous/Next functions.
I can get it to go back one object in the array when pressing previous, but i Can't get it to go back any further? here's my code: I have two extra classes, PhoneBookEntry which is a subclass of the Person class. These classes contain three strings, Firstname,lastname and studentID
- (IBAction)addPerson:(id)sender {
PhonebookEntry *person = [[PhonebookEntry alloc] init];
NSLog(#"%#",self.firstName.text);
self.currentIndex++;
person.firstName = self.firstName.text;
person.lastName = self.lastName.text;
person.phoneNumber = self.phoneNumber.text;
[self.entries addObject:person];
NSLog(#"%#", self.entries);
[self arrayLength ];
I've created a property to hold the current index.
#property (nonatomic, assign) NSInteger currentIndex;
I've created a method which then -1 from the currentINdex;
self.currentIndex = [self.entries count] - 1;
heres my button previous.
- (IBAction)btnPrevious:(id)sender {
//[self prevObject];
int length;
length = [self.entries count];
if (length > 0) {
NSLog(#"%#", self.entries[self.currentIndex--]);
// NSLog(#"object %#", [self.entries objectAtIndex:index]);
}
else {
NSLog (#"No contacts have been entered. No");
}
I can get it to go back once, but when I press it a second time Iget the following error.
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 2 beyond bounds [0 .. 1]'
Theres definitely data in there as I get it to print whats in the array, it also prints when I press previous also. happens no matter how many times I press the add button.
thanks
Better:
Previous Index:
// in order to go back you need to make sure that you're not already
// on index 0 and that you've items to go back to
if([self.entries count] > 1 && self.currentIndex > 0) {
self.currentIndex--;
}
Next Index:
// in order to go forward you need to make sure that you're not already
// on the last element
if(self.currentIndex < ([self.entries count] - 1)) {
self.currentIndex++;
}
Some further explanation on the root cause of your problem:
The main problem is, that you use currentIndex--. This will use the old currentIndex (which is 2) before decreasing the value. If you want to use the decreased value in this statement, you have to apply the decreasing before, i.e. by writing --currentIndex instead.
--expression = pre-decrement operator
expression-- = post-decrement operator
The pre-decrement operator does decrease the value and return the decreased value while the post-decrement operator will decrease the value by 1 and return the initial value.
i think you are starting from end of list
self.currentIndex = [self.entries count] - 1;
if current index is # 1 and you have 2 items in array adding an other will give you error
try this
NSLog(#"%#", self.entries[self.currentIndex--]);
For Previous
- (IBAction)btnPrevious:(id)sender
{
if(self.currentIndex <= 0)
{
self.currentIndex = [self.entries count] - 1;
NSLog(#"%#", self.entries[self.currentIndex])
}
else
{
self.currentIndex --;
NSLog(#"%#", self.entries[self.currentIndex])
}
}
For Next
- (IBAction)btnNext:(id)sender
{
if(self.currentIndex >= [self.entries count] - 1)
{
self.currentIndex = 0;
NSLog(#"%#", self.entries[self.currentIndex])
}
else
{
self.currentIndex ++;
NSLog(#"%#", self.entries[self.currentIndex])
}
}
Hope this will working for you.
I have a NSMutableArray of N Integer elements (N>4), I want to get 3 different random elements from this array. I do not really need a perfectly-uniform distribution, just 3 different random elements should be OK. Do you have any suggestion? Thanks
Make NSIndexSet, and keep adding
int value = arc4random() % array.count;
items to it until its size gets to 3. The you know that you have your three indexes.
NSMutableIndexSet *picks = [NSMutableIndexSet indexSet];
do {
[picks addIndex:arc4random() % array.count];
} while (picks.count != 3);
[picks enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
NSLog(#"Element at index %ud: %#", idx, [array elementAt:idx]);
}];
for (int i = 1; i <= 3; i++) {
int index = (int)(arc4random() % [array count]);
id object = [array objectAtIndex:index];
[array removeObjectAtIndex:index];
}
arc4random() returns a random number in the range [0,2^32-1). The remainder when you take the modulus with the size of the array gets you a value between [0,arrayCountLessOne].
If you don't want to change your original data array, you can just make a copy of the array.
If you want to do this more than once from various places in your code then consider doing this: The "Objective C way" is to create a category on NSMutableArray which adds a method randomObjects. The method itself should generate three random integers from 0 to the length of the array -1 (N-1), then return a set of objects from the array at those indices, as per the other answers here (dasblinkenlight's in particular.)
First, create the category. Create a new header file NSMutableArray+RandomObject.h, containing:
#interface NSMutableArray (RandomObjects)
- (NSSet *) randomObjects;
#end
The RandomElement in parentheses is the name of your category. Any class you write that includes this new header file will give all your NSMutableArray instances the randomElement method.
Then the implementation, in NSMutableArray+RandomObjects.m:
#implementation NSMutableArray (RandomObjects)
- (NSSet *) randomObjects {
// Use the code from #dasblinkenlight's answer here, adding the following line:
return picks;
}
#end
And that's basically it. You've effectively added that capability to NSMutableArray.
Nice answer from dasblinkenlight!
In Swift 4:
let indexes = NSMutableIndexSet()
if array.count > setSize {
repeat {
indexes.add(Int(arc4random_uniform(UInt32(array.count))))
} while (indexes.count < setSize)
}