I'm querying from parse and I when I try to search using the search bar it returns with "no results." I'm trying to figure out what I did wrong showing the objects because it does show in the NSLog that it has found objects.
My viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
self.tableView.tableHeaderView = self.searchBar;
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
self.searchController.delegate = self;
self.searchResults = [NSMutableArray array];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
The Retrieving for the Table View:
-(void)filterResults:(NSString *)searchTerm {
[self.searchResults removeAllObjects];
PFQuery *query = [PFQuery queryWithClassName:#"New"];
[query whereKeyExists:#"title"]; //this is based on whatever query you are trying to accomplish
[query whereKey:#"title" containsString:searchTerm];
NSArray *results = [query findObjects];
NSLog(#"%u", results.count);
[self.searchResults addObjectsFromArray:results];
}
Finally, The tableview cell that doesn't want to work:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFObject * testObject = [self.searchResults objectAtIndex:indexPath.row];
cell.textLabel.text = [testObject objectForKey:#"title"];
return cell;
}
Then:
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterResults:searchString];
return YES;
}
Then to load from Parse to UTTableview:
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithClassName:#"New"];
self = [super initWithCoder:aDecoder];
if (self) {
// The className to query on
self.ClassName = #"New";
//self.textKey = #"title";
// The key of the PFObject to display in the label of the default cell style
// self.keyToDisplay = #"text";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = NO;
// Whether the built-in pagination is enabled
self.paginationEnabled = YES;
self.loadingViewEnabled = NO;
// The number of objects to show per page
self.objectsPerPage = 50;
}
return self;
}
You can use another way where you can take the help of the search bar delegate method.
e.g - Include UISearchBarDelegate in your header file and also -
#property (strong, nonatomic) IBOutlet UISearchBar *searchSong;
Now in your .m file
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
NSMutableArray *temp = [[NSMutableArray alloc] init];
temp = [self searchSongsData:self.searchSong.text from:`YourArray`];
}
+ (NSMutableArray *) searchSongsData:(NSString *)searchtext from:(NSMutableArray *)array
{
NSMutableArray *arrayToBeReturned = [[NSMutableArray alloc] init];
NSArray *temp = [[NSArray alloc] initWithArray:array];
NSString *textToBeSearch = [searchtext lowercaseString];
SongsMoviesData *songs;
for(int i = 0; i<temp.count; i++)
{
songs = [temp objectAtIndex:i];
NSString *string1 = [songs.song_title lowercaseString];
NSString *string2 = [songs.moview_name lowercaseString];
NSString *string3 = [songs.singer_name lowercaseString];
if ([string1 rangeOfString:textToBeSearch].location != NSNotFound ||[string2 rangeOfString:textToBeSearch].location != NSNotFound || [string3 rangeOfString:textToBeSearch].location != NSNotFound)
{
// NSLog(#"%#", songs.moview_name);
[arrayToBeReturned addObject:songs];
}
}
return arrayToBeReturned;
}
and like this you save this array in your search results.
Related
I have a UITableView I add as a subview of self.view and it crashes at
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
Here is my code:
interface (in CRFeedViewController.m)
#property (assign) BOOL dataIsLoaded;
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(dataIsLoaded == YES)
{
return [self.items count];
}
else {
return 1;
}
}
// Return a cell for the index path
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Cell label
cell.textLabel.text = #"Tweet";
if (cell == nil) {
cell = [[UITableViewCell alloc] init];
}
return cell;
}
- (void)getTimeLine {
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[account requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
if (granted == YES)
{
NSArray *arrayOfAccounts = [account accountsWithAccountType:accountType];
if ([arrayOfAccounts count] > 0)
{
ACAccount *twitterAccount = [arrayOfAccounts lastObject];
NSURL *requestURL = [NSURL URLWithString:#"http://api.twitter.com/1/statuses/home_timeline.json"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
[parameters setObject:#"20" forKey:#"count"];
[parameters setObject:#"1" forKey:#"include_entities"];
SLRequest *postRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:requestURL parameters:parameters];
postRequest.account = twitterAccount;
[postRequest performRequestWithHandler: ^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
self.items = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&error];
if (self.items.count != 0) {
dataIsLoaded = YES;
[self.tableView reloadData];
}
else {
NSLog(#"No items");
}
}];
}
} else {
NSLog(#"No access");
}
}];
}
- (void) viewWillAppear:(BOOL)animated
{
[self getTimeLine];
}
- (void)viewDidLoad
{
[super viewDidLoad];
/**
* TABLE VIEW
* Add subview of the table
*/
self.items = [NSArray arrayWithObjects:#"test", nil];
CGRect tableViewRect = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
UITableView *tableView = [[UITableView alloc] initWithFrame:tableViewRect style:UITableViewStylePlain];
tableView.dataSource = self;
[self.view addSubview:tableView];
}
EDIT
Here is my complete code, I'm sorry I don't understand all of this yet, I am still very new.
.h
//
// CRFeedViewController.h
// Twitter
//
// Created by Cody Robertson on 6/27/13.
// Copyright (c) 2013 Cody Robertson. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <Accounts/Accounts.h>
#import <Social/Social.h>
#interface CRFeedViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (strong, nonatomic) UITableView *tableView;
#property (strong, nonatomic) NSArray *items;
#end
.m
//
// CRFeedViewController.m
// Twitter
//
// Created by Cody Robertson on 6/27/13.
// Copyright (c) 2013 Cody Robertson. All rights reserved.
//
#import "CRFeedViewController.h"
#import "CRComposeViewController.h"
#import "CRSearchViewController.h"
#interface CRFeedViewController ()
#property (assign) BOOL dataIsLoaded;
- (void) composeTweet: (id) sender;
- (void) searchTweets: (id) sender;
- (void) getTimeLine;
#end
#implementation CRFeedViewController
#synthesize dataIsLoaded;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
/**
* NAV BAR
* Add icon and button to nav bar
*/
// Add Twitter Icon as Title
UIImageView *UINavTitleLogo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"UINavBarLogo.png"]];
UINavTitleLogo.contentMode = UIViewContentModeScaleAspectFill;
self.navigationItem.titleView = UINavTitleLogo;
// Add Search & Compose Icon
UIImage *UISearchNavButton = [UIImage imageNamed:#"Search.png"];
UIBarButtonItem *CRSearchNavButton = [[UIBarButtonItem alloc] initWithImage:UISearchNavButton style:UIBarButtonItemStylePlain target:self action:#selector(searchTweets:)];
UIImage *UIComposeNavButton = [UIImage imageNamed:#"Compose.png"];
UIBarButtonItem *CRComposeNavButton = [[UIBarButtonItem alloc] initWithImage:UIComposeNavButton style:UIBarButtonItemStylePlain target:self action:#selector(composeTweet:)];
NSArray *UINavItems = #[CRComposeNavButton, CRSearchNavButton];
self.navigationItem.rightBarButtonItems = UINavItems;
[[UINavigationBar appearance] setTitleTextAttributes:#{
UITextAttributeTextColor: [UIColor whiteColor]
}];
/**
* TAB BAR
* Add icon and label to task bar
*/
UIImage *CRFeedTabBarIcon = [UIImage imageNamed:#"Home.png"];
UITabBarItem *CRFeedTabBarItem = [[UITabBarItem alloc] initWithTitle:#"Home" image:CRFeedTabBarIcon tag:0];
self.tabBarItem = CRFeedTabBarItem;
}
return self;
}
- (void) composeTweet:(id)sender
{
/**
* PUSH VIEW TO COMPOSE
* Load the compose view
*/
CRComposeViewController *CRCompose = [[CRComposeViewController alloc] init];
CRCompose.title = #"New Tweet";
[self.navigationController pushViewController:CRCompose animated:YES];
}
- (void) searchTweets:(id)sender
{
/**
* PUSH VIEW TO SEARCH
* Load the search view
*/
CRSearchViewController *CRSearch = [[CRSearchViewController alloc] init];
CRSearch.title = #"Search";
[self.navigationController pushViewController:CRSearch animated:YES];
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(dataIsLoaded == YES)
{
return [self.items count];
}
else {
return 1;
}
}
// Return a cell for the index path
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Cell label
cell.textLabel.text = #"Tweet";
if (cell == nil) {
cell = [[UITableViewCell alloc] init];
}
return cell;
}
- (void)getTimeLine {
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[account requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
if (granted == YES)
{
NSArray *arrayOfAccounts = [account accountsWithAccountType:accountType];
if ([arrayOfAccounts count] > 0)
{
ACAccount *twitterAccount = [arrayOfAccounts lastObject];
NSURL *requestURL = [NSURL URLWithString:#"http://api.twitter.com/1/statuses/home_timeline.json"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
[parameters setObject:#"20" forKey:#"count"];
[parameters setObject:#"1" forKey:#"include_entities"];
SLRequest *postRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:requestURL parameters:parameters];
postRequest.account = twitterAccount;
[postRequest performRequestWithHandler: ^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
self.items = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&error];
if (self.items.count != 0) {
dataIsLoaded = YES;
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
}
else {
NSLog(#"No items");
}
}];
}
} else {
NSLog(#"No access");
}
}];
}
- (void) viewWillAppear:(BOOL)animated
{
[self getTimeLine];
}
- (void)viewDidLoad
{
[super viewDidLoad];
/**
* TABLE VIEW
* Add subview of the table
*/
self.items = [NSArray arrayWithObjects:#"test", nil];
CGRect tableViewRect = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
UITableView *tableView = [[UITableView alloc] initWithFrame:tableViewRect style:UITableViewStylePlain];
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You should call the reloadData method on the main thread:
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
Not sure if this is causing your crash, but you need to init your cells with the reuse identifier:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;
I would recommend that you post the trace logged in Xcode when the app crashes. It will give a better understanding as to why your app is crashing.
Add the delegate first so those methods are ran. Don't forget to subscribe to the delegate in your .h as well.
ViewController.h
#interface ViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>
#property (nonatomic, strong) NSArray *items;
// In your viewDidLoad
tableView.dataSource = self;
tableView.delegate = self;
You return 1 cell even if you don't have data. You should return 0
If the error is happening in the numberOfRows method, then the culprit is most likely:
[self.items count];
The most likely case this causes an error is if self.items does not have a count method. In your viewDidLoad, you set it to an NSArray, which does have a count method. However, there is one other place you set self.items:
self.items = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&error];
The result of that method most likely does not have a count method, and therefore is not an NSArray, yet you are storing it in a variable that is defined as NSArray.
After that line, above, put the following code:
NSLog(#"Class: %#", NSStringFromClass([self.items class]));
If the output is not NSArray, you most likely have a programming error.
Also, it looks like you are using multiple threads, to read/write to the same variable. This is usually not a good idea without implementing some sort of thread safety on those properties.
I have a subview in which I build a UITableview, I've set the delegate and datasource to the subview but for some reason the table methods are not being called...can someone look over my code and see what I am doing wrong? Thanks
.h file
#interface TwitterController : UIView <UITableViewDelegate, UITableViewDataSource> {
UIButton* btnCloseView;
UITableView* tblTweets;
UIImageView* imgTwitterIcon;
ColorController* colorManager;
NSMutableArray* tweetsArray;
NSMutableArray* tableData;
NSString* twitterID;
}
#property (nonatomic, retain) NSString* twitterID;
- (NSMutableArray* ) getTweets;
- (void) sendNotification : (id) sender;
#end
.m file
#import "TwitterController.h"
#implementation TwitterController
#synthesize twitterID;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
colorManager = [ColorController new];
}
return self;
}
/*- (void)drawRect:(CGRect)rect {
}*/
- (void)layoutSubviews {
imgTwitterIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"imgTwitterBird"]];
CGRect twitterIconFrame = [imgTwitterIcon frame];
twitterIconFrame.origin.x = 50.0;
twitterIconFrame.origin.y = 20.0;
tblTweets = [[UITableView alloc] initWithFrame:CGRectMake(50.0, 25.0, 220.0, 500.0)];
tblTweets.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
tblTweets.separatorColor = [colorManager setColor:176.0:196.0:222.0];
tblTweets.layer.borderWidth = 1.0;
tblTweets.rowHeight = 20.0;
tblTweets.scrollEnabled = YES;
tblTweets.delegate = self;
tblTweets.dataSource = self;
tableData = [self getTweets];
UIImage* imgCloseButton = [UIImage imageNamed:#"btnCloseWindow.png"];
CGSize imageSize = imgCloseButton.size;
btnCloseView = [[UIButton alloc] initWithFrame: CGRectMake(220.0, 550.0, imageSize.width, imageSize.height)];
[btnCloseView setImage:[UIImage imageNamed:#"btnCloseWindow.png"] forState:UIControlStateNormal];
[btnCloseView addTarget:self action:#selector(sendNotification:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:tblTweets];
[self addSubview:imgTwitterIcon];
[self addSubview:btnCloseView];
}
- (NSMutableArray*) getTweets {
//array to hold tweets
tweetsArray = [[NSMutableArray alloc] init];
twitterID = #"Pruit_Igoe";
///set up a NSURL to the twitter API
NSURL* twitterAPI = [NSURL URLWithString:[NSString stringWithFormat:#"https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name=%#&count=10", twitterID]];
//get last 10 tweets (max is 20)
TWRequest *twitterRequest = [[TWRequest alloc] initWithURL:twitterAPI
parameters:nil requestMethod:TWRequestMethodGET];
// Notice this is a block, it is the handler to process the response
[twitterRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if ([urlResponse statusCode] == 200) {
// The response from Twitter is in JSON format
// Move the response into a dictionary and print
NSError *error;
NSDictionary *tweetsDict = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
for(NSDictionary* thisTweetDict in tweetsDict) {
[tweetsArray addObject:[thisTweetDict objectForKey:#"text"]];
}
}
else
NSLog(#"Twitter error, HTTP response: %i", [urlResponse statusCode]);
}];
return tweetsArray;
}
#pragma mark Table Management
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [tableData count];
NSLog(#"%i", [tableData count]); //does not log!
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"tableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.textColor = [UIColor colorWithRed:66.0/255.0 green:66.0/255.0 blue:66.0/255.0 alpha:1];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size: 13.0];
cell.textLabel.text = [tweetsArray objectAtIndex:indexPath.row];
CGRect cellFrame = [cell frame];
cellFrame.size.height = 25.0;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString* thisTweet = [tableData objectAtIndex:indexPath.row];
}
#pragma mark Close Window
- (void) sendNotification : (id) sender {
NSMutableDictionary* userData = [[NSMutableDictionary alloc] init];
[userData setObject:#"closeTwitter" forKey:#"theEvent"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"theMessenger" object:self userInfo: userData];
}
#end
I think you are not allocate and initialize tableData. Write it tableData = [[NSMutableArray alloc] init]; in - (id)initWithFrame:(CGRect)frame method or - (void)layoutSubviews method. Just try it.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSLog(#"%i", [tableData count]);
return [tableData count];
//NSLog(#"%i", [tableData count]); //does not log!
}
If the output is zero, tableData array is empty. Check it tableData array
You should do all the initialization (tblTweets for example) in initWithFrame:.
layoutSubviews is ment for laying out subviews.
In fact your code will (should) work if you move all the code fromLayoutSubviews to initWithFrame:. You can then move parts of the code (the laying out part) back.
EDIT: when you move initializing code you will probably also have to add [tblTweets reloadData]; right after tableData = [self getTweets];
I have an NSArray that contains a couple of items. The NSArray is loaded into a uitableview from another class. when I back out of the detail view and re-enter (for the 3rd time), the NSArray is empty and the tableview is empty as well. What is happening? (I am using arc so I don't think it is a leak)
- (void)viewDidLoad {
myMatch = [[Match alloc] initWithId:1 OpponentId:13];
}
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *askCellIdent = #"askCell";
static NSString *answerCellIdent = #"answerCell";
if (indexPath.row == 0)
{
AskCell *cell = [tv dequeueReusableCellWithIdentifier:askCellIdent];
if (cell==nil) {
cell = [[AskCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:askCellIdent];
}
cell.nameLabel.text = #"Albert asked:";
cell.questionLabel.text = [NSString stringWithFormat:#"%#", [[myMatch.chat objectAtIndex:indexPath.row] objectAtIndex:1]];
return cell;
}
if (indexPath.row == 1)
{
AnswerCell *cell = [tv dequeueReusableCellWithIdentifier:answerCellIdent];
if (cell==nil) {
cell = [[AnswerCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:answerCellIdent];
}
cell.nameLabel.text = #"Hugh answered:";
cell.answerLabel.text = [NSString stringWithFormat:#"%#", [[myMatch.chat objectAtIndex:indexPath.row] objectAtIndex:1]];
return cell;
}
}
Here is the init code of the my match class:
- (id) initWithId:(NSInteger)yourId OpponentId:(NSInteger)opId {
self = [super init];
if (self != nil) {
//set your id and opponents id to the match.
[self setUserId:yourId];
[self setUserId:opId];
JSON = #"[{\"opponentId\":\"4\",\"chat\":[[\"1\",\"Does he have a beard?\"],[\"1\",\"No.\"]]}]";
//initiate the chat array.
chat = [[NSMutableArray alloc] init ];
[self loadMatch];
}
return self;
}
and here is the chat property/synthesize
NSMutableArray *chat;
#property (nonatomic, retain) NSMutableArray *chat;
#synthesize chat;
No idea whats going on, because the slog of the array is empty too!
Declare an int varable repeatCount in appDelegate
- (void)viewDidLoad
{
[super viewDidLoad];
ypurAppDelegate *appDelegate = (yourAppDelegate *)[[UIApplication sharedApplication] elegate];
appDelegate.repeatCount++;
if(appDelegate.repeatCount %3==0)
{
[array removeAllObjects];
[tableview reloaddata];
}
}
Use self.chat = [[[NSMutableArray alloc] init ]autorelease]; to initialize your array
Instead ViewDidLoad, allocate the object in initWithCoder.
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if( self )
{
myMatch = [[Match alloc] initWithId:1 OpponentId:13];
}
return self;
}
I think it's a problem with the populating the NSMutableArray as only once will viewDidLoad will be called. You should insert values into array in viewWillAppear Method or initiate the match class in initWithCoder.
I have data like this...(All the data comes from .plist file...)
Searching Array - (
{
FirstName = "Ramesh";
LastName = "Bean";
EmpCode = 1001;
},
{
FirstName = "Rohan";
LastName = "Rathor";
EmpCode = 102;
},
{
FirstName = "Priya";
LastName = "Malhotra";
EmpCode = 103;
},
{
FirstName = "Mukesh";
LastName = "Sen";
EmpCode = 104;
},
{
FirstName = "Priya";
LastName = "Datta";
EmpCode = 105;
}
)
I want implement search data from this array on the basis of FirstName (key).
I am able to search data with the "FirstName(Key)"
but after filtering data suppose i clicked Row( in the data) which is displayed in the TableView. It Navigate me to New-Controller with all the information of that particular employee (like: FirstName,LastName,EmpCode).
How can i get information?
As i gone through the search sample codes.
Here is my search code...
NSString *searchText = searchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
NSInteger TotalNoOfRecords=[self.SearchtableDataSource count];
for (int i=0;i<TotalNoOfRecords;i++)
{ NSDictionary *dictionary = [self.SearchtableDataSource objectAtIndex:i];
NSArray *array = [dictionary objectForKey:#"FirstName"];
[searchArray addObject:array];
}
for (NSString *sTemp in searchArray)
{
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
{
[copyListOfItems addObject:sTemp];
}
}
How can i improve this code?....Please guide me... [searchArray release]; searchArray = nil;
How we maintain all the "Keys(FirstName,LastName,EmpCode)" in the searchArray please help me out? Thanks...
I think the best approach would be to make an array of NSDictionary which has value for three keys namely "FirstName", "LastName", "EmpCode"
now to filter the data according to "FirstName" use NSPredicate instead of for loop,
NSString *searchText = searchBar.text;
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"FirstName like[cd] %#",searchText];
NSArray* filteredArray = [self.SearchtableDataSource filteredArrayUsingPredicate:predicate];
In method cellForRowAtIndexPath
NSDictionary* currentEmp = [filteredArray objectAtIndex:inddexPath.row];
display the information in this currentEmp.
Similarly in didSelectRowAtIndexPath
NSDictionary* currentEmp = [filteredArray objectAtIndex:inddexPath.row];
and pass this dictionary in the next ViewController in which u want to dispaly the detail of the current employ.
if u have two table views one that of searchDisplayController (showing the filtered result)
and one which is showing the whole result, then u can track this by having a BOOL variable tacking that is if filtering is active or not.
Here is what i have done and its working fine with me(tested it). I have taken one IBOutlet of UISearchBar so here is the code for ur .h file
#interface SearchForEmp : UIViewController<'UISearchDisplayDelegate,UISearchBarDelegate,UITableViewDelegate,UITableViewDataSource> {
IBOutlet UISearchBar* mySearchBar;
UISearchDisplayController* mySearchDisplayController;
NSMutableArray* allEmp;
NSMutableArray* filteredEmp;
BOOL isFilatering;
}
#end
Now in .m file
-(void)viewDidLoad
{
[super viewDidLoad];
mySearchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:mySearchBar contentsController:self];
mySearchDisplayController.searchResultsDelegate = self;
mySearchDisplayController.searchResultsDataSource = self;
mySearchDisplayController.delegate = self;
isFilatering = NO;
filteredEmp = [[NSMutableArray alloc] init];
allEmp = [[NSMutableArray alloc] init];
NSDictionary *temp;
for (int i = 0; i < 30; i++) {
temp = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:#"FirstName_%d",i],#"FirstName",[NSString stringWithFormat:#"LastName_%d",i],#"LastName",[NSNumber numberWithInt:1000+i],#"EmpCode",nil];
[allEmp addObject:temp];
}
}
for e.g purpose i have thake an array of 30 Dictionaries, each with a unique name.For table view data source and delegate .....
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (isFilatering) {
return [filteredEmp count];
}
else {
return [allEmp count];
}
return [allEmp count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] init] autorelease];
}
NSDictionary* temp;
if (isFilatering) {
temp = [filteredEmp objectAtIndex:indexPath.row];
}
else {
temp = [allEmp objectAtIndex:indexPath.row];
}
cell.textLabel.text = [NSString stringWithFormat:#"%# %#",[temp objectForKey:#"FirstName"],[temp objectForKey:#"LastName"]];
return cell;
}
Now as far as searching is concerned here is what u need to do .......
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
NSPredicate* predicate = [[NSPredicate predicateWithFormat:#"self.FirstName contains %#",mySearchBar.text] retain];
filteredEmp = [[allEmp filteredArrayUsingPredicate:predicate] retain];
}
-(void) searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
isFilatering = YES;
}
-(void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller
{
isFilatering = NO;
}
I hope that helps you understanding the things, dont forget to add retain in line
filteredEmp = [[allEmp filteredArrayUsingPredicate:predicate] retain];
because method filteredArrayUsingPredicate: is an accessor method and its retain count is handled by the NSArray so have access to the filtered array u need to pass a retain msg to it.
I have a question about adding XML to the searchbar in a tableview. I can get all the external XML file to load in the tableview, but when I hit the searchbar up top, and hit a letter, it crashes.
I think it's something really simple that I'm doing wrong. In my RootViewController, there's a function called searchTableView. I feel like that's where it's not picking up the search items. I think it's somewhere around the objectForKey:#"title". When I debug, I get this error message also: "NSCFArray objectForKey unrecognized selector". Here's my searchTableView function:
- (void) searchTableView {
NSString *searchText = searchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
for (NSDictionary *dictionary in listOfItems)
{
NSArray *array = [dictionary objectForKey:#"title"];
[searchArray addObjectsFromArray:array];
}
for (NSString *sTemp in searchArray)
{
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
[copyListOfItems addObject:sTemp];
}
[searchArray release];
searchArray = nil;
}
Ok figured it out. For some reason this was really hard to find documentation how to do this.
Here's my RootViewController.m below.
My pList is configured as:
Root (Array)
Item0 (Dictionary)
Name (String)
Item1 (Dictionary)
Name (String)..
Here's my code, hopefully this helps anyone else looking for help on this:
#implementation RootViewController
#synthesize listOfItems, copyListOfItems;
- (void)viewDidLoad {
[super viewDidLoad];
//Initialize the array.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"plistArray" ofType:#"plist"];
NSMutableArray* tmpArray = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
self.listOfItems = tmpArray;
[tmpArray release];
//Initialize the copy array.
copyListOfItems = [[NSMutableArray alloc] init];
//Set the title
self.navigationItem.title = #"Search";
//Add the search bar
self.tableView.tableHeaderView = searchBar;
searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
searching = NO;
letUserSelectRow = YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (searching)
return 1;
else
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (searching)
return [copyListOfItems count];
else {
//Number of rows it should expect should be based on the section
return [listOfItems count];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//Get the selected country
NSString *selectedCountry = nil;
if(searching)
selectedCountry = [copyListOfItems objectAtIndex:indexPath.row];
else {
// Navigation logic may go here. Create and push another view controller.
}
NSDictionary *dictionary = [self.listOfItems objectAtIndex:indexPath.row];
FoodDetail *dvController = [[FoodDetail alloc] initWithNibName:#"FoodDetail" bundle:nil andDictionary: dictionary];
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:dvController animated:YES];
[dvController release];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
if(searching)
cell.textLabel.text = [copyListOfItems objectAtIndex:indexPath.row];
else {
cell.textLabel.text = [[self.listOfItems objectAtIndex:indexPath.row]
objectForKey:#"Name"];
}
return cell;
}
- (NSIndexPath *)tableView :(UITableView *)theTableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(letUserSelectRow)
return indexPath;
else
return nil;
}
#pragma mark -
#pragma mark Search Bar
- (void) searchBarTextDidBeginEditing:(UISearchBar *)theSearchBar {
//This method is called again when the user clicks back from the detail view.
//So the overlay is displayed on the results, which is something we do not want to happen.
if(searching)
return;
//Add the overlay view.
if(ovController == nil)
ovController = [[OverlayViewController alloc] initWithNibName:#"OverlayView" bundle:[NSBundle mainBundle]];
CGFloat yaxis = self.navigationController.navigationBar.frame.size.height;
CGFloat width = self.view.frame.size.width;
CGFloat height = self.view.frame.size.height;
//Parameters x = origion on x-axis, y = origon on y-axis.
CGRect frame = CGRectMake(0, yaxis, width, height);
ovController.view.frame = frame;
ovController.view.backgroundColor = [UIColor grayColor];
ovController.view.alpha = 0.5;
ovController.rvController = self;
[self.tableView insertSubview:ovController.view aboveSubview:self.parentViewController.view];
searching = YES;
letUserSelectRow = NO;
self.tableView.scrollEnabled = NO;
//Add the done button.
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self action:#selector(doneSearching_Clicked:)] autorelease];
}
- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText {
//Remove all objects first.
[copyListOfItems removeAllObjects];
if([searchText length] > 0) {
[ovController.view removeFromSuperview];
searching = YES;
letUserSelectRow = YES;
self.tableView.scrollEnabled = YES;
[self searchTableView];
}
else {
[self.tableView insertSubview:ovController.view aboveSubview:self.parentViewController.view];
searching = NO;
letUserSelectRow = NO;
self.tableView.scrollEnabled = NO;
}
[self.tableView reloadData];
}
- (void) searchBarSearchButtonClicked:(UISearchBar *)theSearchBar {
[self searchTableView];
}
- (void) searchTableView {
NSString *searchText = searchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
for (NSDictionary *dictionary in listOfItems)
{
NSString *text1 = [dictionary objectForKey:#"Name"];
[searchArray addObject:text1];
}
NSLog(#"%s: searchArray=%#", __func__, searchArray);
for (NSString *sTemp in searchArray)
{
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
[copyListOfItems addObject:sTemp];
}
[searchArray release];
searchArray = nil;
}
- (void) doneSearching_Clicked:(id)sender {
searchBar.text = #"";
[searchBar resignFirstResponder];
letUserSelectRow = YES;
searching = NO;
self.navigationItem.rightBarButtonItem = nil;
self.tableView.scrollEnabled = YES;
[ovController.view removeFromSuperview];
[ovController release];
ovController = nil;
[self.tableView reloadData];
}
- (void)dealloc {
[ovController release];
[copyListOfItems release];
[searchBar release];
[listOfItems release];
[super dealloc];
}
#end