Search in CCSprite array element Objective C (cocos2d) - objective-c

I'm using cocos2d and I want to see if a specific string is in the array's element. Here is the element, which is a CCSprite object:
<theSwift = 08A6EA70 | Rect = (0.00,0.00,27.00,75.00) | tag = 2 | atlasIndex = -1>
I am spawning "monsters" and one type of monsters get the tag = 1 and some get the tag = 2. Is it possible to check if the last monster spawned got the tag = 2 in the element above?

If that object is in an array, you could use an NSPredicate to find the object with a certain tag:
NSArray *myArray;
NSObject childWithTag = [[myArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"tag == 2"]]] lastObject];
EDIT: Since you are using cocos2d, its as simple as this:
CCSprite *spriteWithTag = (CCSprite *)[myLayer childWithTag:2];

Not sure I understand your question, I'll give it a shot though:
If the line above is simply an NSString and all you want is to check for tag = 2, then you'd do:
NSRange range = [theString rangeOfString:#"tag = 2"];
if (range.location != NSNotFound) {
// theString contains "tag = 2"
}

If you are talking about NSArray, then do this:
You can use containsObject in an if statement:
if ([array containsObject:#"tag = 2"]) {
//contains tag = 2
}
It would be better to use NSDictionary though. Use setObject:forKey: in NSMutableDictionary to set the values for their keys, and to check the value do:
[dict objectForKey:#"tag"]
I would recommend using the NSDictionary method.

You can easily use this method
[layerName getChildByTag:<(NSInteger)>]
for getting the child of any layer.

Related

How to remove elements of NSDictionary

I have NSArray of NSDictionaries I need to extract 2 values or remove the values I don't need from the dictionary in the example below I need to remove id and NumberValue. any of you knows how can I do that?
Array: (
{
customerUS= {
DisplayName = "level";
InternalName = "Number 2";
NumberValue = 1;
id = xwrf
},
customerCAN= {
DisplayName = "PurchaseAmount";
InternalName = "Number 1";
NumberValue = 3500;
id = adf;
};
}
)
I'll really appreciate your help.
First thing, You can not remove/insert/update value in (immutable) NSDictionary/NSArray you need to convert NSDictionary/NSArray to (mutable) NSMutableDictionary/NSMutableArray.
such like
NSArray *myArr = ....;
NSMutableArray *newMutableArr = [myArr mutableCopy];
Then you can change in newMutableArr.
Such like
for(int i = 0 ; i < newMutableArr.count ; i ++)
{
[[newMutableArr objectAtIndex:i] removeObjectForKey:#"id"];
[[newMutableArr objectAtIndex:i] removeObjectForKey:#"NumberValue"];
}
EDITED:
Without Use of for loop and removeObjectForKey, if you have array of dictionary and both are mutable then you can also delete a key and its object from all elements of the array like this:
[newMutableArr makeObjectsPerformSelector:#selector(removeObjectForKey:) withObject:#"id"];
[newMutableArr makeObjectsPerformSelector:#selector(removeObjectForKey:) withObject:#"NumberValue"];
I would advice you to read Apple documents.
For modifying any Collection object after it is created, you need the mutable version.
For NSDictionary we have NSMutableDictionary. Read here.
We have a method for removing objects:
- (void)removeObjectForKey:(id)aKey
There are other methods as well. You can easily refer them in the above mentioned documentation.
Find out removeObjectForKey for deleting record from NSMutabledictionary.
removeObjectForKey pass the key value whatever you have like
all this are your key
DisplayName,
InternalName,
NumberValue,
id
do like this
removeObjectForKey:#"id";
First of all you have to convert the array to mutable array and then you can remove the key-value pairs from dictionary.
NSMutableArray *mutableArray = [yourArray mutableCopy];for(int i=0;i<mutableArray.count;i++){ NSMutableDictionary *outerDictionary = [mutableArray objectAtIndex:i]; for(NSString *key in outerDictionary.allKeys){ NSMutableDictionary *innerDictionary = [outerDictionary objectForKey:key]; [innerDictionary removeObjectForKey:#"id"]; [innerDictionary removeObjectForKey:#"NumberValue"]; }
}

Create Instance variables at runtime

I want to create instance variables dynamically at runtime, and I want to add these variables to a category. The number of the instance variables may change based on the configuration/properties file which I am using for defining them.
Any ideas??
Use Associative References - this is tricky, but that is the mechanism invented specifically for your use case.
Here is an example from the link above: first, you define a reference and add it to your object using objc_setAssociatedObject; then you can retrieve the value back by calling objc_getAssociatedObject.
static char overviewKey;
NSArray *array = [[NSArray alloc] initWithObjects:# "One", #"Two", #"Three", nil];
NSString *overview = [[NSString alloc] initWithFormat:#"%#", #"First three numbers"];
objc_setAssociatedObject (
array,
&overviewKey,
overview,
OBJC_ASSOCIATION_RETAIN
);
[overview release];
NSString *associatedObject = (NSString *) objc_getAssociatedObject (array, &overviewKey);
NSLog(#"associatedObject: %#", associatedObject);
objc_setAssociatedObject (
array,
&overviewKey,
nil,
OBJC_ASSOCIATION_ASSIGN
);
[array release];
I'd be inclined to just use a NSMutableDictionary (see NSMutableDictionary Class Reference). Thus, you would have an ivar:
NSMutableDictionary *dictionary;
You'd then initialize it:
dictionary = [NSMutableDictionary dictionary];
You can then save values to it dynamically in code, e.g.:
dictionary[#"name"] = #"Rob";
dictionary[#"age"] = #29;
// etc.
Or, if you are reading from a file and don't know what the names of the keys are going to be, you can do this programmatically, e.g.:
NSString *key = ... // your app will read the name of the field from the text file
id value = ... // your app will read the value of the field from the text file
dictionary[key] = value; // this saves that value for that key in the dictionary
And if you're using an older version of Xcode (before 4.5), the syntax is:
[dictionary setObject:value forKey:key];
Depends on exactly what you want to do, the question is vague but if you want to have several objects or several integers or so on, arrays are the way to go. Say you have a plist with a list of 100 numbers. You can do something sort of like this:
NSArray * array = [NSArray arrayWithContentsOfFile:filePath];
// filePath is the path to the plist file with all of the numbers stored in it as an array
That will give you an array of NSNumbers, you can then turn that into an array of just ints if you want like this;
int intArray [[array count]];
for (int i = 0; i < [array count]; i++) {
intArray[i] = [((NSNumber *)[array objectAtIndex:i]) intValue];
}
Whenever you want to get an integer from a certain position, lets say you want to look at the 5th integer, you would do this:
int myNewInt = intArray[4];
// intArray[0] is the first position so [4] would be the fifth
Just look into using a plist for pulling data, it will them be really easy to create arrays of custom objects or variables in your code by parsing the plist.

Bug in my code using NSArray crashes

I'm making a code which shows the names of people on a list.
The list is different for each date, so my problem is when there is only like 1 or no people signed and I make an array with index beyond the limit of people, it crashed. I know that this happens because the array is empty, but how do I make the code ignore empty arrays?
I have tried to make an "if" that count the number of arrays and then decide to post the array or just post no name. But it doesn't work like this, I still get the out of bounds exception.
How should I manage empty arrays?
My code:
NSString *html = [request2 responseString];
NSMutableArray *arr2 = [html componentsSeparatedByString:#"vagter"];
NSString *html1 = [arr2 objectAtIndex:1];
//name1
NSMutableArray *arr3 = [html1 componentsSeparatedByString:#"<td><font color=#ffffff>"];
NSString *html2 = [arr3 objectAtIndex:1];
NSMutableArray *arr4 = [html2 componentsSeparatedByString:#"</font></td>"];
NSString *html3 = [arr4 objectAtIndex:0];
_name.text = html3;
//name 2
NSMutableArray *arr5 = [html1 componentsSeparatedByString:#"<td><font color=#ffffff>"];
if ([arr5 count] > 4) {
NSString *html4 = [arr5 objectAtIndex:5];
NSMutableArray *arr6 = [html4 componentsSeparatedByString:#"</font></td>"];
NSString *html5 = [arr6 objectAtIndex:0];
_name.text = html5;
}
else
{
_name1.text = #"No name";
}
It should be:
if ([arr5 count] > 5) {
NSString *html4 = [arr5 objectAtIndex:5];
...
Indeed, index 5 will correspond to the sixth array item, so you have to have at least 6 objects in it.
Use the same pattern, if you want to check for the array bounds, in all cases.
The problem is that you expect the return from componentsSeparatedByString to return consistent results according to your expectations.
Clearly thats not working.
Array handling is simple. Dont ask for objects that arent there.
Check the count and only access indexes from 0 to count - 1;
If count is zero dont access anything.

How to perform binary search on NSArray?

What is the simplest way to do a binary search on an (already) sorted NSArray?
Some potential ways I have spotted so far include:
The use of CFArrayBSearchValues (mentioned here) - would this work on an NSArray?
The method indexOfObject:inSortedRange:options:usingComparator: of NSArray assumes the array is sorted and takes an opts param of type NSBinarySearchingOptions - does this mean it performs a binary search? The docs just say:
Returns the index, within a specified range, of an object compared with elements in the array using a given NSComparator block.
Write my own binary search method (something along the lines of this).
I should add that I am programming for iOS 4.3+
Thanks in advance.
The second option is definitely the simplest. Ole Begemann has a blog entry on how to use the NSArray's indexOfObject:inSortedRange:options:usingComparator: method:
NSArray *sortedArray = ... // must be sorted
id searchObject = ...
NSRange searchRange = NSMakeRange(0, [sortedArray count]);
NSUInteger findIndex = [sortedArray indexOfObject:searchObject
inSortedRange:searchRange
options:NSBinarySearchingFirstEqual
usingComparator:^(id obj1, id obj2)
{
return [obj1 compare:obj2];
}];
See NSArray Binary Search
1 and 2 will both work. #2 is probably easier; it certainly doesn't make sense for that method to do anything other than a binary search (if the range is above a certain size, say). You could verify on a large array that it only does a small number of comparisons.
I'm surprised that nobody mentioned the use of NSSet, which [when it contains objects with a decent hash, such as most Foundation data types] performs constant time lookups. Instead of adding your objects to an array, add then to a set instead (or add them to both if you need to retain a sorted order for other purposes [or alternatively on iOS 5.0 or Mac OS X 10.7 there is NSOrderedSet]).
To determine whether an object exists in a set:
NSSet *mySet = [NSSet setWithArray:myArray]; // try to do this step only once
if ([mySet containsObject:someObject])
{
// do something
}
Alternatively:
NSSet *mySet = [NSSet setWithArray:myArray]; // try and do this step only once
id obj = [mySet member:someObject];
// obj is now set to nil if the object doesn't exist or it is
// set to an object that "isEqual:" to someObject (which could be
// someObject itself).
It is important to know that you will lose any performance benefit if you convert the array to a set each time you do a lookup, ideally you will be using a preconstructed set containing the objects you want to test.
//Method to pass array and number we are searching for.
- (void)binarySearch:(NSArray *)array numberToEnter:(NSNumber *)key{
NSUInteger minIndex = 0;
NSUInteger maxIndex = array.count-1;
NSUInteger midIndex = array.count/2;
NSNumber *minIndexValue = array[minIndex];
NSNumber *midIndexValue = array[midIndex];
NSNumber *maxIndexValue = array[maxIndex];
//Check to make sure array is within bounds
if (key > maxIndexValue || key < minIndexValue) {
NSLog(#"Key is not within Range");
return;
}
NSLog(#"Mid indexValue is %#", midIndexValue);
//If key is less than the middleIndexValue then sliceUpArray and recursively call method again
if (key < midIndexValue){
NSArray *slicedArray = [array subarrayWithRange:NSMakeRange(minIndex, array.count/2)];
NSLog(#"Sliced array is %#", slicedArray);
[self binarySearch:slicedArray numberToEnter:key];
//If key is greater than the middleIndexValue then sliceUpArray and recursively call method again
} else if (key > midIndexValue) {
NSArray *slicedArray = [array subarrayWithRange:NSMakeRange(midIndex+1, array.count/2)];
NSLog(#"Sliced array is %#", slicedArray);
[self binarySearch:slicedArray numberToEnter:key];
} else {
//Else number was found
NSLog(#"Number found");
}
}
//Call Method
#interface ViewController ()
#property(nonatomic)NSArray *searchArray;
#end
- (void)viewDidLoad {
[super viewDidLoad];
//Initialize the array with 10 values
self.searchArray = #[#1,#2,#3,#4,#5,#6,#7,#8,#9,#10];
//Call Method and search for any number
[self binarySearch:self.searchArray numberToEnter:#5];
// Do any additional setup after loading the view, typically from a nib.
}
CFArrayBSearchValues should work—NSArray * is toll-free bridged with CFArrayRef.

how to sort an NSArray with a nested NSArray

Hi I'm new with the Objective-C and i try to do some try.
I have an NSArray called "values". It is an array of array. It seems like :
["0" = > "aString",6872,5523,0091]
["1" = > "anotherString",4422,1234,0091]
["2" = > "aString",6812,2143,0314] ...
How do I sort the "values" array than the first integer value?
I should use the NSPredicate ?
please help me with some example.
thanks
Something like that with block (assuming that your integer value are NSNumber or some class that can be compared):
NSArray *sortArray = [yourArray sortedArrayUsingComparator: ^(id elt1, id elt2) {
return [[elt1 objectAtIndex:1] compare:[elt2 objectAtIndex:1]];
} ];