Reputation: 1251
I have an array with following elements in ViewDidLoad
method
inputArray = [NSMutableArray arrayWithObjects:@"car", @"bus", @"helicopter", @"cruiz", @"bike", @"jeep", nil];
I have another UITextField
for searching the elements .So once i type some thing in UITextField
i want to check whether that string is present in "inputArray" or not.If it is not matching with elements in inputArray then remove the corresponding elements from inputArray .
for (NSString* item in inputArray)
{
if ([item rangeOfString:s].location == NSNotFound)
{
[inputArray removeObjectIdenticalTo:item];//--> Shows Exception
NSLog(@"Contains :%@",containsAnother);
}
}
but this code shows exception , something related to "removeobject:"
Exception :
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSCFConstantString rangeOfString:options:range:locale:]: nil argument'
*** First throw call stack:
`
Upvotes: 5
Views: 25098
Reputation: 437442
+1 to Anoop for pointing out that you can use filteredArrayUsingPredicate
. Thus, if you wanted to create a new array based upon the matches in inputArray
, you could also use something like:
NSArray *matchingArray = [inputArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF contains[c] %@", s]];
Alternatively, given that inputArray
is a NSMutableArray
you can simply filter the array with this single line:
[inputArray filterUsingPredicate:[NSPredicate predicateWithFormat:@"SELF contains[c] %@", s]];
Or, if you like blocks:
[inputArray filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return ([evaluatedObject rangeOfString:s].location != NSNotFound);
}]];
Upvotes: 0
Reputation: 5237
This is a clean solution that I like to use. You define a NSArray category to extend it and create a map method. This method creates a new NSArray based on what you return within your block:
@interface NSArray (BlockExtensions)
/*!
Invokes block once for each element of self, returning a new array containing the
values returned by the block.
*/
- (NSArray *)map:(id (^)(id obj))block;
@end
@implementation NSArray (BlockExtensions)
- (NSArray *)map:(id (^)(id obj))block
{
return [self mapWithOptions:0 usingBlock:^id(id obj, NSUInteger idx) {
return block(obj);
}];
}
- (NSArray *)mapWithOptions:(NSEnumerationOptions)options usingBlock:(id (^)(id obj, NSUInteger idx))block
{
NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self count]];
[self enumerateObjectsWithOptions:options usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
id newobj = block? block(obj, idx) : obj;
if (newobj)
[array addObject:newobj];
}];
return array;
}
@end
The block will be called once for every item in your original array, passing this object as a parameter:
NSArray *newArray = [inputArray map:^id(NSString *item) {
if ([item rangeOfString:s].location == NSNotFound) {
return item;
}
return nil;
}];
newArray
will contain your filtered out items!
Upvotes: 0
Reputation: 46533
In fast enumeration you can NOT modify the collection.
The enumerator object becomes constant and immutable.
If you want to do updation on the array
You should like this :
NSMutableArray *inputArray = [NSMutableArray arrayWithObjects:@"car", @"bus", @"helicopter", @"cruiz", @"bike", @"jeep", nil];
NSString *s=@"bus";
for (int i=inputArray.count-1; i>-1; i--) {
NSString *item = [inputArray objectAtIndex:i];
if ([item rangeOfString:s].location == NSNotFound) {
[inputArray removeObject:item];
}
}
EDIT:
The above works similar as this :
NSArray *array=[inputArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF CONTAINS[c] %@",s]];
Upvotes: 10
Reputation: 4836
As others have said you can't mutate an array while it is being enumerated. The easiest way to do what you want and keep the convenience of fast enumeration is to copy the array.
for (NSString* item in [inputArray copy]) {
...
}
Upvotes: 0
Reputation: 47049
Use following Code. (This Code is use for filter Array base on input string/text of UITextField
)
Take Two NSMutableArray
and add one array to another array in ViewDidLoad
method such like,
self.listOfTemArray = [[NSMutableArray alloc] init]; // array no - 1
self.ItemOfMainArray = [[NSMutableArray alloc] initWithObjects:@"YorArrayList", nil]; // array no - 2
[self.listOfTemArray addObjectsFromArray:self.ItemOfMainArray]; // add 2array to 1 array
And Write following delegate Method of UISearchBar
- (BOOL) textFieldDidChange:(UITextField *)textField
{
NSString *name = @"";
NSString *firstLetter = @"";
if (self.listOfTemArray.count > 0)
[self.listOfTemArray removeAllObjects];
if ([searchText length] > 0)
{
for (int i = 0; i < [self.ItemOfMainArray count] ; i = i+1)
{
name = [self.ItemOfMainArray objectAtIndex:i];
if (name.length >= searchText.length)
{
firstLetter = [name substringWithRange:NSMakeRange(0, [searchText length])];
//NSLog(@"%@",firstLetter);
if( [firstLetter caseInsensitiveCompare:searchText] == NSOrderedSame )
{
// strings are equal except for possibly case
[self.listOfTemArray addObject: [self.ItemOfMainArray objectAtIndex:i]];
NSLog(@"=========> %@",self.listOfTemArray);
}
}
}
}
else
{
[self.listOfTemArray addObjectsFromArray:self.ItemOfMainArray ];
}
[self.tblView reloadData];
}
}
Output Show in your Console.
Upvotes: 0
Reputation: 19310
You can use the following code
for (int i=0;i<[inputArray count]; i++) {
NSString *item = [inputArray objectAtIndex:i];
if ([item rangeOfString:s].location == NSNotFound) {
[inputArray removeObject:item];
i--;
}
}
Upvotes: 9
Reputation: 10251
The s
in your question is probably nil. So your are getting the exception.Please check that out.
Upvotes: 0
Reputation: 14427
That needs to be an NSMutableArray
. You can't modify an NSArray
once created (except to start all over).
Change this:
inputArray = [NSArray arrayWithObjects:@"car", @"bus", @"helicopter", @"cruiz", @"bike", @"jeep", nil];
to this:
inputArray = [NSMutableArray arrayWithObjects:@"car", @"bus", @"helicopter", @"cruiz", @"bike", @"jeep", nil];
and also change the property to NSMutableArray also:
@property(nonatomic, strong) NSMutableArray *inputArray;
Upvotes: 0