This question already has answers here:
Random number without repeating
(3 answers)
Closed 8 years ago.
I'm brand new to SpriteKit, and I'm creating a game that involves randomizing the CGPoint positions of objects on my screen when the user reaches certain score increments. I created a plist of the 8 set positions I want my objects to choose from when this method is called, but I'm having a problem with my objects selecting duplicate plist positions and overlapping each other. Is there a method I can call that will prevent my objects from picking the same position from the plist as another object when that method is called?
FYI, I plan on calling this randomization method many times throughout the course of the game.
I wrote the following code but my game crashes.
- (NSMutableArray *)pickAndRemoveFromList:(NSMutableArray *)list {
list = [_objectList copy];
NSInteger randomIndex = arc4random()%list.count;
Objects *object = [list objectAtIndex:randomIndex];
[list addObject:object];
[list removeObject:object];
return list;
}
Your method has several problems. First, you're passing in a mutable array called list, but then in the first line of the method you redefine what list is. You either shouldn't pass in the list to start with, or you shouldn't redefine it. Second, if _objectList is an immutable array, you need to use mutableCopy to make it a mutable array, not copy. Third, there's no need to add an object to the list, and then turn around and remove it in the next line. Also a better random number function to use is arc4random_uniform(). So, if you're passing in a mutable array, your method should be,
- (NSMutableArray *)pickAndRemoveFromList:(NSMutableArray *)list {
NSInteger randomIndex = arc4random_uniform((int)list.count);
Objects *object = [list objectAtIndex:randomIndex];
[list removeObject:object];
return list;
}
Related
I have array of custom objects. I am removing objects from that array but I am not able to remove the objects from that array here is my code.
if([arr_userFav count]>0)
{
int i;
for (i=0; i<[arr_userFav count]; i++)
{
Post *objectCopy = [arr_userFav copy]; //create a copy of our object
[arr_temp_Fav addObject: objectCopy];
}
NSLog(#"size of arr_temp_Fav %lu",(unsigned long)[arr_temp_Fav count]);
[arr_userFav removeAllObjects];
}
after removing objects form arr_userFav I have size of array as zero but when I put a breakpoint after it & see the objects in it then I don't get a empty array. Please tell how to do it?
Below is the screenshot
Please look very carefully at what your code is doing.
The object that you add to arr_temp_fav is a copy of arr_user_fav, that is a copy of the complete array. So if your array originally had ten elements, you now have an array with ten arrays as elements, each with ten elements itself. If you had 10,000 elements it's a lot worse.
Post *objectCopy = [arr_userFav copy]; //create a copy of our object
Here we have a case of a comment that would be completely pointless if it was correct - it is however incorrect and may be hiding from you what you are doing wrong.
I am trying to check if the NSMutableArray has a specific object, before adding the object to it, if exists then don't add.
i looked over many posts explaining how to do this, managed to implement it like this, but it always gives me that the object "doesn't exist", though i already added it !
//get row details into FieldLables Object
AllItemsFieldNames *FieldLabels = feedItems[row];
// object to hold single row detailes
AllItemsFieldNames *SelectedRowDetails = [[AllItemsFieldNames alloc] init];
SelectedRowDetails.item_name = FieldLabels.item_name;
//SelectedRowDetails.item_img = FieldLabels.item_img;
SelectedRowDetails.item_price = FieldLabels.item_price;
//NSLog(#"item has been added %#", SelectedRowDetails.item_name);
//NSLog(#"shopcartLength %lu", (unsigned long)SelectedFieldsNames.count);
if([SelectedFieldsNames containsObject:SelectedRowDetails])
{
NSLog(#"Already Exists!");
}
else
{
NSLog(#"Doesn't Exist!");
[SelectedFieldsNames addObject:SelectedRowDetails];
}
I can display all object from the NSMutableArray into a table, what i need to do in the above code is stop the addition of duplicate objects.
The first method listed on the NSArray documentation under the section "querying an array" is containsObject:. If it's not working, that suggests that your implementation of isEqual: is not correct. Make sure you follow the note in the documentation:
If two objects are equal, they must have the same hash value. This
last point is particularly important if you define isEqual: in a
subclass and intend to put instances of that subclass into a
collection. Make sure you also define hash in your subclass.
You might also consider using an NSSet since you can't add duplicates to that. Of course, this would also require a working version of isEqual:.
Sets are composed of unique elements, so this serves as a convenient way to remove all duplicates in an array.
here some sample,
NSMutableArray*array=[[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"4", nil];
[array addObject:#"4"];
NSMutableSet*chk=[[NSMutableSet alloc ]initWithArray:array]; //finally initialize NSMutableArray to NSMutableSet
array= [[NSMutableArray alloc] initWithArray:[[chk allObjects] sortedArrayUsingSelector:#selector(compare:)]]; //after assign NSMutableSet to your NSMutableArray and sort your array,because sets are unordered.
NSLog(#"%#",array);//1,2,3,4
I'm trying the following code to create an instance, assign properties, add to array.
Then, assigning new properties and adding again.
However array will contain 2 identical objects (equal to the second one added). The class Message simply has several (nonatomic, retain) NSStrings/Integer properties.
This probably has something to do with my understanding of pointer, can someone explain?
self.messages=[[NSMutableArray alloc]init];
Message *m=[[Message alloc]init];
m.cb=#"2402";
m.ck=1001;
m.msg=#"as";
[self.messages addObject:m];
m.cb=#"2422";
m.ck=1002;
m.msg=#"aadfsdsdfdssdklsdflkh";
[self.messages addObject:m];
NSLog(#"%#",self.messages);
When you add an object to an array, it does not add a copy of the object to the array, but instead just a reference to it. If you want two different objects, then you need to create two different objects instead of re-using the same one (or, as #Brendon points out, create a copy when you add it to your array).
To fix your example, the most common technique would be to add the following line right before you start modifying the properties for the second object:
m=[[Message alloc]init];
Or, use a second pointer and object instead of reusing m.
EDIT:
To add a copy, change [self.messages addObject:m]; to [self.messages addObject:[m copy]];, assuming that the Message class conforms to the NSCopying protocol.
Yes, after executing the posted code self.messages contains the Message object twice, at indexes 0 and 1. That's not a problem, though. Arrays can contain any object, even themselves.
It seems that you want two distict objects, so you would just create a second Message.
You can either implement the NSCopy protocol — as mentioned by lnafziger — or just create new instances quite easily in a for loop.
«Two or more, use a for»
— Edsger W. Dijkstra
self.messages=[[NSMutableArray alloc] init];
NSArray *dataArray = #[ #{#"cb": #"2402", #"ck": #(1001), #"msg": #"as"},
#{#"cb": #"2422", #"ck": #(1002), #"msg": #"aadfsdsdfdssdklsdflkh"}
];
for(NSDictionary *data in dataArray) {
Message *m=[[Message alloc] init];
m.cb = data[#"cb"];
m.ck = [data[#"ck"] integerValue];
m.msg = data[#"msg"];
[self.messages addObject:m];
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Best way to remove from NSMutableArray while iterating?
Mods: I realized this was a duplicate of this question, can you close/delete it?
If you don't want to create a temporary or new array, you can use this:
NSMutableArray *array = ...; // your mutable array
NSIndexSet *toBeRemoved = [array indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
// The block is called for each object in the array.
BOOL removeIt = ...; // YES if the element should be removed and NO otherwise
return removeIt;
}];
[array removeObjectsAtIndexes:toBeRemoved];
(But a temporary NSIndexSet is used.)
Remark: My thought was that it might be more efficient to remove all matching elements "at once" instead of removing each element separately during the iteration, as suggested by Richard J. Ross III.
But a short test showed that this is not the case. Removing every second element from an array with 1000000 elements takes almost the same time with both methods on my computer.
You can use an NSPredicate to do this, see this SO question and answer.
https://stackoverflow.com/a/129942/36984
And the Apple docs for this:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html#//apple_ref/occ/instm/NSMutableArray/filterUsingPredicate:
I am polling an HTTP API - it returns one item at a time, in real-time (about every 4 seconds). As each item is received, I would like a new UITableView cell to be populated. The full list of received items must remain in a class property, I'm guessing an NSMutableArray. What is the best way to initialize an NSMutableArray as a class property, update it as new information comes in, and then use the count to update a new UITableViewCell?
Here's how I'm adding content to an NSMutableDictionary:
NSMutableDictionary *messageContents = [[NSMutableDictionary alloc] init];
[messageContents retain];
[messageContents setValue:messageText forKey:#"text"];
[messageContents setValue:image forKey:#"image"];
[self addMessageToDataArray:messageContents];
Here's the method stuffing objects into the array:
- (void)addMessageToDataArray:(NSArray *)messageDictionary {
[self.messageDataArray addObject:messageDictionary];
NSLog(#"count = %#", [self.messageDataArray count]);
[self reloadTableData];
}
At this point, calling count on the messageDataArray class property crashes the application. I'm very used to working with arrays in Actionscript, Obj-C is obviously totally different. Please explain the method for instantiating an NSMutableArray as a class property, filling it with NSMutableDictionary's and then finding the NSMutableArray count (which will be dynamically updating in real-time) so I can use that info to update a UITableView (on the fly).
Or... tell me I'm being silly and suggest a much easier solution.
From your description I would guess you're not allocating the messageDataArray before using it.
The init function for your table view (controller?) class should have a line like this
messageDataArray = [[NSMutableArray alloc] initWithCapacity:20];
It's also worth checking that you have [messageDataArray release]; in your dealloc method.