How will I check a NSInteger is in a NSMutableArray? - ios

I am adding NSInteger object as NSNumber in a NSMutableArray. But now I am such in condition like that I need to check a NSInteger is in the NSMutableArray. If the array contains the value then I will execute my next code else I will execute other code. I want to execute else condition only if array doesn't contain the value. I tried this code:
for(int i=0; i<self.indexArray.count; i++){
if([[self.indexArray objectAtIndex:i] integerValue]==self.selectedIndex){
NSLog(#"execute if in the array");
}
else{
NSLog(#"execute if not in the array");
}
}
Though the array contains the value, else is executing for the loop. My question is how will I check a value which one is in a NSMutableArray or not.

This is the simple solution:
BOOL containsSelected = NO;
for (int i = 0; i < self.indexArray.count; i++){
if ([[self.indexArray objectAtIndex:i] integerValue] == self.selectedIndex){
containsSelected = YES;
break;
}
}
if (containsSelected) {
NSLog(#"execute if in the array");
} else {
NSLog(#"execute if not in the array");
}
I believe this could be further simplifed to:
if ([self.indexArray containsObject:#(self.selectedIndex)]) {
NSLog(#"execute if in the array");
} else {
NSLog(#"execute if not in the array");
}
but I haven't tested it.

Related

How to check my nsarray contains another nsarray element or not in fastest way IOS

I have seen many of the answers but didn't get my answer. So that's why I decide to post a question. If anybody can find the helpful link or answer will be helpful.
Here is my array of dictionary:
<__NSArrayM 0x283ba04e0>(
{
failvalues = (
"Check 1"
);
fieldname = "Check 3";
fieldvalue = (
"Check 1",
"Check 2"
);
showtype = mandatory;
tagvalue = 0;
},
{
failvalues = (
Fail
);
fieldname = "Dropdown 3";
fieldvalue = (
Fail
);
showtype = mandatory;
tagvalue = 1;
},
{
failvalues = (
"Check 1",
"Check 4"
);
fieldname = "Check 4";
fieldvalue = (
"Check 1",
"Check 2"
);
showtype = mandatory;
tagvalue = 2;
})
So I want to check if the fieldvalue contains failvalues or not.
Below is the code which I have tried but it doesn't seem to work:
for (int i = 0; i< [arrFields count]; i++) {
if ([[[arrFields objectAtIndex:i]objectForKey:#"failvalues"] isKindOfClass:[NSArray class]]) {
if (![[[[arrFields objectAtIndex:i] objectForKey:#"failvalues"] objectAtIndex:0] isEqualToString:#""]) {
NSLog(#"Field Values %#",[[arrFields objectAtIndex:i]objectForKey:#"fieldvalue"]);
NSArray *failValues = [[arrFields objectAtIndex:i] objectForKey:#"failvalues"];
for (int j = 0; j < [failValues count]; j++) {
if ([failValues containsObject:[[arrFields objectAtIndex:i]objectForKey:#"fieldvalue"]]) {
NSLog(#"Contains %#",[[arrFields objectAtIndex:i]objectForKey:#"fieldvalue"]);
} else {
NSLog(#"No fail values");
}
}
} else {
NSLog(#"No Fail Fields");
}
} else {
NSLog(#"Not an array");
}
}
EDIT:
This one I have tried but how to break both the loops
for (int i = 0; i< [arrFields count]; i++) {
NSArray *fieldValues = [[arrFields objectAtIndex:i]objectForKey:#"fieldvalue"];
NSArray *failValues = [[arrFields objectAtIndex:i] objectForKey:#"failvalues"];
if (![[[[arrFields objectAtIndex:i] objectForKey:#"failvalues"] objectAtIndex:0] isEqualToString:#""]) {
//NSLog(#"Field Values %#",[[arrFields objectAtIndex:i]objectForKey:#"fieldvalue"]);
for(NSString *value in fieldValues){
if ([failValues containsObject:value]) {
NSLog(#"Contains %#",value);
scanStatus = TRUE;
return;
}
}
} else {
NSLog(#"No Fail Fields");
}
}
Thanks in advance!
This is a classic use case for the feared and dreaded goto. It's well known that goto can create disastrously messy code, but in cases like this it'll make things cleaner. You have to know when to use goto, and definitely use it sparingly. But here's how I'd write your code:
BOOL found = NO;
for (NSDictionary *dict in arrFields)
{
NSArray *fieldValues = dict[#"fieldvalue"];
NSArray *failValues = dict[#"failvalues"];
if (![failValues[0] isEqualToString:#""]) {
for (NSString *value in fieldValue) {
if ([failValues containsObject:value]) {
NSLog(#"Contains %#",value);
found = YES;
goto leaveLoops;
}
}
}
}
leaveLoops:
if (found) NSLog(#"Found one.");
else NSLog(#"Didn't find one.");
And if you cannot bring yourself to use goto (you wouldn't be alone,) here's a gotoless alternative:
BOOL found = NO;
for (NSDictionary *dict in arrFields)
{
NSArray *fieldValues = dict[#"fieldvalue"];
NSArray *failValues = dict[#"failvalues"];
if (![failValues[0] isEqualToString:#""]) {
for (NSString *value in fieldValue) {
if ([failValues containsObject:value]) {
NSLog(#"Contains %#",value);
found = YES;
break;
}
}
if (found) break;
}
}
if (found) NSLog(#"Found one.");
else NSLog(#"Didn't find one.");

*** Collection <__NSArrayM: 0x117d7320> was mutated while being enumerated.'

I made a bug when I implement the search function. I opened an asynchronous thread. But when deleting a character (a digit of a phone number), the app would crash.
Error:
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x117d7320> was mutated while being enumerated.'
Code:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
//
self.isSearch = YES;
//remove the last search all the contacts
[self.resultArr removeAllObjects];
//
[self.rcs_SearchTableView reloadData];
//
dispatch_queue_t uploadQueue = dispatch_get_global_queue(0, 0);
dispatch_queue_t getMainQueue = dispatch_get_main_queue();
dispatch_async(uploadQueue, ^{
NSMutableArray *phoneArr = (NSMutableArray *)[self rcs_GetPhoneNumberFromeDatabaseWithPhone:searchText];
//
//NSLog(#"清空上次搜索的数据:%#", self.resultArr);
//NSLog(#"输入的关键字是---%#---%lu",searchText,(unsigned long)searchText.length);
if (0 == searchText.length || [searchText isEqualToString:#" "]) {
self.isSearch = NO;
//[self.rcs_SearchTableView reloadData];
[self.resultArr removeAllObjects];
}
//[self.rcs_SearchTableView reloadData];
if (0 != phoneArr.count) {
//
for (NSUInteger i = 0; i < phoneArr.count; i ++) {
RCSPhoneModel *flagPhoneModel = phoneArr[i];
for (NSUInteger i = 0; i < self.rcsRecentSearchDataSource.count; i ++) {
RCSContactModel *flagModel = self.rcsRecentSearchDataSource[i];
if ([flagPhoneModel.serverId isEqualToString:flagModel.serverId] || [flagPhoneModel.phone isEqualToString:flagModel.name]) {
//the same contact has multiple Numbers To prevent repeated add the same contacts
if (![self.resultArr containsObject:flagModel]) {
[self.resultArr addObject:flagModel];
continue;
}
}
}
}
}else{
//search contacts by name
for (NSInteger i = 0; i < self.rcsRecentSearchDataSource.count; i ++) {
RCSContactModel *model = self.rcsRecentSearchDataSource[i];
NSString *nameStr = model.name;
if (nameStr.length >= searchText.length) {
//search all the name
if ([nameStr containsString:searchText]) {
[self.resultArr addObject:model];
}
}
}
}
//
if (self.resultArr.count > 0) {
self.isSearch = YES;
//[self.rcs_SearchTableView reloadData];
}
//The phone contacts or local contact synchronized to the server
dispatch_async(getMainQueue, ^{
[self.rcs_SearchTableView reloadData];
});
});
}
A for loop should not enumerate anything that could change on any other thread or that could change within that loop. You should only enumerate an object that you are certain is not going to change while being enumerated (either in another thread, or within the loop itself). One way to do this is to only use a local copy of the array to enumerate over.
I can't see where anything being enumerated in your for loops is changed within the loop, so I would guess that in some other code in some other thread, you are changing either self.rcsRecentSearchDataSource or phoneArr. This crashes the for loop that enumerates self.rcsRecentSearchDataSource or phoneArr because it is required to not change while being enumerated.
Does this really need to be run on a separate thread?
If so, use a thread-local copy of the array to enumerate over, instead of the original array. That way you can be sure that nothing else can modify it, because it does not exist in any other scope.
Eg, there are two places where you could change your code to:
NSArray *localSearchDataSource = [self.rcsRecentSearchDataSource copy];
for (NSUInteger i = 0; i < localSearchDataSource.count; i ++) {
and one place where you could change to:
NSArray *localPhoneArr = [[self rcs_GetPhoneNumberFromeDatabaseWithPhone:searchText] copy];
for (NSUInteger i = 0; i < localPhoneArr .count; i ++) {
I got it answer and like unders codes:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
//
self.isSearch = YES;
//
if (0 == searchText.length || [searchText isEqualToString:#" "]) {
self.isSearch = NO;
//[self.resultArr removeAllObjects];
}
//Remove the last search all the contacts
[self.resultArr removeAllObjects];
//
[self.rcs_SearchTableView reloadData];
//
NSMutableArray *localSearchDataSource = [self.resultArr mutableCopy];
//Create an array of objects as well as the original array
//According to the input access to the phone number of the data
NSArray *localPhoneArr = [[self rcs_GetPhoneNumberFromeDatabaseWithPhone:searchText] copy];
//
//[self.rcs_SearchTableView reloadData];
if (0 != localPhoneArr.count) {
//Because when data matching number takes longer, using asynchronous thread
dispatch_queue_t uploadQueue = dispatch_get_global_queue(0, 0);
dispatch_queue_t getMainQueue = dispatch_get_main_queue();
dispatch_async(uploadQueue, ^{
//
for (NSUInteger i = 0; i < localPhoneArr.count; i ++) {
RCSPhoneModel *flagPhoneModel = localPhoneArr[i];
for (NSUInteger i = 0; i < self.rcsRecentSearchDataSource.count; i ++) {
RCSContactModel *flagModel = self.rcsRecentSearchDataSource[i];
if ([flagPhoneModel.serverId isEqualToString:flagModel.serverId] || [flagPhoneModel.phone isEqualToString:flagModel.name]) {
//The same contact has multiple Numbers To prevent repeated add the same contacts
if (![localSearchDataSource containsObject:flagModel]) {
[localSearchDataSource addObject:flagModel];
}
}
}
}
//Add the search results to the search data source
dispatch_async(getMainQueue, ^{
[self.resultArr addObjectsFromArray:localSearchDataSource];
[self.rcs_SearchTableView reloadData];
});
});
}else{
//Search contacts by name
for (NSInteger i = 0; i < self.rcsRecentSearchDataSource.count; i ++) {
RCSContactModel *model = self.rcsRecentSearchDataSource[i];
NSString *nameStr = model.name;
if (nameStr.length >= searchText.length) {
//Search all name
if ([nameStr containsString:searchText]) {
[self.resultArr addObject:model];
}
}
}
}
//
if (self.resultArr.count > 0) {
self.isSearch = YES;
[self.rcs_SearchTableView reloadData];
}
}
I made two change that 'NSMutableArray *localSearchDataSource = [self.resultArr mutableCopy];' and 'NSArray *localPhoneArr = [[self rcs_GetPhoneNumberFromeDatabaseWithPhone:searchText] copy];'. And finish it . Collection <__NSArrayM: 0x117d7320> was mutated while being enumerated.'

Executes same code more than once. How to use Goto statement inside for loop

I have code which is used more than two times in different condition in same function. So I decided to use Goto statement. But that code will be executed inside for loop. So I don't understand how to call same code in same function. I don't want to create one more function. My code is...
- (void)setSelectedSearchCriteria:(NSString *)storedValue storedTag:(NSString *)storedTag D_Key:(NSString *)D_Key D_Tag_Value:(NSString *)D_Tag_Value arrayMain:(NSMutableArray *)arrayMain bgView:(UIView *)bgView
{
//Add data
NSMutableArray *sArray = [[storedValue componentsSeparatedByString:#","] mutableCopy];
NSMutableArray *sTagArray = [[storedTag componentsSeparatedByString:#","] mutableCopy];
[sArray removeObject:#""];
[sTagArray removeObject:#""];
int maxTag = 0;
if (sTagArray.count != 0)
{
maxTag = [[sTagArray valueForKeyPath:#"#max.intValue"] intValue];
for (int i = maxTag + 1; i <= [D_Tag_Value intValue]; i++)
goto add_value;
}
else
goto add_value;
add_value:
{
NSString *D_Value = [[arrayMain objectAtIndex:[D_Tag_Value intValue]] valueForKey:PARAMETER_KEY];
if (![sArray containsObject:D_Value])
{
[sArray addObject:D_Value];
[sTagArray addObject:D_Tag_Value];
}
//Add data
UIButton *btn = (UIButton *)[bgView viewWithTag:[D_Tag_Value intValue]];
[self setSelectedButtonStyle:btn];
}
storedValue = [[[sArray valueForKey:KEY_DESCRIPTION] componentsJoinedByString:#","] mutableCopy];
storedTag = [[[sTagArray valueForKey:KEY_DESCRIPTION] componentsJoinedByString:#","] mutableCopy];
[SEARCH_CRITERIAS setValue:storedValue forKey:D_Key];
[SEARCH_CRITERIAS_TAG setValue:storedTag forKey:D_Key];
}
Code inside add_value executed in for loop and also in else part. So I don't know how to manage this.
Define a block inside your function
void(^theBlock)(void) = ^(){
NSString *D_Value = [[arrayMain objectAtIndex:[D_Tag_Value intValue]] valueForKey:PARAMETER_KEY];
if (![sArray containsObject:D_Value])
{
[sArray addObject:D_Value];
[sTagArray addObject:D_Tag_Value];
}
//Add data
UIButton *btn = (UIButton *)[bgView viewWithTag:[D_Tag_Value intValue]];
[self setSelectedButtonStyle:btn];
};
I don't fully understand what do you do in your add_value. If it can change to a block receive some parameters and return some value that would be better
after that you simply call the block
theBlock();
The code doesn't actually depend on the loop counter, so it isn't too hard to refactor the code so that you can simply execute the loop the appropriate number of times.
- (void)setSelectedSearchCriteria:(NSString *)storedValue storedTag:(NSString *)storedTag D_Key:(NSString *)D_Key D_Tag_Value:(NSString *)D_Tag_Value arrayMain:(NSMutableArray *)arrayMain bgView:(UIView *)bgView
{
//Add data
NSMutableArray *sArray = [[storedValue componentsSeparatedByString:#","] mutableCopy];
NSMutableArray *sTagArray = [[storedTag componentsSeparatedByString:#","] mutableCopy];
[sArray removeObject:#""];
[sTagArray removeObject:#""];
int loopCount = 1;
if (sTagArray.count != 0) {
int maxTag = [[sTagArray valueForKeyPath:#"#max.intValue"] intValue];
loopCount = [D_Tag_Value intValue] - maxTag;
}
for (int i = 0; i < loopCount ; i++) {
NSString *D_Value = [[arrayMain objectAtIndex:[D_Tag_Value intValue]] valueForKey:PARAMETER_KEY];
if (![sArray containsObject:D_Value])
{
[sArray addObject:D_Value];
[sTagArray addObject:D_Tag_Value];
}
//Add data
UIButton *btn = (UIButton *)[bgView viewWithTag:[D_Tag_Value intValue]];
[self setSelectedButtonStyle:btn];
}
storedValue = [[[sArray valueForKey:KEY_DESCRIPTION] componentsJoinedByString:#","] mutableCopy];
storedTag = [[[sTagArray valueForKey:KEY_DESCRIPTION] componentsJoinedByString:#","] mutableCopy];
[SEARCH_CRITERIAS setValue:storedValue forKey:D_Key];
[SEARCH_CRITERIAS_TAG setValue:storedTag forKey:D_Key];
}

iOS removeObjectAtIndex

Good day!
I have this code to remove the a particular database in a NSMutableArray.
-(void)removeDatabaseName:(NSString*)databaseName {
// remove database from array of databases
for (int index = 0; index < [[self.openDatabases objectForKey:#"databaseName"] count]; index++) {
if ([[self.openDatabases objectForKey:#"databaseName"] objectAtIndex:index] == databaseName) {
//Match
[[self.openDatabases objectForKey:#"database"] removeObjectAtIndex:index];
[[self.openDatabases objectForKey:#"databaseName"] removeObjectAtIndex:index];
[[self.openDatabases objectForKey:#"location"] removeObjectAtIndex:index];
NSLog(#"removed database");
break;
}
}
}
As a result, it displays the NSLog(#"removed database"); but I don't know if it was totally removed in the NSMutableArray or if I am wrong can I have at least remove the specific file?

better way of removing double (NSManagedObjects) from NSArray (also logic flaw)

I made the following method to remove doubles, however it doesn't fully work. Any suggestions?
Thank you for the help,
-(NSMutableArray*)removeDuplicateCars:(NSMutableArray*)array{
NSMutableArray *noDuplicates =[[NSMutableArray alloc]init];
for (int i=0; i<[array count]; i++) {
int counter =0;
Car *car =(Car*)[array objectAtIndex:i];
if ([noDuplicates count]==0) {
[noDuplicates addObject:car];
}
for (int i=0; i<[noDuplicates count]; i++) {
Car *car2 =(Car*)[array objectAtIndex:i];
if (![car.name isEqualToString:car2.name]) {
counter++;
}
}
if (counter==[noDuplicates count]) {
[noDuplicates addObject:car];
}
}
NSLog(#"number of results = %i",[noDuplicates count]);
return noDuplicates;
}
Create an array called "addedCars" - you will use it to store the name of each unique car.
In each iteration, use [NSArray containsObject:] to check if the current name has already been added to "addedCars". If not, add the name to "addedCars" and the car to "noDuplicates". Otherwise, skip this item, as it has already been added to noDuplicates.
be sure [isEqual:] and [hash] is implemented as you expected
-(NSMutableArray*)removeDuplicateCars:(NSMutableArray*)array{
NSOrderedSet *set = [[NSOrderedSet alloc] initWithArray:array];
NSMutableArray *newArr = [NSMutableArray arrayWithCapacity:[set count]];
for (id obj in set) {
[newArr addObject:obj];
}
return newArr;
}
You used ![car.name isEqualToString:car2.name] to compare objects so I believe you want to filter objects with same name? Than you need to override [isEqual:] for Car
- (BOOL)isEqual:(id)other {
if ([other isKindOfClass:[self class]]) {
return [self.name isEuqalToString: [other name]];
}
return NO;
}
- (NSUInteger)hash {
return [self.name hash];
}
also check this question The best way to remove duplicate values from NSMutableArray in Objective-C?

Resources