I create the UISearchController in ViewDidLoad
//create the search controller
self.searchController = [[UISearchController alloc]initWithSearchResultsController:nil];
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchResultsUpdater = self;
self.searchController.delegate = self;
self.definesPresentationContext = YES;
[self.searchBarHolder addSubview: self.searchController.searchBar];
self.searchController.searchBar.delegate = self;
when the users clicks the CANCEL button the following delegate method is called.
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
self.searchController.active = NO;
self.myTableView.hidden = YES;
self.transparentViewSearch.hidden = YES;
}
The line self.searchController.active=NO navigates the user back to the previous view controller.
Additionally the line self.transparentViewSearch.hidden = YES does nothing. The view is still visible.
What is going on?
you are using same table for showing search result
self.searchController = [[UISearchController alloc]initWithSearchResultsController:nil];
You need to do update table after cancel search result.
[self.tableview reloadData];
then you need to do something like below.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(bShowSearchResult)
{
// return search result count
}
else
{
// return normal list count
}
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(bShowSearchResult)
{
// create cell using search result data
Data = [lstSearchResults objectAtIndex:indexPath.row];
//create cell
// return cell
}
else
{
Data = [lstFiles objectAtIndex:indexPath.row];
//create cell
// return cell
}
}
I think it will help to you
Related
I am building an app for downloading files from server, I have a NSTableViewController with custom cell with progess indicator in it, but i have a problem with drawing cells for each row/downloadable file. When i start downloading it seems the progress cell is just a copy of a first created cell and progress updating is a bit fuzzy and when i select multiple rows to download it displays only one progress on the last selected row. If anyone can help telling me where I did wrong?
Here is the code for drawing the cells in -(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row method:
if([identifier isEqualToString:#"status"]) {
if ([selectedIndexes count] >0) {
for (indexNumber in selectedIndexes) {
ProgressBarCell *statusCell = [tableView makeViewWithIdentifier:#"StatusCell" owner:self];
progressCellArray = [self populateArrayOfProgressBarCells:selectedIndexes with:statusCell];
if ([indexNumber integerValue] == row) {
if (downloadTask != nil) {
[statusCell.imageView
setImage:[NSImage imageNamed:#"downloading"]];
[statusCell.textField setStringValue:#"downloading"];
for (int i = 0; i < statusCell.progressBar.maxValue; i++) {
[statusCell.progressBar setDoubleValue:[self getProgressPercentageForRowIndex:[indexNumber integerValue]]];
[statusCell.progressBar displayIfNeeded];
[statusCell.progressBar setUsesThreadedAnimation:YES];
[statusCell.progressBar
startAnimation:statusCell.progressBar];
}
if (statusCell.progressBar.doubleValue == statusCell.progressBar.maxValue) {
[statusCell.textField setStringValue:#"downloaded"];
[statusCell.imageView setImage:[NSImage imageNamed:#"finishedDownload"]];
}
return statusCell;
}
return notSelectedStatusCell = statusCell;
}
}
}
return notSelectedStatusCell;
}
tableView:viewForTableColumn:row: doesn't draw. NSTableView asks the delegate for a cell view by calling tableView:viewForTableColumn:row:. The cell view is added as subview of the table view. Invisible cell views are reused. You can't return the same cell view for multiple rows. tableView:viewForTableColumn:row: should return a cell view for the row and do nothing else. The values of the subviews of the cell view are set. Example:
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
DownloadItem *item = self.data[row];
if ([tableColumn.identifier isEqualToString:#"status"]) {
StatusCellView *statusCell = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
statusCell.progressIndicator.doubleValue = item.progress;
if (item.finished) {
statusCell.textField.stringValue = #"downloaded";
statusCell.imageView.image = [NSImage imageNamed:NSImageNameMenuOnStateTemplate];
}
else
if (item.downloading) {
statusCell.textField.stringValue = #"downloading";
statusCell.imageView.image = [NSImage imageNamed:NSImageNameMenuMixedStateTemplate];
}
else {
statusCell.textField.stringValue = #"paused";
statusCell.imageView.image = nil;
}
return statusCell;
}
else {
NSTableCellView *cellView = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
cellView.textField.stringValue = item.title;
return cellView;
}
return nil;
}
Reload the cell when the values change and the cell view should be updated. Example:
NSInteger row = [self.data indexOfObjectIdenticalTo:item];
NSInteger column = [self.tableView columnWithIdentifier:#"status"];
[self.tableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:row] columnIndexes:[NSIndexSet indexSetWithIndex:column]];
I am trying to make chatting App in Objective-C.
In this I want to implement tagging like WhatsApp.
When the user enters a # in the group it should show the list of the group members.
I try to do but sometimes facing issue when entering backspace after for example "#xyz". I am not getting output as expected.
Can you show me some example or a tutorial which I can take as reference.
Try this Simply,
- (void)viewDidLoad {
[super viewDidLoad];
textViews.delegate = self;
namesArray = #[#"John",#"Mathew”,#“iOS”];
membersTable.hidden = true;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)textViewDidChange:(UITextView *)textView { // Delegate method called when any text is modified
if ([textViews.text isEqualToString: #""]) {
membersTable.hidden = true;
}else{
if ([[textView.text substringFromIndex: [textView.text length] - 1] isEqualToString:#"#"]) {
NSLog(#"Success");
membersTable.hidden = false;
}else{
membersTable.hidden = true;
}
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return namesArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [membersTable dequeueReusableCellWithIdentifier:#"cell"];
cell.textLabel.text =[namesArray objectAtIndex:indexPath.row];
return cell;
}
Members tableView will show when user entered "#" symbol in your textView then user can choose members by selecting tableView
how to reload the data in the table while scrolling?
If i have a url "http:.......&start=0&limit=50".
How to reload the data in table with incrementing the start and limit value with 50.
Can anyone find a solution for this?
You need to implement the load more functionality in the table view for this.In order to do so, you need to track the table view's index while it is scrolling once table reaches the last cell you can call the api with increased page number and add the new records to the array once you get the positive response from the api.
See the below code for more understanding.
Variable initialization
#interface ExampleListVC (){
BOOL hasNextPage,isLoadingNextPage;
int currentPage;
NSMutableArray *arrTableData;
}
#end
In viewDidLoad method
arrTableData = [[NSMutableArray alloc]init];
currentPage=-1;
hasNextPage = YES;
In tableView numberOfRowsInSection method
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int count = (int)arrTableData.count;
if (hasNextPage)
{
count++;
}
return count;
}
In cellForRowAtIndexPath method
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
if (indexPath.row<arrTableData.count)
{
//Load TableviewCell you intend to show
}
else
{
//Show loading cell
cell = [self loadingCell:indexPath];
if (!isLoadingNextPage)
{
[self fetchData];
}
}
return cell;
}
Loading Cell Code
-(UITableViewCell *) loadingCell :(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:nil];
cell.backgroundColor = [UIColor clearColor];
UIActivityIndicatorView *activityIndicatorView =[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activityIndicatorView.color = [UIColor blackColor];
activityIndicatorView.center = CGPointMake(self.tblView.center.x, cell.center.y);
[cell.contentView addSubview:activityIndicatorView];
[activityIndicatorView startAnimating];
cell.userInteractionEnabled = NO;
return cell;
}
Api call implementation
-(void)fetchData
{
isLoadingNextPage = YES;
if (currentPage==-1)
currentPage=0;
//API Call
{
DLog(#"API Call Response = %#",response);
isLoadingNextPage = NO;
if (response == nil)
{
hasNextPage=NO;
return;
}
if (success)
{
if (hasNextPage)
{
currentPage++;
}
[arrTableData addObjectsFromArray:response];
}
else
{
hasNextPage=NO;
}
//Reload tableview
}];
}
Alternative solution for this is
Use the SVPullToRefresh library in integrate infinite scrolling of it.
https://github.com/samvermette/SVPullToRefresh
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if(self.comptabl.contentOffset.y >= (self.comptabl.contentSize.height - self.comptabl.bounds.size.height))
{
if(isPageRefreshing==NO){
isPageRefreshing=YES;
[appDelegate showIndicator:nil view1:self.view];
start=start+50;
[self makeRequest:start];
[self.comptabl reloadData];
NSLog(#"called %d",start);
}
}
}
I am using this method but at all time the value is increment with 50 ..how can i set limit to the value
I noticed one of my custom UITableViewCell is leaking. It is not getting released on performing edit, remove bottom cell and tap on Save. This is my top cell in the table (I call it add cell). Once my table view is in edit mode, Add cell is shown up with all the other cells shown underneath with delete mode on. Now, after performing the delete operation and saving the data, Add Cell still hang around even if dealloc on my table view gets called.
I am attaching my code and instrument screenshot (I've removed first line (Malloc call) from the screenshot. To me, it appears to be something wrong in iOS internal handling. Please advise.
- (UITableViewCell *)tableView:(UITableView *)iTableView cellForRowAtIndexPath:(NSIndexPath *)iIndexPath {
MyTableViewCell *aCell = nil;
NSString *aCellType;
if (iIndexPath.row == 0 && self.inEditMode) {
aCellType = kMyAddCell;
aCell = (MyAddCell *)[iTableView dequeueReusableCellWithIdentifier:aCellType];
if (!aCell) {
aCell = [[MyAddCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:aCellType];
}
aCell.isGroupedView = YES;
aCell.delegate = self;
aCell.textLabel.text = #“Add More";
self.tableView.allowsSelectionDuringEditing = YES;
} else {
aCellType = kMyDefaultCell;
aCell = (MyTableViewCell *)[iTableView dequeueReusableCellWithIdentifier:aCellType];
if (!aCell) {
aCell = [[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:aCellType];
}
NSInteger anIndex = iIndexPath.row;
if (self.inEditMode) {
anIndex = anIndex - 1;
}
aCell.textLabel.text = #“Name";
aCell.selectionStyle = UITableViewCellSelectionStyleNone;
}
return aCell;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)iIndexPath {
return (iIndexPath.row == 0 && self.inEditMode) ? UITableViewCellEditingStyleNone : UITableViewCellEditingStyleDelete;
}
- (BOOL)tableView:(UITableView *)iTableView canEditRowAtIndexPath:(NSIndexPath *)iIndexPath {
return YES;
}
- (void)tableView:(UITableView *)iTableView commitEditingStyle:(UITableViewCellEditingStyle)iEditingStyle forRowAtIndexPath:(NSIndexPath *)iIndexPath {
if (iEditingStyle == UITableViewCellEditingStyleDelete) {
[self setSaveModeNavigationBar];
[self.tableView beginUpdates];
[self.enabledUsers removeObjectAtIndex:(self.inEditMode) ? iIndexPath.row - 1 : iIndexPath.row];
[self.tableView deleteRowsAtIndexPaths:#[iIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
}
}
- (void)setEditing:(BOOL)iEditing animated:(BOOL)iAnimated {
[super setEditing:iEditing animated:iAnimated];
[self.navigationItem setHidesBackButton:YES animated:NO];
self.headerViewLabel.text = #“Edit Me";
UIBarButtonItem *aDoneButton = [[UIBarButtonItem alloc] initWithTitle:#“Done"
style:UIBarButtonItemStylePlain
target:self
action:#selector(cancelEditing)];
[self.navigationItem setRightBarButtonItem:aDoneButton];
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
self.inEditMode = YES;
[self.tableView reloadData];
}
Code that gets called once I tap on Save button:
self.requestHandler = [[MyRequestHandler alloc] initWithEndPoint:myEndPoint body:aPostBody successHandler:^(NSDictionary *iResponse) {
[aBlockSelf addNoDataOverlay];
} andErrorHandler:^(NSString *iMessage, NSString *iKey, NSInteger iErrorCode, BOOL iIsNetworkError) {
[aBlockSelf addNoDataOverlay];
}];
[self.requestHandler executeRequest];
Instrument Allocation Stack:
Apparently it turned out to be a known issue being tracked in this thread. Tried the same steps in iPhone 5S (iOS 8) and issue has been resolved there.
I am making a chatting application.
In my datasource method, I dequeue a cell and pass a Core Data Entity to initialize it.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Post *post = self.posts[indexPath.row];
AbstractPostCell *cell;
if ([post.type isEqualToString:#"text"]) {
cell = [tableView dequeueReusableCellWithIdentifier:CELL_POST_LIST_TEXT forIndexPath:indexPath];
}
else if ([post.type isEqualToString:#"image"]) {
cell = [tableView dequeueReusableCellWithIdentifier:CELL_POST_LIST_IMAGE forIndexPath:indexPath];
}
[cell setupWithPost:post];
return cell;
}
Here is setupWithPost method:
- (void)setupWithPost:(Post *)post {
self.label.text = post.text;
self.datetimeLabel.text = [Format stringWithDatetime:post.datetime];
if ([DBHelper didLikePost:post likerID:[Helper currentUserID]]) {
self.likeButton.enabled = NO;
self.likeButton.titleLabel.alpha = 0.5;
self.likeButton.titleLabel.text = [NSString stringWithFormat:#"liked"];
}
else {
self.likeButton.enabled = YES;
self.likeButton.titleLabel.alpha = 1.0;
self.likeButton.titleLabel.text = [NSString stringWithFormat:#"like"];
}
}
the button labels are correct when I first enter the ListViewController(TableViewController), but When I navigate to the next ViewController (DetailViewController), and then navigate back, all button labels become unset (showing whatever text I preset in storyboard)
Interestingly, when I scroll down and then scroll back, all the buttons labels become correct again.
I have tried prepareForReuse but not working
NOTE: this applies only to button title labels, normal labels (e.g. datetimeLabel) are always correctly displayed
- (void)prepareForReuse {
[super prepareForReuse];
self.label.text = #"";
self.datetimeLabel.text = #"";
self.likeButton.titleLabel.text = #"";
}
that sound very strange, I don't know if this is the cause of the problem but you should set a button title using the API
- (void)setTitle:(NSString *)title forState:(UIControlState)state
try
[self.likeButton setTitle:#"some title" forState:UIControlStateNormal];