I was using this example for searching through a UICollectionView: https://github.com/ihomam/CollectionViewWithSearchBar/blob/master/collevtionViewWithSearchBar/CollectionViewController.m
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
// Configure the cell
if (self.searchBarActive) {
cell.laName.text = self.dataSourceForSearchResult[indexPath.row];
} else {
cell.laName.text = self.dataSource[indexPath.row];
}
return cell;
}
...only my app is setup a little differently:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
PlaceCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
Place *p = [_entries objectAtIndex:indexPath.item];
if (self.searchBarActive) {
cell.placeName.text = self.dataSourceForSearchResult[indexPath.item];
} else {
cell.placeName.text = p.PName;
cell.placeImg.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:p.PImage]]];
}
return cell;
}
So if I just run it the way it is then self.dataSourceForSearchResult[indexpath.item] will return EVERYTHING and I get an error because it's not returning a string...
'Can't use in/contains operator with collection <Place: 0x17d8ad70> (not a collection)'
but what I want it to do is search through the p.PName results. Something like:
self.dataSourceForSearchResult[p.PName indexpath.item]
Having looked through the github code I think that the core of your problem lies somewhere else.
The problem lies here :
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"self contains[c] %@", searchText];
self.dataSourceForSearchResult = [self.dataSource filteredArrayUsingPredicate:resultPredicate];
}
What this method does is it filters matching items from self.datasource
(which I assume you renamed to self.entries
, and I hope you also did it here) based on the predicate. The predicate is a little tricky to understand, especially if you have no previous experience with them. Let's break it down :
self
- in this context it means the object that will be checked against the condition. This object will be an element of the array.
contains[c]
- this is the condition. The self
will be checked if it contains
something. The [c]
means that the check will be case insensitive.
%@
- this is the 'something'. It will be replaced with searchText
.
This worked in the example because the array contained NSString
objects and NSPredicate
knows how to check if they contain
something (a substring). Since your array consists of Place
objects the NSPredicate
doesn't know how to check if they contain
something (a subplace? :P).
To fix this replace the predicate with this one self.PName contains[c] %@
. This one will acces the PName
property of each object of array and check whether it contains the substring.
You can read more on NSPredicate on NSHipster and in the docs
As to the second problem, self.dataSourceForSearchResult[indexpath.item]
will not in fact return an NSString
but a Place
object, though not EVERYTHING
, but one of the filtered ones. It was actually never reached in your app, as it crashed earlier. No offence, but I think that you don't entirely understand the whole order of things in this code. To break it down :
- The view controller is shown and the searchbar is empty so the cells are drawn, based on data in
self.datasource
(or self.entries
as you renamed it). collectionView:cellForItemAtIndexPath:
is being called.
- User inputs something in the search bar. (this triggers
searchBar:textDidChange:
).
- The matching objects are filtered into
self.dataSourceForSearchResult
array.
- The collection view gets reloaded.
- The cells are redrawn (
collectionView:cellForItemAtIndexPath:
is being called again), but since the searchbar is not empty, we now use only objects from self.dataSourceForSearchResult
.
So to make it work your - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
should look like this :
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
PlaceCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
Place *p;
// retrieve item from appropriate array
if (self.searchBarActive) {
p = self.dataSourceForSearchResult[indexPath.item];
} else {
p = self.entries[indexPath.item];
}
// populate the cell - we do this regardless of whether the searchbar is active or not
cell.placeName.text = p.PName;
cell.placeImg.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:p.PImage]]];
return cell;
}