How to remove array object from for loop - objective-c

please Help me. I stuck here when deleting an object from array.
for (id obj in self.arrSavedImage)
{
Class cls = [obj class];
id newObj = [[cls alloc] init];
//UIImage *img = nil;
if([newObj isKindOfClass:[UIImage class]]){
NSLog(#"class type %#", [newObj class]);
}
else{
[self.arrSavedImage removeObject:obj];
}
}
Thank You.

You shouldn't remove objects from an array you are enumerating over. Better is to keep a list of the objects you want to delete, and then delete them when you've finished enumerating the original array:
NSMutableArray *toDelete = [NSMutableArray new];
for (id obj in self.arrSavedImage)
{
Class cls = [obj class];
id newObj = [[cls alloc] init];
if([newObj isKindOfClass:[UIImage class]]){
NSLog(#"class type %#", [newObj class]);
}
else{
[toDelete addObject:obj];
}
}
for (id obj in toDelete)
[self.arrSavedImage removeObject:obj];

NSMutableArray *itemsToDelete = [[NSMutableArray alloc] init];
for (id obj in self.arrSavedImage)
{
Class cls = [obj class];
id newObj = [[cls alloc] init];
//UIImage *img = nil;
if([newObj isKindOfClass:[UIImage class]]){
NSLog(#"class type %#", [newObj class]);
}
else{
[itemsToDelete addObject:obj];
}
}
[self.arrSavedImage removeObjectsInArray:itemsToDelete];

You can not remove the object in array while in loop.
You should create a new array with existing array and remove objects from it. Then replace the old array with editedArray.
NSMutableArray * editedArray = [[NSMutableArray alloc] initWithArray:self.arrSavedImage];
for (id obj in self.arrSavedImage)
{
Class cls = [obj class];
id newObj = [[cls alloc] init];
//UIImage *img = nil;
if([newObj isKindOfClass:[UIImage class]]){
NSLog(#"class type %#", [newObj class]);
}
else{
[editedArray removeObject:obj];
}
}
[self.arrSavedImage setArray:editedArray];
editedArray = nil;

Related

Objective-c: Use predicate with an object

I have a search bar for my table view and until now I used a predicate to check if the data array contains the search bar value. But now there are objects in my data array and now I don't know how to use the predicate. Here is my code:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains [cd] %#", self.controller.searchBar.text];
NSMutableArray *temp = [[NSMutableArray alloc] init];
for (int i = 0; i < [self.data count]; i++) {
Student *student = [[Student alloc] initWithIdentifier:[[self.data objectAtIndex:self.tableView.indexPathForSelectedRow.row] objectForKey:#"id"] name:[[self.data objectAtIndex:self.tableView.indexPathForSelectedRow.row] objectForKey:#"name"] is_public:[[self.data objectAtIndex:self.tableView.indexPathForSelectedRow.row] objectForKey:#"is_public"] password:[[self.data objectAtIndex:self.tableView.indexPathForSelectedRow.row] objectForKey:#"passwort"]];
[temp addObject:student];
}
self.results = [temp filteredArrayUsingPredicate:predicate];
Now it compares the search bar value with the object. But it should compare the search bar value with object.name. How can I do this?
EDIT:
The Student code:
#implementation Student
- (id)initWithIdentifier:(NSString *)identifier name:(NSString *)name is_public:(NSString *)is_public password:(NSString *)password {
self= [super init];
if( self ) {
self.identifier = identifier;
self.name = name;
self.is_public = is_public;
self.password = password;
}
return self;
}
- (NSDictionary*)writableRepresentation {
NSMutableDictionary *writableRepresentation= [NSMutableDictionary dictionaryWithCapacity:4];
[writableRepresentation setValue:self.identifier forKey:#"Identifier"];
[writableRepresentation setValue:self.name forKey:#"Name"];
[writableRepresentation setValue:self.is_public forKey:#"is_public"];
[writableRepresentation setValue:self.password forKey:#"password"];
return writableRepresentation;
}
+ (Student*)studentFromDictionary:(NSDictionary*)dictionaryRepresentation {
return [[Tipprunde alloc] initWithIdentifier:[dictionaryRepresentation valueForKey:#"Identifier"] name:[dictionaryRepresentation valueForKey:#"Name"] is_public:[dictionaryRepresentation valueForKey:#"is_public"] password:[dictionaryRepresentation valueForKey:#"password"]];
}
#end
It don't seem to work with SELF.name. I get the following error:
-[Student objectForKey:]: unrecognized selector sent to instance...

uisearchbar in grouped section uitable

I've pieced together several tutorials to create a grouped table with sections and I'm now trying to get a uisearchbar to work. the problem I'm having is how to search within the grouped sections.
I've read the similar questions this post suggested but can't
This is the code to create the grouped sections
#import "Job.h" // A model for the data
#import "Address.h" // Another model for the data
- (void)viewDidLoad
{
[super viewDidLoad];
self.theTable.delegate = self;
self.theTable.dataSource =self;
_searchBar.delegate = (id)self;
FMDBDataAccess *db = [[FMDBDataAccess alloc] init];
jobs = [[NSMutableArray alloc] init];
jobs = [db getJobs:1];
_sections = [[NSMutableDictionary alloc] init];
NSMutableArray *jobsTempArray = [db getJobsAsDictionary:1];
BOOL found;
// Loop through the books and create our keys
for (NSDictionary *book in jobsTempArray)
{
NSString *cLong = [book objectForKey:#"addrAddress"];
NSString *c = [cLong substringToIndex:1];
found = NO;
for (NSString *str in [_sections allKeys])
{
if ([str isEqualToString:c])
{
found = YES;
}
}
if (!found)
{
[_sections setValue:[[NSMutableArray alloc] init] forKey:c];
}
}
// Loop again and sort the books into their respective keys
for (NSDictionary *book in jobsTempArray)
{
[[_sections objectForKey:[[book objectForKey:#"addrAddress"] substringToIndex:1]] addObject:book];
}
// Sort each section array
for (NSString *key in [_sections allKeys])
{
[[_sections objectForKey:key] sortUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"addrAddress" ascending:YES]]];
}
}
And this is the code that searches
-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text
{
if(text.length == 0)
{
_isFiltered = FALSE;
}
else
{
_isFiltered = true;
_filteredjobs = [[NSMutableArray alloc] init];
//for (Job* book in jobs)
//for (Job* book in [_sections allKeys])
//for (NSString *food in [_sections allKeys])
for (NSDictionary* book in [_sections allKeys])
{
NSString *addrStr = [book objectForKey:#"addrAddress"];
NSString *postStr = [book objectForKey:#"addrPostcode"];
//NSRange nameRange = [book.jobAddress rangeOfString:text options:NSCaseInsensitiveSearch];
NSRange nameRange = [addrStr rangeOfString:text options:NSCaseInsensitiveSearch];
//NSRange descriptionRange = [book.jobPostcode rangeOfString:text options:NSCaseInsensitiveSearch];
NSRange descriptionRange = [postStr rangeOfString:text options:NSCaseInsensitiveSearch];
if(nameRange.location != NSNotFound || descriptionRange.location != NSNotFound)
{
[_filteredjobs addObject:book];
}
}
}
[self.theTable reloadData];
}
I've got as far as realising I need to change for (Job* food in jobs) to for (NSDictionary* book in [_sections allKeys]) but I'm stuck how to search within [_sections allKeys]
Specifically this line
NSRange nameRange = [addrStr rangeOfString:text options:NSCaseInsensitiveSearch];
which crashes with
-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x692e200
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]:
unrecognized selector sent to instance 0x692e200':
Any ideas? PS Treat me as a noob, I'll need some code as well as explanation - I'm still learning obj-c
Check the Link.It shows the UISearchBar With Grouped Section Tableview.Its a simple Tutorial..Hope its useful for you
I found the answer in
UISearchBar - search a NSDictionary of Arrays of Objects and reading up on allkeys.
Basically loop through the grouped NSDictionary and extract the NSArrays, then loop through again searching...
-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text
{
if(text.length == 0)
{
_isFiltered = FALSE;
}
else
{
_isFiltered = true;
_filteredjobs = [[NSMutableArray alloc] init];
NSString *currentLetter = [[NSString alloc] init];
for (int i=0; i<[_sections count]; i++)
{
currentLetter = [[_sections allKeys] objectAtIndex:i];
NSArray *jobsForKey = [ [NSArray alloc] initWithArray:[_sections objectForKey:[[_sections allKeys] objectAtIndex:i]] ];
for (int j=0; j<[jobsForKey count]; j++)
{
NSDictionary *book = [jobsForKey objectAtIndex:j];
NSRange titleResultsRange = [[book objectForKey:#"addrAddress"] rangeOfString:text options:NSCaseInsensitiveSearch];
if(titleResultsRange.location != NSNotFound)
{
[_filteredjobs addObject:book];
}
}
}
}
[self.theTable reloadData];
}

Error: index 1 beyond bounds [0 .. 0]

I am a rookie in Xcode and I have been using the UITableViewController which shows this error.
This is the error message:
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
* First throw call stack:
(0x1c91012 0x10cee7e 0x1c330b4 0x36d0 0xc58d5 0xc5b3d 0xacce83 0x1c50376 0x1c4fe06 0x1c37a82 0x1c36f44 0x1c36e1b 0x1beb7e3 0x1beb668 0x1665c 0x2132 0x2065)
libc++abi.dylib: terminate called throwing an exception
(lldb)
This is my code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row == 0) {
NSString *strURL = [NSString stringWithFormat:#"http://localhost:8888/GetDetail.php?choice=row0"];
NSArray *arrayImagesNames = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURL]];
arrayDataFromServer2 = [[NSMutableArray alloc]init];
NSEnumerator *enumForNames = [arrayImagesNames objectEnumerator];
id objName;
while ( objName = [enumForNames nextObject]) {
[arrayDataFromServer2 addObject:[NSDictionary dictionaryWithObjectsAndKeys:objName, #"name", nil]];
}
NSString *nn = [[arrayDataFromServer2 objectAtIndex:indexPath.row] objectForKey:#"name"];
row1 = [nn intValue];
NSLog(#"%d", row1);
CompanyProfileViewController *profile = [self.storyboard instantiateViewControllerWithIdentifier:#"Profile"];
[self.navigationController pushViewController:profile animated:YES];
profile.profileid = row1;
NSLog(#"%d", profile.profileid);
}
if (indexPath.row == 1) {
NSString *strURL = [NSString stringWithFormat:#"http://localhost:8888/GetDetail.php?choice=row1"];
NSArray *arrayImagesNames = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURL]];
arrayDataFromServer2 = [[NSMutableArray alloc]init];
NSEnumerator *enumForNames = [arrayImagesNames objectEnumerator];
id objName;
while (objName = [enumForNames nextObject]) {
[arrayDataFromServer2 addObject:[NSDictionary dictionaryWithObjectsAndKeys:objName, #"name", nil]];
}
NSString *nn = [[arrayDataFromServer2 objectAtIndex:indexPath.row] objectForKey:#"name"];
row1 = [nn intValue];
NSLog(#"%d", row1);
CompanyProfileViewController *profile = [self.storyboard instantiateViewControllerWithIdentifier:#"Profile"];
[self.navigationController pushViewController:profile animated:YES];
profile.profileid = row1;
NSLog(#"%d", profile.profileid);
}
if (indexPath.row == 2) {
NSString *strURL = [NSString stringWithFormat:#"http://localhost:8888/GetDetail.php?choice=row2"];
NSArray *arrayImagesNames = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURL]];
arrayDataFromServer2 = [[NSMutableArray alloc]init];
NSEnumerator *enumForNames = [arrayImagesNames objectEnumerator];
id objName;
while ( objName = [enumForNames nextObject]) {
[arrayDataFromServer2 addObject:[NSDictionary dictionaryWithObjectsAndKeys:objName, #"name", nil]];
}
NSString *nn = [[arrayDataFromServer2 objectAtIndex:indexPath.row] objectForKey:#"name"];
row1 = [nn intValue];
NSLog(#"%d", row1);
CompanyProfileViewController *profile = [self.storyboard instantiateViewControllerWithIdentifier:#"Profile"];
[self.navigationController pushViewController:profile animated:YES];
profile.profileid = row1;
NSLog(#"%d", profile.profileid);
}
if (indexPath.row == 3) {
NSString *strURL = [NSString stringWithFormat:#"http://localhost:8888/GetDetail.php?choice=row3"];
NSArray *arrayImagesNames = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURL]];
arrayDataFromServer2 = [[NSMutableArray alloc]init];
NSEnumerator *enumForNames = [arrayImagesNames objectEnumerator];
id objName;
while ( objName = [enumForNames nextObject]) {
[arrayDataFromServer2 addObject:[NSDictionary dictionaryWithObjectsAndKeys:objName, #"name", nil]];
}
NSString *nn = [[arrayDataFromServer2 objectAtIndex:indexPath.row] objectForKey:#"name"];
row1 = [nn intValue];
NSLog(#"%d", row1);
CompanyProfileViewController *profile = [self.storyboard instantiateViewControllerWithIdentifier:#"Profile"];
[self.navigationController pushViewController:profile animated:YES];
profile.profileid = row1;
NSLog(#"%d", profile.profileid);
}
}
When I click on the second cell (index.row == 1) this error would occur.
I have used breakpoint and the error was on the line:
"NSString *nn = [[arrayDataFromServer2 objectAtIndex:indexPath.row] objectForKey:#"name"];"
Please Help!
Swift 4
after more time i am get the love for this Error 😄
when you use the tableView from the storyboard and implementing in your code :
hint that and compare :
between the number of section and numberOfRowsInSection == storyboard and code
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 3
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 1
}
You have an array and you have either 0 or 1 elements in it. Now you are trying to extract 2nd element from it, [0] is first, and [1] is second.
EDIT:
As you are not sure when the array will contain 1 or more objects. Therefore you can use as:
NSString *nn=nil;
if([arrayDataFromServer2 count]>1){
nn = [[arrayDataFromServer2 objectAtIndex:indexPath.row] objectForKey:#"name"];
}

Remove object from an array stored in a singleton

Im working with a singleton to store some data, her's the implementation
static ApplicationData *sharedData = nil;
#implementation ApplicationData
#synthesize list;
+ (id)sharedData
{
static dispatch_once_t dis;
dispatch_once(&dis, ^{
if (sharedData == nil) sharedData = [[self alloc] init];
});
return sharedData;
}
- (id)init
{
if (self = [super init])
{
list = [[NSMutableArray alloc]init];
}
return self;
}
if list have less than 3 (2<) object i the app crash with "index 0 beyond bounds for empty array"
// NSMutableArray *anArray = [[NSMutableArray alloc]initWithObjects:#"", nil];
while ([[[ApplicationData sharedData]list] lastObject] != nil)
{
File *file = [[[ApplicationData sharedData]list] lastObject];
BOOL isDir;
if (![[NSFileManager defaultManager] fileExistsAtPath:file.filePath isDirectory:&isDir])
{
NSMutableDictionary *tmpDic = [NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:file.fileName,file.filePath,logEnteryErrorfileNotFoundDisplayName,[formatter stringFromDate:[NSDate date]], nil] forKeys:[NSArray arrayWithObjects:logShredFileName,logShredFilePath,logShredStatue,logShredDate, nil]];
[logArray addObject:tmpDic];
errorOccured = YES;
[[[ApplicationData sharedData]list] removeLastObject];
continue;
}
... other code
}
if i use the anArray that work perfectly.
what is the problem ?
That's totally weird, you've probably did something else to achieve this. Why don't you use - (void)removeAllObjects?
Maybe you remove objects in the while cycle the last line, ie:
while ([[[ApplicationData sharedData]list] count] != 0)
{
// remove object from list
// ...
[[[ApplicationData sharedData]list] removeLastObject];
}
And just a note, you don't need to check if (sharedData == nil) in sharedData as far as it's guaranteed to be executed only once. (unless you do something outside to your static variable, but that's not how it's supposed to be done I believe)

isMemberOfClass doesn't work as expected with ocunit [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
'isMemberOfClass' returning 'NO' when custom init
I've some trouble with the "isMemberOfClass"-Method.
I have a class, that generates and returns objects ("MyObject")
// ObjectFactory.h
...
-(MyObject*)generateMyObject;
...
// ObjectFactory.m
...
-(MyObject*)generateMyObject
{
MyObject *obj = [[MyObject alloc]init];
obj.name = #"Whatever"; // set properties of object
return obj;
}
...
And there's a unittest-class, that calls the generateMyObject-selector and checks the class of the returned object:
...
ObjectFactory *factory = [[ObjectFactory alloc]init];
MyObject *obj = [factory generateMyObject];
if (![obj isMemeberOfclass:[MyObject class]])
STFail(#"Upps, object of wrong class returned...");
else
...
I expect, that the else-part is processed...but the STFail(...) is called instead, but why?
Thx for any help!
Regards,
matrau
Ok, here is the original copy&pasted code:
//testcase
- (void)test001_setCostumeFirstCostume
{
NSString *xmlString = #"<Bricks.SetCostumeBrick><costumeData reference=\"../../../../../costumeDataList/Common.CostumeData\"/><sprite reference=\"../../../../..\"/></Bricks.SetCostumeBrick>";
NSError *error;
NSData *xmlData = [xmlString dataUsingEncoding:NSASCIIStringEncoding];
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData
options:0 error:&error];
SetCostumeBrick *newBrick = [self.parser loadSetCostumeBrick:doc.rootElement];
if (![newBrick isMemberOfClass:[SetCostumeBrick class]])
STFail(#"Wrong class-member");
}
// "MyObject"
#implementation SetCostumeBrick
#synthesize indexOfCostumeInArray = _indexOfCostumeInArray;
- (void)performOnSprite:(Sprite *)sprite fromScript:(Script*)script
{
NSLog(#"Performing: %#", self.description);
[sprite performSelectorOnMainThread:#selector(changeCostume:) withObject:self.indexOfCostumeInArray waitUntilDone:true];
}
- (NSString*)description
{
return [NSString stringWithFormat:#"SetCostumeBrick (CostumeIndex: %d)", self.indexOfCostumeInArray.intValue];
}
#end
// superclass of SetCostumeBrick
#implementation Brick
- (NSString*)description
{
return #"Brick (NO SPECIFIC DESCRIPTION GIVEN! OVERRIDE THE DESCRIPTION METHOD!";
}
//abstract method (!!!)
- (void)performOnSprite:(Sprite *)sprite fromScript:(Script*)script
{
#throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:#"You must override %# in a subclass", NSStringFromSelector(_cmd)]
userInfo:nil];
}
#end
// the "factory" (a xml-parser)
- (SetCostumeBrick*)loadSetCostumeBrick:(GDataXMLElement*)gDataSetCostumeBrick
{
SetCostumeBrick *ret = [[SetCostumeBrick alloc] init];
NSArray *references = [gDataSetCostumeBrick elementsForName:#"costumeData"];
GDataXMLNode *temp = [(GDataXMLElement*)[references objectAtIndex:0]attributeForName:#"reference"];
NSString *referencePath = temp.stringValue;
if ([referencePath length] > 2)
{
if([referencePath hasSuffix:#"]"]) //index found
{
NSString *indexString = [referencePath substringWithRange:NSMakeRange([referencePath length]-2, 1)];
ret.indexOfCostumeInArray = [NSNumber numberWithInt:indexString.intValue-1];
}
else
{
ret.indexOfCostumeInArray = [NSNumber numberWithInt:0];
}
}
else
{
ret.indexOfCostumeInArray = nil;
#throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:#"Parser error! (#1)"]
userInfo:nil];
}
NSLog(#"Index: %#, Reference: %#", ret.indexOfCostumeInArray, [references objectAtIndex:0]);
return ret;
}
SOLUTION:
Eiko/jrturton gave me a link to the solution - thx: isMemberOfClass returns no when ViewController is instantiated from UIStoryboard
The problem was, that the classes were included in both targets (app and test bundle)
Thank you guys for your help :)
You generally want isKindOfClass:, not isMemberOfClass. The isKindOfClass: will return YES if the receiver is a member of a subclass of the class in question, whereas isMemberOfClass: will return NO in the same case.
if ([obj isKindOfClass:[MyObject class]])
For example,
NSArray *array = [NSArray array];
Here [array isMemberOfClass:[NSArray class]] will return NO but [array isKindOfClass:[NSArray class]] will return YES.
Ok, with different class addresses per your comment, I think I can track this down to be a duplicate of this:
isMemberOfClass returns no when ViewController is instantiated from UIStoryboard
Basically, your class is included twice.