I have this code for creating an array of images to display on a view. Most of the pages in my view will have 20 images (in columns of 5, rows of 4), but i actually have 43 images and when my images array contains the final 3, i get an exception when on the 4th iteration of the inner loop, the array is empty.
- (void)displayImages:(NSMutableArray *)images {
NSMutableArray *keysArray = [[NSMutableArray alloc] initWithCapacity:5];
for (int column = 0; column < 5; column++){
[keysArray addObject:[NSMutableArray arrayWithCapacity:5]];
for (int row = 0; row < 4; row++) {
[[keysArray objectAtIndex:column] addObject:[images objectAtIndex:0]];
[images removeObjectAtIndex:0];
}
}
....
Can i get around this?
Thanks.
EDIT:
Following on from this code, is the code which actually pulls the image from the array. But the same scenario occurs... on the fourth iteration it crashes.
for (int column = 0; column < 5; column++) {
for (int row = 0; row < 4; row++){
UIButton *keyButton = [UIButton buttonWithType:UIButtonTypeCustom];
keyButton.frame = CGRectMake(column*kKeyGap, row*kKeyGap, kKeySize, kKeySize);
[keyButton setImage:[[keysArray objectAtIndex:column] objectAtIndex:row] forState:UIControlStateNormal];
[keyButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:keyButton];
}
}
[keysArray release];
I can't test images at this point as the array is emptied already.
Just check to see if there are objects in that array before you try to do anything with it
- (void)displayImages:(NSMutableArray *)images {
NSMutableArray *keysArray = [[NSMutableArray alloc] initWithCapacity:5];
for (int column = 0; column < 5; column++){
[keysArray addObject:[NSMutableArray arrayWithCapacity:5]];
for (int row = 0; row < 4; row++) {
//test to see if there's an object left in the inner array
if ([images count] > 0) {
[[keysArray objectAtIndex:column] addObject:[images objectAtIndex:0]];
[images removeObjectAtIndex:0];
}
}
}
Try using the actual array sizes instead of constant values in your for loop text expressions. So rather than this:
for (int column = 0; column < 5; column++)
do this:
for (int column = 0; column < [keysArray count]; column++)
The resulting code might look something like this:
for (int column = 0; column < [keysArray count]; column++) {
NSArray *rowArray = [keysArray objectAtIndex:column];
for (int row = 0; row < [rowArray count]; row++) {
UIButton *keyButton = [UIButton buttonWithType:UIButtonTypeCustom];
keyButton.frame = CGRectMake(column*kKeyGap, row*kKeyGap, kKeySize, kKeySize);
[keyButton setImage:[rowArray objectAtIndex:row] forState:UIControlStateNormal];
[keyButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:keyButton];
}
}
By the way, nested message expressions can be cool sometimes, but nesting calls to objectAtIndex: is probably never a good idea.
test the number of object in images
Related
I have the array which consists of objects:
ViewController *item1 = [ViewController new];
item1.name = #"Mary";
item1.Description = #"good girl";
ViewController *item2 = [ViewController new];
item2.name = #"Daniel";
item2.Description = #"bad boy";
ComplexArray= [NSArray arrayWithObjects: item1, item2, nil];`
i want to view in labels a name and description if name is equal Mary
for (int i = 0; i < [ComplexArray count]; i++) {
if (item[i].name isEqualString:#"Mary") {
_nameLabel.text= item[i].name;
_DescriptionLabel.text= item[i].Description;
}
}
Please help me
You basically had it. All I did was rename item to ComplexArray added [] around the isEqualToString call and added a break:
for (int i = 0; i < [ComplexArray count]; i++) {
ViewController *item = ComplexArray[i];
if ([item.name isEqualString:#"Mary"]) {
_nameLabel.text= item.name;
_DescriptionLabel.text= item.Description;
break; // Added
}
}
There are other ways, but this approach is fine.
BTW: variables should start, by convention, with a lowercase character.
Your problem is you didn't assign anything in item variable. Just update like this and it will work.
for (int i = 0; i < [ComplexArray count]; i++) {
ViewController *item = [ComplexArray objectAtIndex:i]; // you missed this line.
if ([item.name isEqualToString:#"Mary"]) { //you missed the opening "[" and closing "]"
_nameLabel.text= item.name;
_DescriptionLabel.text= item.Description;
}
}
I am writing a recursive Sudoku solver and I am having some issues with 2D array handling. I included the function which is giving the trouble. There are some unnecessary lines I was using for debugging in there.
- (Stack *)successors
{
Stack *stack = [[Stack alloc] init];
NSMutableArray *temp = [[NSMutableArray alloc] init];
NSMutableArray *test = [[NSMutableArray alloc] init];
temp = [self.board copy];
for (int x = 0; x < columns; x++) {
for (int y = 0; y < rows; y++) {
if ([self.board[x][y] isEqualToString:#""] ||
[self.board[x][y] isEqualToString:#"."]) {
NSLog(#"%d %d", x, y);
for (int i = 1; i < 10; i++) {
NSLog(#"%d", i);
[temp[x] setObject:[NSString stringWithFormat:#"%d", i] atIndex:y];
State *tempState = [[State alloc] initWithBoard:temp];
if ([tempState legal]) {
NSMutableArray *input = [NSMutableArray arrayWithArray:temp];
[stack push:input];
[stack push:input];
[test addObject:input];
}
}
NSLog(#"test %#", test);
int p = [stack size];
for (int i = 0; i < p; i++) {
NSLog(#"%#", [stack pop]);
}
return stack;
}
}
}
return stack;
}
essentially, it begins at the top of the array and if the space is empty, it tries putting in the number 1 through 9 and if it is legal, based on another function I wrote previously, it will input it in the temp array and add it to the stack. I checked this and it works great. However, after adding them all together, I NSLog to check the stack and find that all of the stacked arrays now begin with the number 9, the last number checked in the temp array. I believe I am having some issue with keeping reference to the temp array, but I cannot figure it out. Any help is great.
I've stored 4 unique numbers inside an NSMutableArray from 1-4. i've done that by using this code:
storeArray = [[NSMutableArray alloc] init];
BOOL record = NO;
int x;
for (int i=1; [storeArray count] < 4; i++) //Loop for generate different random values
{
x = arc4random() % 4;//generating random number
if(i==1)//for first time
{
[storeArray addObject:[NSNumber numberWithInt:x]];
}
else
{
for (int j=0; j<= [storeArray count]-1; j++)
{
if (x ==[[storeArray objectAtIndex:j] intValue])
record = YES;
}
if (record == YES)
{
record = NO;
}
else
{
[storeArray addObject:[NSNumber numberWithInt:x]];
}
}
}
I can then print the numbers out using storeArray[1] and so on.
the problem is i want to print the numbers inside this.
[option1 setTitle:questions[r][storeArray[0]] forState: UIControlStateNormal];
[option2 setTitle:questions[r][storeArray[1]] forState: UIControlStateNormal];
[option3 setTitle:questions[r][storeArray[2]] forState: UIControlStateNormal];
[option4 setTitle:questions[r][storeArray[3]] forState: UIControlStateNormal];
How can i do this?, cause i when i do this i get thread sigbrt error?
The problem is that your algorithm is faulty and when there are collisions because you are trying to keep the numbers unique, you don't record anything so your array might not always be the expected length. Actually there is a 91% chance of this happening in your case so it looks like it happens all the time.
Instead of trying to write your own algorithm, just use the existing classes. Simply use an NSSet to guarantee the uniqueness of the numbers in your array.
NSMutableSet *set = [[NSMutableSet alloc] init];
while(set.count < 4) {
int x = arc4random() % 4;
[set addObject:[NSNumber numberWithInteger:x]];
}
NSArray * storeArray = [set allObjects];
in the if statement below how could i make piece1's name be dynamic so that it checks for other pieces also which are piece1, piece2, ...piece5.
I would have to make it look like something like [#"piece%d",i] I'm just not sure what the correct way of writing this would be since i'm just starting with iOS.
for (int i = 0; i < 6; i++) {
if(CGRectContainsPoint([piece1 frame], location)){
piece1.center = location;
}
}
Something like this :
for (int i = 0; i < 6; i++) {
// Create a selector to get the piece
NSString *selectorName = [NSString stringWithFormat:#"piece%d", i];
SEL selector = NSSelectorFromString(selectorName);
UIView *peice = [self performSelector:selector];
// Now do your test
if(CGRectContainsPoint([piece frame], location)){
piece1.center = location;
}
}
The key bits are NSSelectorFromString to turn a string into a selector and performSelector: to get the object matching it.
First add tags to your imageView when initializing them
then change your code to this
for (int i = 0; i < 6; i++) {
UIImageView *piece = (UIImageView *)[self.view viewWithTag:i] ;
if(CGRectContainsPoint([piece frame], location)){
piece.center = location;
}
}
make sure your tag matches the value that will be in the loop i values.
I would like to select x amount of items randomly from a "list" in objective C store them in an other "list" (each item can only be selected one) , I'm talking about lists because I'm coming from Python. What would be the best way to store a list of strings in Objective C ?
cheers,
You should use NSMutableArray class for changeable arrays or NSArray for non-changeable ones.
UPDATE: a piece of code for selecting a number of items from an array randomly:
NSMutableArray *sourceArray = [NSMutableArray array];
NSMutableArray *newArray = [NSMutableArray array];
int sourceCount = 10;
//fill sourceArray with some elements
for(int i = 0; i < sourceCount; i++) {
[sourceArray addObject:[NSString stringWithFormat:#"Element %d", i+1]];
}
//and the magic begins here :)
int newArrayCount = 5;
NSMutableIndexSet *randomIndexes = [NSMutableIndexSet indexSet]; //to trace new random indexes
for (int i = 0; i < newArrayCount; i++) {
int newRandomIndex = arc4random() % sourceCount;
int j = 0; //use j in order to not rich infinite cycle
//tracing that all new indeces are unique
while ([randomIndexes containsIndex:newRandomIndex] || j >= newArrayCount) {
newRandomIndex = arc4random() % sourceCount;
j++;
}
if (j >= newArrayCount) {
break;
}
[randomIndexes addIndex:newRandomIndex];
[newArray addObject:[sourceArray objectAtIndex:newRandomIndex]];
}
NSLog(#"OLD: %#", sourceArray);
NSLog(#"NEW: %#", newArray);