Get the number of rows of a static table view - objective-c

I have a static table view, created using a storyboard. I want to get its number of rows in code. How can I do that?

The best I know about is:
NSInteger rows = 0;
for (NSInteger i = 0; i < [myTable numberOfSections]; ++i)
{
rows += [myTable numberOfRowsInSection:i];
}

Related

UIButton with random text/value or tag [duplicate]

This question already has answers here:
iOS: How do I generate 8 unique random integers?
(6 answers)
Closed 9 years ago.
I have 10 UIButtons created in historyboard, OK?
I want to add random numbers that do not repeat these numbers, ie, numbers from 0 to 9 that interspersed whenever the View is loaded.
I tried to find on Google and here a way to use my existing buttons ( 10 UIButton ), and just apply them to random values​​. Most ways found ( arc4random() % 10 ), repeat the numbers.
Here's one
here's another
here's another
All results found that creating buttons dynamically. Anyone been through this?
Create an array of the numbers. Then perform a set of random swapping of elements in the array. You now have your unique numbers in random order.
- (NSArray *)generateRandomNumbers:(NSUInteger)count {
NSMutableArray *res = [NSMutableArray arrayWithCapacity:count];
// Populate with the numbers 1 .. count (never use a tag of 0)
for (NSUInteger i = 1; i <= count; i++) {
[res addObject:#(i)];
}
// Shuffle the values - the greater the number of shuffles, the more randomized
for (NSUInteger i = 0; i < count * 20; i++) {
NSUInteger x = arc4random_uniform(count);
NSUInteger y = arc4random_uniform(count);
[res exchangeObjectAtIndex:x withObjectAtIndex:y];
}
return res;
}
// Apply the tags to the buttons. This assumes you have 10 separate ivars for the 10 buttons
NSArray *randomNumbers = [self generateRandomNumbers:10];
button1.tag = [randomNumbers[0] integerValue];
button2.tag = [randomNumbers[1] integerValue];
...
button10.tag = [randomNumbers[9] integerValue];
#meth has the right idea. If you wanna make sure the numbers aren't repeating, try something like this: (note: top would the highest number to generate. Make sure this => amount or else this will loop forever and ever and ever ;)
- (NSArray*) makeNumbers: (NSInteger) amount withTopBound: (int) top
{
NSMutableArray* temp = [[NSMutableArray alloc] initWithCapacity: amount];
for (int i = 0; i < amount; i++)
{
// make random number
NSNumber* randomNum;
// flag to check duplicates
BOOL duplicate;
// check if randomNum is already in your array
do
{
duplicate = NO;
randomNum = [NSNumber numberWithInt: arc4random() % top];
for (NSNumber* currentNum in temp)
{
if ([randomNum isEqualToNumber: currentNum])
{
// now we'll try to make a new number on the next pass
duplicate = YES;
}
}
} while (duplicate)
[temp addObject: randomNum];
}
return temp;
}

Dividing an array into separate arrays of four elements plus the reminder

I'm trying to divide an array into individual arrays of four elements, where the last array will contain the reminder. For example, if that main array's length property will be ten, three subarrays will be created - two consisting of four elements, and one of two elements.
The code I have right now looks like the following:
NSMutableArray *mainMutableArray = [NSMutableArray arrayWithObjects:#"First", #"Second", #"Third", #"Fourth", #"Fifth", #"Sixth", #"Seventh", #"Eighth", nil];
NSMutableArray *mutableArrayOfSubarrays = [NSMutableArray array];
int length = mainMutableArray.count / 4;
int location = 0;
for (int i = 0; i < length; i++)
{
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, 4)]];
location += 4;
}
This of course works only when the reminder is equal to 0.
Any help would be greatly appreciated.
Ok, here we go:
int length = mainMutableArray.count;
for (int location = 0; location < length; location+=4)
{
unsigned int Size=length-location;
if (Size>4) Size=4;
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, Size)]];
}
If you use a while loop, you can make the condition describe what you are actually trying to do:
NSUInteger length = [mainMutableArray count];
NSUInteger location = 0;
// Until the location is less than four away from the end
while( location <= (length - 4) ){
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, 4)]];
location += 4;
}
// Pick up the remainder, if any
if( location != length ){
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, length-location)]];
}
Loop from length*4 to mainMutableArray.count to get the remainder of the array.

Total number of rows in UITableView with multiple sections

I need to calculate the total number of rows in my UITableView, however I have multiple sections. Is there a property on the table view I can access? If not, how can I find this information?
Create an "Objective-c Category" of UITableView from the new file dialogue of xCode and add this method to it:
-(NSInteger)numberOfRowsInTotal{
NSInteger sections = self.numberOfSections;
NSInteger cellCount = 0;
for (NSInteger i = 0; i < sections; i++) {
cellCount += [self numberOfRowsInSection:i];
}
return cellCount;
}
Then import your category header into any class that you need to access this method in et voila, you have what you're looking for.
You can easily calculate this value by iterating through each section.
NSUInteger allRows = 0;
for(NSInteger i = 0; i < [tableview numberOfSections]; i++)
{
allRows += [tableview numberOfRowsInSection:i];
}
If you would like a property you can easily add the above code to a category for UITableView.
A UITableView doesn't know how many sections or rows it has, but your table view data source does. Iterate over the sections and add up the number of rows in each, if that's what you need to do. There may be an easier way, depending on how you're storing the data.

when using NSUInteger in a decreasing for loop, how to determine >= 0

If I want to use a loop like
for (NSUInteger row = 10; row >= 0; row--) {
// do something
}
how do I get around the fact that row will always be > 0 since it's an unsigned integer. Does the middle construct of the for loop just become:
for (NSUInteger row = 10; row; row--) {
}
If you use NSInteger instead of NSUInteger this gets a bit simpler. Because NSInteger is a signed integer type, calling the decrement operator (--) on a variable with the value zero changes the value to -1, so you can test for this using a simple comparison:
for (NSInteger row = 10; row >= 0; row--) {
// do stuff with row
}
If you have to use an NSUInteger for some reason then calling the decrement operator on a variable with a value of zero will result in the variable's value wrapping around to the maximum possible value for NSUInteger. You can test for this using NSUIntegerMax.
for (NSUInteger row = 10; row != NSUIntegerMax; row--) {
// do stuff with row
}
Do you need an unsigned? If so, you'll have to come up with a test that does what you want. Possibly row>=0 && row<=10, although that's a bit clunky for my tastes.
Edit: Just wanted to add that the comparison of unsigned >=0 is superfluous, but if you are going to stick with unsigned, I would leave it, because it at least conveys intent.
You should either do this:
for (NSUInteger row = 10; row >= 1; row--) {
}
or this:
for (NSInteger row = 10; row >= 0; row--) {
}
for (NSUInteger index = 11; index > 0; index--) {
NSUInteger row = index-1;
}
If you really need to use a NSUInteger
for (NSUInteger row = 10; row >= 0; row--) {
// do something
if(row == 0) {break;}
}
Otherwise, try using a NSInteger as Simon Whitaker suggested
Another trick is to move decrement to condition check part. By the way this loop one operation less that classic one.
for (NSUInteger i = 10; i-- > 0;)
{
}

Array giving EXC_BAD_ACCESS in for loop

I have a C array defined in my method as:
int c = 4;
int r = 5;
keysArray[c][r];
I have this for loop, which works, populating the keysArray as expected.
for (int row = 0; row < r; row++) {
for (int column = 0; column < c; column++){
keysArray[column][row] = [anotherArray objectAtIndex:0];
NSLog(#"array1 %#",keysArray[column][row]);
[anotherArray removeObjectAtIndex:0];
}
}
Then in a for loop underneath, featuring exactly the same looping counter structure, when i try to NSLog the array, it gives an EXC_BAD_ACCESS.
for (int row = 0; row < r; row++){
for (int column = 0; column < c; column++) {
NSLog(#"array2: %#",keysArray[column][row]); //EXC_BAD_ACCESS here
}
}
What would cause this to happen, given that the keysArray is defined in the method body, outside of both sets of loops?
Are the contents of anotherArray retained by some other object? If not, they do not exist anymore in the second loop. WTH are you using a C array to store Objective-C objects anyway?
int c = 4;
int r = 5;
NSMutableArray *keysArray = [[NSMutableArray alloc] initWithCapacity:c];
for (int column = 0; column < c; column++) {
[keysArray addObject:[NSMutableArray arrayWithCapacity:r]];
for (int row = 0; row < r; row++) {
[[keysArray objectAtIndex:column] addObject:[anotherArray objectAtIndex:0]];
[anotherArray removeObjectAtIndex:0];
}
}
for (int row = 0; row < r; row++){
for (int column = 0; column < c; column++) {
NSLog(#"array2: %#", [[keysArray objectAtIndex:column] objectAtIndex:row]);
}
}
You need to retain the objects held in your C array. Unlikes an NS*Array, a C array does not retain on adding to the array.
However, for a no-holes 2D array like that, I'd just use a single NSMutableArray. Any N-dimensional array can be represented as a line-- as a one dimensional array-- with simple math.
Namely, to determine the index of an object at (X,Y), use (Y * width) + X).
The only caveat is that NS*Array does not support "holes". You will need to fill the array row by row. That is, for a 3x4 (3 wide, 4 tall) array, you would fill it in the order 0,0, 1,0, 2,0, 0,1, 1,1, etc...
Obviously, insert and remove operations will mess up your 2D representation (but they would in an NSMutableArray of NSMutableArrays, too).
Alternatively, use NSPointerArray as it can have holes.
Could this be the problem :
[anotherArray removeObjectAtIndex:0];
try
keysArray[column][row] = [[anotherArray objectAtIndex:0] retain];
although if I were you I would use NSMutableArray of NSMutableArray instead