Objective-c: Use predicate with an object - objective-c

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...

Related

Filtering an NSArray with custom objects [duplicate]

This question already has answers here:
How do I sort an NSMutableArray with custom objects in it?
(27 answers)
Closed 9 years ago.
I have a class like this :
#interface MyObject : NSObject
#property (nonatomic, strong) NSString *type;
#end
and I am creating an array like this:
NSMutableArray *array = [NSMutableArray array];
MyObject *obj = [[MyObject alloc] init];
obj.type = #"test1";
[array addObject:obj];
MyObject *obj2 = [[MyObject alloc] init];
obj2.type = #"test2";
[array addObject:obj2];
MyObject *obj3 = [[MyObject alloc] init];
obj3.type = #"test1";
[array addObject:obj3];
I would like to filter the array to just have only the objects which have different types, in my example just to have obj1, obj2 and remove the obj3.
Something along these lines should do the trick:
NSMutableSet * types = [NSMutableSet setWithCapacity:10];
NSPredicate * filterPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
if ([types containsObject:[evaluatedObject type]]) {
return NO;
}
else {
[types addObject:[evaluatedObject type]];
return YES
}
}];
NSArray * filteredArray = [detailedError filteredArrayUsingPredicate:filterPredicate];
The above code keeps the first object of each type and removes others.
I would do this by just overriding hash and isEqual:
- (BOOL) isEqual:(id)object
{
if([object isKindOfClass: [self class]])
return [_type isEqualToString: object];
return NO;
}
- (NSInteger) hash
{
return [_type hash];
}
Then taking the distinct objects array from a set created from the array:
NSArray* filteredArray= [NSSet setWithArray: array].allObjects;

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];
}

NSMutableArray- removeObject results with removing object and a nil element

Firstly, I am new with Objective C.
I have my class Song that has a pair of attributes.
In my main class i got a variable allSongs that is a NSMutableArray and in this array have I added all my song-objects.
My problem comes when trying to call [self.allSongs removeObject:OBJECT];
Using the debugger, I can see that before the call, the list looks as expected. But after the call it will result that the targeted object will be removed but also the first element in the array will turn to nil.
Is this a common pointer problem or what?
Here is my code:
in h file
#property (nonatomic, strong) NSMutableArray *songs;
#property (nonatomic, strong) NSMutableArray *allChapters;
in m file
- (void)viewDidLoad
{
self.chosenChapter = [[NSString alloc]initWithFormat:self.chosenChapter];
self.allChapters = [[NSMutableArray alloc]init];
//Chapter names and chapter page range
chapters = [[NSArray alloc]initWithObjects:#"chapter1", #"chapter2", #"chapter3", nil];
chaptersRange = [[NSArray alloc]initWithObjects:#"25", #"51", #"88", nil];
//Filnames of every song
files = [[NSMutableArray alloc] initWithObjects:#"test", #"Feta_fransyskor", nil];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey: #"page" ascending: YES];
self.songs = [[NSMutableArray alloc]init];
for(int i = 0; i < chapters.count; i++){
Song *chapter = [[Song alloc]init];
[chapter setPage:(NSString *)self.chaptersRange[i]];
[chapter setTitle:(NSString *)self.chapters[i]];
[self.allChapters addObject:chapter];
[self.songs addObject:chapter];
}
NSString *filePath;
int i;
for (i = 0; i < files.count; i++) {
filePath = [[NSBundle mainBundle] pathForResource:files[i] ofType:#"txt"];
if(filePath){
NSError *error;
NSString *textFromfile = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error: &error];
/*
index
0 for page number
1 for title name
2 for melody name
3 -> for lyrics
*/
NSMutableArray *newLineseparatedText = (NSMutableArray *)[textFromfile componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
if(newLineseparatedText){
Song *newSong = [[Song alloc]init];
[newSong setPage:newLineseparatedText[0]];
[newSong setTitle:newLineseparatedText[1]];
[newSong setMelody:newLineseparatedText[2]];
[newLineseparatedText removeObjectAtIndex:0]; //remove page number
[newLineseparatedText removeObjectAtIndex:0]; //remove title name
[newLineseparatedText removeObjectAtIndex:0]; //remove melody name
[newSong setLyric:[newLineseparatedText componentsJoinedByString:#"\n"]];
[songs addObject:newSong];
}
}
}
[self.songs sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[super viewDidLoad];
}
-(void)addChapters{
for(int i = 0; i < self.allChapters.count; i++){
if([self.songs containsObject:self.allChapters[i]] == false)
[self.songs addObject:self.allChapters[i]];
}
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey: #"page" ascending: YES];
[self.songs sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
}
-(void)addChapters{
for(int i = 0; i < self.allChapters.count; i++){
if([self.songs containsObject:self.allChapters[i]] == false)
[self.songs addObject:self.allChapters[i]];
}
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey: #"page" ascending: YES];
[self.songs sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
}
-(void)removeChaptersExcept:(Song *) chapter{
for(int i = 0; i < self.allChapters.count; i++){
if(self.allChapters[i] != chapter && [self.songs containsObject:self.allChapters[i]])
[self.songs removeObject:self.allChapters[i]];
}
}
last line of this code is were i get an error, as the mutableArray has a couple of nil elements.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.chosenChapter isEqualToString:#"Alla"]){
[self addChapters];
}
else{
Song *chapter = nil;
for(int i = 0; i < self.allChapters.count; i++){
if([((Song *)self.allChapters[i]).title isEqualToString:self.chosenChapter]){
chapter = self.allChapters[i];
break;
}
}
[self addChapters];
[self removeChaptersExcept:chapter];
}
NSString *cellIdentifier = nil;
UITableViewCell *cell = nil;
NSString *page = ((Song *)self.songs[indexPath.row]).page;
and here are some screen bumps
This is before removing first object
This is after the first object was removed. You see how one element disapeared as expected and the other is set too nil?
Sometimes the Variables View shows incorrect values.
An array can't contain nil values, so this is definitely a case where the values are wrong.
You state that your application crashes on this line:
NSString *page = ((Song *)self.songs[indexPath.row]).page;
My guess is that self.songs[indexPath.row] simply doesn't have a property called page.
Try to replace this line with this code:
Song *s = self.songs[indexPath.row];
if (s == nil)
{
NSLog("Song is nil! How can that be?");
}
else
{
NSLog("Page is %#", s.page);
}
It will help you pin-point the problem. Good luck.

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)

How to return arrays object + count IOS

hi at all ,I've this code :
+(NSArray *)splatterUrls
{
NSString *jsonString = [ ApiMethod jsonOfStores];
NSDictionary *results =[jsonString objectFromJSONString];
NSArray *movieArray = [results objectForKey:#"Seasons"];
//int i=0;
// Search for year to match
for (NSDictionary *movie in movieArray)
{
NSNumber *idSplatterMovie = [movie objectForKey:#"Id"];
// NSLog(#" %#", idSplatterMovie );
NSArray *try = [movie objectForKey:#"Episodes"];
// NSLog(#"%#", try);
for (NSDictionary *op in try)
{
if([idSplatterMovie integerValue] == 46)
{
//i++;
NSArray *movieArrayString = [op objectForKey:#"Url"];
// NSLog(#" %#", movieArrayString);
return movieArrayString;
}
}
}
}
I want to return movieArrayString with all his objects and how many object contains in it. I think that I should use this method : + (id)arrayWithObjects:(const id *)objects count:(NSUInteger)count. It's possible? If yes, can you tell me how can use it?
Thank you so much!
by the way , i have to call splatterUrls method and implement in home.m that it is :
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *urlSplatter= [GetSplatterUrlsMovie splatterUrls];
NSLog(#" %#", urlSplatter);
}
Looks good as it is to me.
Do this to return your movies array, array will be equal to your movies array:
NSArray *array = [self splatterUrls];
Then to get the count/number of objects in your array do this, i is equal to the number of objects in the array:
int i = [array count];
What is the problem ??
You return a NSarray ... call the method count on your NSarray object!