UISearchBar not responding - ios

I added UISearchBar in UITableView and than added it inside UIView. I'm adding UIView on window and everything works fine. searchBarShouldBeginEditing is triggering and displaying logs however, searchBarTextDidBeginEditing is not triggering. Below is my code:
AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
self.frame = appDelegate.window.frame;
[appDelegate.window addSubview:self];
inside myView.h:
#property(strong, nonatomic) UISearchController *searchController;
and inside myView.m:
- (void)drawRect:(CGRect)rect {
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchBar.delegate = self;
[self.searchController.searchBar sizeToFit];
self.searchController.searchBar.userInteractionEnabled = YES;
tblDropdown.tableHeaderView = self.searchController.searchBar;
arrSeached = [NSMutableArray array];
}

Maybe, the problem is that your view controller or view (I do know without all code) has not added the protocol correctly.
Anyway, this is a example using UISearchController:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchControllerDelegate, UISearchBarDelegate, UISearchResultsUpdating>
#property (nonatomic, weak) IBOutlet UITableView * tableView;
#property (nonatomic, strong) UISearchController * searchController;
#property (nonatomic, strong) NSMutableArray * allItems;
#property (nonatomic, strong) NSMutableArray * filteredItems;
#property (nonatomic, weak) NSArray * displayedItems;
#end
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize tableView;
#synthesize searchController;
#synthesize allItems;
#synthesize displayedItems;
#synthesize filteredItems;
- (void)viewDidLoad {
[super viewDidLoad];
// Create a list
self.allItems = [[NSMutableArray alloc] init];
[self.allItems addObject:#"One"];
[self.allItems addObject:#"Two"];
[self.allItems addObject:#"Three"];
// Create a list to hold search results (filtered list)
self.filteredItems = [[NSMutableArray alloc] init];
// Initially display the full list. This variable will toggle between the full and the filtered lists.
self.displayedItems = self.allItems;
// Here's where we create our UISearchController
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.delegate = self;
[self.searchController.searchBar sizeToFit];
// Add the UISearchBar to the top header of the table view
self.tableView.tableHeaderView = self.searchController.searchBar;
// Hides search bar initially. When the user pulls down on the list, the search bar is revealed.
[self.tableView setContentOffset:CGPointMake(0, self.searchController.searchBar.frame.size.height)];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
return [self.displayedItems count];
}
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)anIndexPath {
UITableViewCell * cell = [aTableView dequeueReusableCellWithIdentifier:#"FruitCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] init];
}
cell.textLabel.text = [self.displayedItems objectAtIndex:anIndexPath.row];
return cell;
}
// When the user types in the search bar, this method gets called.
- (void)updateSearchResultsForSearchController:(UISearchController *)aSearchController {
NSLog(#"updateSearchResultsForSearchController");
NSString *searchString = aSearchController.searchBar.text;
NSLog(#"searchString=%#", searchString);
// Check if the user cancelled or deleted the search term so we can display the full list instead.
if (![searchString isEqualToString:#""]) {
[self.filteredItems removeAllObjects];
for (NSString *str in self.allItems) {
if ([searchString isEqualToString:#""] || [str localizedCaseInsensitiveContainsString:searchString] == YES) {
NSLog(#"str=%#", str);
[self.filteredItems addObject:str];
}
}
self.displayedItems = self.filteredItems;
}
else {
self.displayedItems = self.allItems;
}
[self.tableView reloadData];
}
#end

Related

Admob in ToolBar UITableViewController Xcode

I am developing an application in Xcode using objective-c. My problem is that I am trying to show admob advertising in my UITableViewController using a ToolBar but this bar is not showing anything. I have found a lot of responses on the internet about how to put this ToolBar in the UITableViewController, but for my case is not showing anything. I know that I have a low level of Xcode but I am trying to improve everyday.
This is my piece of code for the admob:
[self.navigationController setToolbarHidden:NO];
self.bannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
self.bannerView.adUnitID = #"ca-app-pub-3940256099942544/2934735716"; //TEST!!!!!
self.bannerView.rootViewController = self;
[self.navigationController.toolbar addSubview:self.bannerView];
GADRequest *request = [GADRequest request];
request.testDevices = #[ #"",];
[self.bannerView loadRequest:request];
This is my MainTableViewController.h:
#import <UIKit/UIKit.h>
#import "Restaurant.h"
#import GoogleMobileAds;
#interface MainTableViewController : UITableViewController
#property (weak, nonatomic) IBOutlet UIBarButtonItem *barButton;
#property (nonatomic, strong) NSArray<Restaurant *> *originData;
#property (nonatomic, strong) NSMutableArray<Restaurant *> *filteredRest;
#property (nonatomic, assign) Boolean isFiltered;
#property (weak, nonatomic) IBOutlet UISearchBar *mySearchBar;
#property (strong, nonatomic) IBOutlet UITableView *RestTableView;
#property (weak, nonatomic) IBOutlet UIToolbar *admobToolBar;
#property(weak, nonatomic) IBOutlet GADBannerView *bannerView;
#end
And this is my MainTableviewController.m:
#import "MainTableViewController.h"
#import "SWRevealViewController.h"
#import "RestTableViewCell.h"
#import "RestViewController.h"
#import "Restaurant.h"
#interface MainTableViewController ()
#end
#implementation MainTableViewController
#synthesize mySearchBar, filteredRest, isFiltered, originData;
- (void)viewDidLoad {
[super viewDidLoad];
_barButton.target = self.revealViewController;
_barButton.action = #selector(revealToggle:);
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
self.RestTableView.tableFooterView = [[UIView alloc] init]; /*Esta linea hace que en la tabla solo aparezcan el numero de filas que tienes establecidas, es decir, que las vacias no aparezcan*/
[self.navigationController setToolbarHidden:NO];
self.bannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
self.bannerView.adUnitID = #"ca-app-pub-3940256099942544/2934735716"; //TEST!!!!!
//self.bannerView.adUnitID = #"ca-app-pub-6926442062866079/7221537141";
self.bannerView.rootViewController = self;
[self.navigationController.toolbar addSubview:self.bannerView];
GADRequest *request = [GADRequest request];
request.testDevices = #[ #"",];
[self.bannerView loadRequest:request];
originData = #[
[[Restaurant alloc] init:#"80 Grados" descripiton:#"Malasaña" image:#"80_grados.jpg"],
[[Restaurant alloc] init:#"90 Grados" descripiton:#"Retiro" image:#"90_grados.jpg"],
[[Restaurant alloc] init:#"B&B Babel" descripiton:#"Barrio de Chueca" image:#"babel.jpg"],
[[Restaurant alloc] init:#"Babelia" descripiton:#"Barrio de Salamanca" image:#"babelia.jpg"],
[[Restaurant alloc] init:#"Bacira" descripiton:#"Chamberí" image:#"bacira.jpg"],
[[Restaurant alloc] init:#"Bar Galleta" descripiton:#"Malasaña" image:#"bar_galleta.jpg"],
[[Restaurant alloc] init:#"Bar Tomate" descripiton:#"Chamberí" image:#"bar_tomate.jpg"],
filteredRest = [NSMutableArray new];
isFiltered = NO;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (isFiltered == YES) {
return filteredRest.count;
} else {
return originData.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell";
RestTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
if (isFiltered == YES) {
cell.TitleLabel.text = [filteredRest objectAtIndex:indexPath.row].title;
cell.DescriptionLabel.text = [filteredRest objectAtIndex:indexPath.row].desc;
cell.RestImage.image = [UIImage imageNamed:[filteredRest objectAtIndex:indexPath.row].image];
} else {
cell.TitleLabel.text = [originData objectAtIndex:indexPath.row].title;
cell.DescriptionLabel.text = [originData objectAtIndex:indexPath.row].desc;
cell.RestImage.image = [UIImage imageNamed:[originData objectAtIndex:indexPath.row].image];
}
cell.RestImage.layer.cornerRadius = 6;
cell.RestImage.clipsToBounds = YES;
cell.RestImage.layer.borderWidth = 1;
return cell;
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowDetails"]){
RestViewController *restviewcontroller = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
if (isFiltered) {
restviewcontroller.DetailModal = filteredRest[myIndexPath.row];
} else {
restviewcontroller.DetailModal = originData[myIndexPath.row];
}
}
}
#end
The ToolBar is not showing anything:
What can be wrong?
I need your help! Than you very much for your responses!
Is there any reason you are using a UIToolBar to show this ad?
I would recommend instead of using a UITableViewController, use a UIViewController and make a property in there for a UITableView.
Once you have done that you can setup your constraints like so:
=====
top
tableview
ad view (set height)
bottom
======
The benefit of using a UIViewController with a table view in it is that you can put whatever else on the screen, not just the tableview :)
I hope that helps! Feel free to reply if you need more info on where to start with that!

Issues with UISearchController. How to correctly present the search results on a new table

I have two controllers: the main one is LocationItemTableViewController and contains all the graphic elements and the unfiltered table; the other one is SearchResultsTableViewController, which is used to process the results of the search. I want the search results to be displayed on LocationItemTableViewController, in a new table.
When the search starts updateSearchResultsForSearchController is called on the main controller and this assigns the results of the search to resultsController (an instance of SearchResultsTableViewController) which displays them on the main view controller.
Issues:
When updateSearchResultsForSearchController is called my NavigationBar unexpectedly disappears! Why?
When updateSearchResultsForSearchController is called the results are displayed correctly but if I scroll them up they pass underneath the SearchBar and then they show up again where there should be the NavigationBar..
When I click on a button that I have implemented in cellForRowAtIndexPath it gives me this warning:
Warning: Attempt to present UIAlertController: xxxxxxx on LocationItemTableViewController: xxxxxx whose view is not in the window hierarchy!
The button is supposed to call a kind of action sheet (UIAlertController) on LocationItemTableViewController.
Clearly there is something conceptually wrong in what I am doing but I cannot understand what...
Any hint please? Thanks!
LocationItemTableViewController.h
#interface LocationItemTableViewController : UIViewController <UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating, UIAlertViewDelegate, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate, NSCoding, UIActionSheetDelegate>
#property (strong,nonatomic) NSMutableArray *filteredLocationItemArray; //Filtered results array
#property (nonatomic, retain) IBOutlet UINavigationBar *NavigationBar;
LocationItemTableViewController.m
#interface LocationItemTableViewController ()
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, strong) NSMutableArray *searchResults;
#property (nonatomic, strong) SearchResultsTableViewController *resultsController;
- (void)viewDidLoad
{
[super viewDidLoad];
self.searchResults = [NSMutableArray arrayWithCapacity:[self.LocationItemArray count]];
resultsController = [[SearchResultsTableViewController alloc] init];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:resultsController];
self.searchController.searchResultsUpdater = self;
self.tableView.tableHeaderView = self.searchController.searchBar;
self.definesPresentationContext = YES;
self.searchController.searchBar.placeholder = nil;
[self.searchController.searchBar sizeToFit];
self.searchController.dimsBackgroundDuringPresentation = YES;
self.searchController.searchBar.delegate = self;
self.searchController.delegate = self;
self.tableView.frame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y + NavigationBar.bounds.size.height +20, self.tableView.frame.size.width, self.tableView.contentSize.height);
}
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController {
NSString *searchString = [self.searchController.searchBar text];
NSString *scope = nil;
[self updateFilteredContentForProductName:searchString type:scope];
if (self.searchController.searchResultsController) {
resultsController.filteredEvents = self.searchResults;
resultsController.tableView.frame = CGRectMake(0,0,[[UIScreen mainScreen] bounds].size.width,[[UIScreen mainScreen] bounds].size.height-ToolBar.bounds.size.height);
//Now reload the table but this time containing the search results
[resultsController.tableView reloadData];
}
}
SearchResultsTableViewController.h
#interface SearchResultsTableViewController : UITableViewController
#property (nonatomic, strong) NSMutableArray *filteredEvents;
SearchResultsTableViewController.m
#interface SearchResultsTableViewController ()
#property (nonatomic, strong) LocationItemTableViewController *instanceOfLocationItemTableViewController;
#end
#implementation SearchResultsTableViewController
#synthesize instanceOfLocationItemTableViewController;
- (void)viewDidLoad
{
[super viewDidLoad];
//Create instance of LocationItemTableViewController.h
instanceOfLocationItemTableViewController = [[LocationItemTableViewController alloc] init];
[self.tableView setAllowsSelection:NO];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.filteredEvents ? 1 : 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"CALLED numberOfRowsInSection --: %lu", (unsigned long)[self.filteredEvents count]);
return [self.filteredEvents count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Create a new LocationItem Object
LocationItem *locationItem = nil;
locationItem = [self.filteredEvents objectAtIndex:[indexPath row]];
static NSString *CellIdentifier = #"SearchResultCell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
....
[[cell textLabel] setText:[locationItem name]];
return cell;
}

Further clarification of "How to implement UISearchController with objective c"

I have been trying to implement UISearchController by following stackoverflow thread:
How to implement UISearchController with objective c
and Apples's documentation, but can't make it working. When the initial controller (EVTSearchViewController which is defined as UIViewController) that complies with UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating, UITableViewDelegate
(I needed to make it compliant with UITableViewDelegate too, since I am making it a delegate of the other UITableViewController type EVTSearchResultsViewController *resultsControllers tableView) delegates is presented, I see my .xib with the UISearchBar and UITableView, I click the search bar and start typing:
When I type one letter, search bar disappears and nothing is shown:
First, I do not want the search bar to disappear. Second, updateSearchResultsForSearchController seems not to be called at all since NSLog() set up there does not produce any output when I am typing in the search bar.
I have .xib for the EVTSearchViewController and it has a UISearchBar that I am connecting to the respective property: IBOutlet UISearchBar *searchBar which is then made to point to the UISearchControllers' searchBar:
self.searchBar = self.searchController.searchBar
There is also UITableView that I put below the UISearchBar in the .xib. Another controller that I am using inside EVTSearchViewController is EVTSearchResultsViewController, it is UITableViewController and it does not have its .xib.
Below is the code for viewDidLoad and updateSearchResultsForSearchController methods:
- (void)viewDidLoad
{
_resultsController = [[EVTSearchResultsViewController alloc] init];
_searchController = [[UISearchController alloc] initWithSearchResultsController:_resultsController];
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.placeholder = nil;
[self.searchController.searchBar sizeToFit];
self.searchBar = self.searchController.searchBar;
// we want to be the delegate for our filtered table so didSelectRowAtIndexPath is called for both tables
self.resultsController.tableView.delegate = self;
self.searchController.delegate = self;
self.searchController.dimsBackgroundDuringPresentation = YES; // default is YES
self.searchController.searchBar.delegate = self; // so we can monitor text changes + others
// Search is now just presenting a view controller. As such, normal view controller
// presentation semantics apply. Namely that presentation will walk up the view controller
// hierarchy until it finds the root view controller or one that defines a presentation context.
//
self.definesPresentationContext = YES; // know where you want UISearchController to be displayed
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
// update the filtered array based on the search text
NSString *searchText = searchController.searchBar.text;
NSLog(#"searchText: %#", searchText);
if (searchText == nil) {
// If empty the search results are the same as the original data
self.searchResults = [[[EVTItemStore sharedStore] allItems] mutableCopy];
} else {
NSMutableArray *searchResults = [[NSMutableArray alloc] init];
NSArray *allEvents = [[EVTItemStore sharedStore] allItems];
NSLog(#"allEvents: %#", allEvents);
for (EVTItem *event in allEvents) {
/*if ([event.number containsString:searchText] || [[phoneMO.closrr_id filteredId] containsString:searchText] || [[phoneMO.contact.fullname lowercaseString] containsString:[searchText lowercaseString]]) {
[searchResults addObject:phoneMO];
}*/
if ([event.eventName containsString:searchText]) {
[searchResults addObject:event];
}
}
self.searchResults = searchResults;
}
// hand over the filtered results to our search results table
EVTSearchResultsViewController *resultsController = (EVTSearchResultsViewController *)self.searchController.searchResultsController;
resultsController.filteredEvents = self.searchResults;
[resultsController.tableView reloadData];
}
The respective #properties defined in EVTSearchViewController:
#interface EVTSearchViewController ()
#property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, strong) EVTSearchResultsViewController *resultsController;
#property (nonatomic, strong) NSMutableArray *searchResults;
// For state restoration
#property BOOL searchControllerWasActive;
#property BOOL searchControllerSearchFieldWasFirstResponder;
#end
Then, here is the code for EVTSearchResultsViewController:
#import "EVTSearchResultsViewController.h"
#implementation EVTSearchResultsViewController
- (instancetype)init
{
// Call the superclass's designated initializer
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:#"UISearchViewCell"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return [self.filteredEvents count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:#"UISearchViewCell"
forIndexPath:indexPath];
cell.textLabel.text = self.filteredEvents[indexPath.row];
return cell;
}
#end
The methods of EVTSearchResultsViewController above are not called at all which makes look very strange for me, why do we need it at all, then?
I tried to set UISearchBar the way Apple docs recommend:
self.resultsTableView.tableHeaderView = self.searchController.searchBar;
but it gives me a non-responsive search box, so when pressing nothing happens.
Could anyone, please, help with resolving the question. The other question linked above can also be clarified then. Thank you.
So, I solved the issue and implemented basic search with UISearchController. Here is what we need to do to implement the basic search:
Create two UITableViewControllers classes with NO .xib files. Yes, there should be no .xib files and we are just creating two classes. In the code below their names are EVTSearchViewController and EVTSearchResultsViewController.
Make one of the controllers to comply with the delegates: <UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating>
Here is the code for the header file of EVTSearchViewController:
#import <UIKit/UIKit.h>
#interface EVTSearchViewController : UITableViewController <UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating>
#end
Here is the EVTSearchResultsViewController's header:
#import <UIKit/UIKit.h>
#interface EVTSearchResultsViewController : UITableViewController
#property (nonatomic, strong) NSMutableArray *filteredEvents;
#end
The NSMutableArray *filteredEvents will hold the results of the search. We should NOT implement any of the UITableViewController delegate methods in EVTSearchViewController.m, but should in EVTSearchResultsViewController.m.
Here is the top part of EVTSearchViewController:
#import "EVTSearchViewController.h"
#import "EVTSearchResultsViewController.h"
// Importing the class that stores `EVTItem` object classes
#import "EVTItemStore.h"
#import "EVTItem.h"
#interface EVTSearchViewController ()
#property (nonatomic, strong) UISearchController *searchController;
// We created this class
#property (nonatomic, strong) EVTSearchResultsViewController *resultsController;
// array to hold the results of the search
#property (nonatomic, strong) NSMutableArray *searchResults;
#end
Here is the code for EVTSearchViewController's viewDidLoad: method:
- (void)viewDidLoad
{
[super viewDidLoad];
self.resultsController = [[EVTSearchResultsViewController alloc] init];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsController];
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.placeholder = nil;
[self.searchController.searchBar sizeToFit];
// This line of code is very important. Here we are using apple docs'
// suggestion. UITableViewController has tableView property, so
// we are just setting tableView`s header to apples' UISearchController`s' `searchBar property
self.tableView.tableHeaderView = self.searchController.searchBar;
self.searchController.delegate = self;
// default is YES
self.searchController.dimsBackgroundDuringPresentation = YES;
// so we can monitor text changes + other changes
self.searchController.searchBar.delegate = self;
// know where you want UISearchController to be displayed
self.definesPresentationContext = YES;
}
Then we add to EVTSearchViewController the following method:
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
// update filtered array based on the search text
NSString *searchText = searchController.searchBar.text;
if (searchText == nil) {
// If empty the search results should be the same as the original data
self.searchResults = [[[EVTItemStore sharedStore] allItems] mutableCopy];
} else {
NSMutableArray *searchResults = [[NSMutableArray alloc] init];
// [[EVTItemStore sharedStore] allItems] message retrieves
// all of the objects that I have in datastore EVTItemStore
NSArray *allEvents = [[EVTItemStore sharedStore] allItems];
// EVTItem class has a property eventName which we are using
// for searching, then adding it to our searchResults array
for (EVTItem *event in allEvents) {
if ([event.eventName containsString:searchText]) {
[searchResults addObject:event];
}
}
self.searchResults = searchResults;
}
// hand over the filtered results to our search results table
EVTSearchResultsViewController *resultsController = (EVTSearchResultsViewController *)self.searchController.searchResultsController;
resultsController.filteredEvents = self.searchResults;
[resultsController.tableView reloadData];
}
Another controller's EVTSearchResultsViewController #implementation part looks like this:
#implementation EVTSearchResultsViewController
- (instancetype)init
{
// Call the superclass's designated initializer
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
}
return self;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return [self.filteredEvents count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:#"UISearchViewCell"
forIndexPath:indexPath];
EVTItem *event = self.filteredEvents[indexPath.row];
cell.textLabel.text = event.eventName;
return cell;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:#"UISearchViewCell"];
}
#end
That's it. If we need to further customize our cells, we should be able to do it by making UISearchViewCell.xib for EVTSearchResultsViewController, and using the following viewDidLoad instead:
- (void)viewDidLoad
{
[super viewDidLoad];
// Load the NIB file
UINib *nib = [UINib nibWithNibName:#"UISearchViewCell" bundle:nil];
// Register this NIB which contains the cell
[self.tableView registerNib:nib forCellReuseIdentifier:#"UISearchViewCell"];
}

UISearchDisplayController does not entirely cover a child view controller

I have a root view controller which composes a search bar on the top and a child table view controller on the bottom. I used composition instead of assigning the search bar to the table view's header for these reasons:
I didn't want the index to overlap with the search bar (like Contacts app).
I wanted the search bar to be sticky. That is, it doesn't move when I scroll the table view (again like the Contacts app).
My table view already had a header.
Since the search bar is in the root view controller, I instantiate my search display controller in the root view controller also. There are two problems with the search UI for which I seek advice:
The translucent gray overlay does not cover the entire child table view. It leaves the top portion of the header and the index visible.
Likewise, the search results table does not cover the entirety of the child table view. I know how to manually change the frame of this results table view, but doing so only fixes just that ... the gray translucent overlay's frame is not linked to the results table view frame. Their is no property to access the overlay.
1) Idle
2) Enter Search Bar
3) Start Typing
#import "ContactsRootViewController.h"
#import "ContactsViewController.h"
#import "UIView+position.h"
#import "User.h"
#import "UserCellView.h"
#import "UserViewController.h"
#interface ContactsRootViewController ()
#property(nonatomic, strong) UISearchBar* searchBar;
#property(nonatomic, strong) ContactsViewController* contactsViewController;
#property(nonatomic, strong) UISearchDisplayController* searchController;
#property(nonatomic, strong) NSMutableArray* matchedUsers;
#end
#implementation ContactsRootViewController
#pragma mark UIViewController
- (NSString*)title
{
return #"Contacts";
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.matchedUsers = [NSMutableArray array];
self.searchBar = [[UISearchBar alloc] init];
self.searchBar.placeholder = #"Search";
[self.searchBar sizeToFit];
[self.view addSubview:self.searchBar];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (self.contactsViewController == nil) {
self.contactsViewController = [[ContactsViewController alloc] init];
[self addChildViewController:self.contactsViewController];
self.contactsViewController.view.frame = CGRectMake(
0.0,
self.searchBar.bottomY,
self.view.frame.size.width,
self.view.frame.size.height - self.searchBar.bottomY
);
self.contactsViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
[self.view addSubview:self.contactsViewController.view];
[self.contactsViewController didMoveToParentViewController:self];
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self.contactsViewController];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
}
}
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.matchedUsers.count;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* identifier = #"contactsRootViewUserCell";
UserCellView* cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UserCellView alloc] initWithIdentifier:identifier];
}
cell.user = [self.matchedUsers objectAtIndex:indexPath.row];
return cell;
}
#pragma mark UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.navigationController pushViewController:[[UserViewController alloc] initWithUser:[self.matchedUsers objectAtIndex:indexPath.row]] animated:YES];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [UserCellView height];
}
#pragma mark UISearchDisplayControllerDelegate
- (BOOL)searchDisplayController:(UISearchDisplayController*)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self.matchedUsers removeAllObjects];
searchString = [searchString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (searchString.length > 0) {
for (User* user in self.contactsViewController.allUsers) {
NSRange match = [user.userDisplayName rangeOfString:searchString options:NSCaseInsensitiveSearch];
if (match.location != NSNotFound) {
[self.matchedUsers addObject:user];
}
}
}
return YES;
}
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
[self.searchBar resignFirstResponder];
}
#end
I re-implemented UISearchDisplayController, calling my implementation SearchController. It does the same thing and has similar delegate callbacks, but the frame of the search results can be controlled by the programmer.
Header
#import <Foundation/Foundation.h>
#class SearchController;
#protocol SearchControllerDelegate <NSObject>
#required
- (BOOL)searchController:(SearchController*)controller shouldReloadTableForSearchString:(NSString*)searchText;
#optional
- (void)searchController:(SearchController*)controller didShowSearchResultsTableView:(UITableView*)tableView;
- (void)searchController:(SearchController *)controller didHideSearchResultsTableView:(UITableView *)tableView;
- (void)searchControllerDidBeginSearch:(SearchController*)controller;
- (void)searchControllerDidEndSearch:(SearchController*)controller;
#end
#interface SearchController : UIViewController <UISearchBarDelegate>
#property(nonatomic, weak) NSObject<SearchControllerDelegate>* delegate;
#property(nonatomic, weak) NSObject<UITableViewDataSource>* searchResultsDataSource;
#property(nonatomic, weak) NSObject<UITableViewDelegate>* searchResultsDelegate;
#property(nonatomic, strong, readonly) UITableView* searchResultsTableView;
- (id)initWithSearchBar:(UISearchBar*)searchBar;
#end
Implementation
#import "SearchController.h"
#import "UIView+position.h"
#interface SearchController ()
#property(nonatomic, strong) UISearchBar* searchBar;
#property(nonatomic, strong) UIButton* searchResultsVeil;
#property(nonatomic, strong, readwrite) UITableView* searchResultsTableView;
#property(nonatomic, assign) BOOL searchResultsTableViewHidden;
- (void)didTapSearchResultsVeil;
- (void)hideSearchResults;
#end
#implementation SearchController
#pragma mark UIViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.searchResultsTableView deselectRowAtIndexPath:[self.searchResultsTableView indexPathForSelectedRow] animated:YES];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.userInteractionEnabled = NO;
}
#pragma mark SearchController ()
- (void)hideSearchResults
{
self.searchBar.text = nil;
[self.searchResultsTableView reloadData];
self.searchResultsTableViewHidden = YES;
[self.searchBar resignFirstResponder];
}
- (void)didTapSearchResultsVeil
{
[self hideSearchResults];
}
- (void)setSearchResultsTableViewHidden:(BOOL)searchResultsTableViewHidden
{
if (self.searchResultsTableView != nil) {
if (self.searchResultsTableView.hidden && !searchResultsTableViewHidden) {
self.searchResultsTableView.hidden = searchResultsTableViewHidden;
if ([self.delegate respondsToSelector:#selector(searchController:didShowSearchResultsTableView:)]) {
[self.delegate searchController:self didShowSearchResultsTableView:self.searchResultsTableView];
}
} else if (!self.searchResultsTableView.hidden && searchResultsTableViewHidden) {
self.searchResultsTableView.hidden = searchResultsTableViewHidden;
if ([self.delegate respondsToSelector:#selector(searchController:didHideSearchResultsTableView:)]) {
[self.delegate searchController:self didHideSearchResultsTableView:self.searchResultsTableView];
}
}
}
}
- (BOOL)searchResultsTableViewHidden
{
return self.searchResultsTableView == nil || self.searchResultsTableView.hidden;
}
#pragma mark SearchController
- (id)initWithSearchBar:(UISearchBar *)searchBar
{
if (self = [super init]) {
self.searchBar = searchBar;
self.searchBar.delegate = self;
}
return self;
}
- (void)setSearchResultsDataSource:(NSObject<UITableViewDataSource> *)searchResultsDataSource
{
_searchResultsDataSource = searchResultsDataSource;
if (self.searchResultsTableView != nil) {
self.searchResultsTableView.dataSource = searchResultsDataSource;
}
}
- (void)setSearchResultsDelegate:(NSObject<UITableViewDelegate> *)searchResultsDelegate
{
_searchResultsDelegate = searchResultsDelegate;
if (self.searchResultsTableView != nil) {
self.searchResultsTableView.delegate = searchResultsDelegate;
}
}
#pragma mark UISearchBarDelegate
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if ([self.delegate searchController:self shouldReloadTableForSearchString:searchText]) {
[self.searchResultsTableView reloadData];
self.searchResultsTableViewHidden = [self.searchResultsTableView.dataSource tableView:self.searchResultsTableView numberOfRowsInSection:0] == 0;
}
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
[searchBar setShowsCancelButton:YES animated:YES];
if (self.searchResultsVeil == nil) {
self.searchResultsVeil = [[UIButton alloc] initWithFrame:self.view.bounds];
self.searchResultsVeil.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.6];
self.searchResultsVeil.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.searchResultsVeil addTarget:self action:#selector(didTapSearchResultsVeil) forControlEvents:UIControlEventTouchUpInside];
self.searchResultsTableView = [[UITableView alloc] initWithFrame:self.searchResultsVeil.bounds style:UITableViewStylePlain];
self.searchResultsTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
if ([self.searchResultsTableView respondsToSelector:#selector(setSeparatorInset:)]) {
self.searchResultsTableView.separatorInset = UIEdgeInsetsMake(
0.0,
self.searchResultsTableView.width,
0.0,
0.0
);
}
self.searchResultsTableViewHidden = YES;
if (self.searchResultsDataSource != nil) {
self.searchResultsTableView.dataSource = self.searchResultsDataSource;
}
if (self.searchResultsDelegate != nil) {
self.searchResultsTableView.delegate = self.searchResultsDelegate;
}
[self.view addSubview:self.searchResultsVeil];
[self.searchResultsVeil addSubview:self.searchResultsTableView];
}
self.view.userInteractionEnabled = YES;
self.searchResultsVeil.hidden = NO;
if ([self.delegate respondsToSelector:#selector(searchControllerDidBeginSearch:)]) {
[self.delegate searchControllerDidBeginSearch:self];
}
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
[searchBar setShowsCancelButton:NO animated:YES];
self.view.userInteractionEnabled = NO;
self.searchResultsVeil.hidden = YES;
if ([self.delegate respondsToSelector:#selector(searchControllerDidEndSearch:)]) {
[self.delegate searchControllerDidEndSearch:self];
}
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
[self hideSearchResults];
}
#end
Usage
self.searchController = [[SearchController alloc] initWithSearchBar:self.searchBar];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
[self addChildViewController:self.searchController];
self.searchController.view.frame = CGRectMake(
self.searchBar.x,
self.searchBar.bottomY,
self.searchBar.width,
self.view.height - self.searchBar.bottomY
);
[self.view addSubview:self.searchController.view];
[self.searchController didMoveToParentViewController:self];
It looks like your view controller does not define a presentation context. I had a similar problem and was able to resolve it by setting
self.definesPresentationContext = YES;
in viewDidLoad. According to the documentation this property is
A Boolean value that indicates whether this view controller's view is covered when the view controller or one of its descendants presents a view controller.

iOS (iPhone/iPad) SDK - UITableView not refreshing on reloadData (numberOfSectionsInTableView etc. does not get called on reloadData)

For some reason [tView reloadData] (where tView is a UITableView) does not refresh my UITableView. cellForRowAtIndexPath, numberOfSectionsInTableView and numberOfRowsInSection only get called once - at load. Those methods don't seem to be called after [tView reloadData]. Here's my code:
(AppDelegate.h):
#import <UIKit/UIKit.h>
#import "MBProgressHUD.h"
#class FirstNavViewController;
#class SecondTableViewController;
#interface <appname>AppDelegate : NSObject <UIApplicationDelegate, MBProgressHUDDelegate> {
UIWindow *window;
UITabBarController *rootController;
FirstNavViewController *viewController;
SecondTableViewController *viewController1;
NSMutableData *responseData;
NSMutableArray *blogEntries;
MBProgressHUD *HUD;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *rootController;
#property (nonatomic, retain) IBOutlet FirstNavViewController *viewController;
#property (nonatomic, retain) IBOutlet SecondTableViewController *viewController1;
#property (nonatomic, retain) NSMutableArray *blogEntries;
#end
(AppDelegate.m):
#import "AppDelegate.h"
#import "FirstNavViewController.h"
#import "SecondTableViewController.h"
#import "SBJson.h"
#define TMP NSTemporaryDirectory()
#implementation AppDelegate
#synthesize window = _window;
#synthesize rootController;
#synthesize viewController;
#synthesize viewController1;
#synthesize blogEntries;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
CGFloat width = self.rootController.view.bounds.size.width;
CGFloat height = self.rootController.view.bounds.size.height;
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, width, height)];
UIImage *imageView = [UIImage imageNamed:#"theme_frame.png"];
UIColor *kMainColor = [[UIColor alloc] initWithPatternImage:imageView];
[v setBackgroundColor:kMainColor];
[kMainColor release];
[self.rootController.tabBar insertSubview:v atIndex:0];
imageView = nil;
[v release];
responseData = [[NSMutableData data] retain];
blogEntries = [NSMutableArray array];
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:#"ENTER_JSON_URL_HERE"]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
NSAssert(nil != self.rootController, #"tab bar controller not hooked up!");
BOOL iPad = NO;
#ifdef UI_USER_INTERFACE_IDIOM
iPad = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
#endif
if (iPad) {
self.viewController = [[[FirstNavViewController alloc] initWithNibName:#"FirstNavViewController_iPad" bundle:nil] autorelease];
self.viewController1 = [[[SecondTableViewController alloc] initWithNibName:#"SecondTableViewController_iPad" bundle:nil] autorelease];
}
else {
self.viewController = [[[FirstNavViewController alloc] initWithNibName:#"FirstNavViewController_iPhone" bundle:nil] autorelease];
self.viewController1 = [[[SecondTableViewController alloc] initWithNibName:#"SecondTableViewController_iPhone" bundle:nil] autorelease];
}
self.rootController.viewControllers = [NSArray arrayWithObject:self.viewController];
self.rootController.selectedIndex = 0;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
self.window.rootViewController = self.rootController;
#else
[self.window addSubview:rootController.view];
#endif
[self.window makeKeyAndVisible];
HUD = [[MBProgressHUD alloc] initWithView:viewController.view];
[viewController.view addSubview:HUD];
[HUD show:NO];
// Regisete for HUD callbacks so we can remove it from the window at the right time
HUD.delegate = self;
HUD.labelText = #"Loading";
return YES;
}
#pragma mark NSURLConnection delegate methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[HUD hide:YES];
[connection release];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
NSMutableArray *allBlogEntries = [responseString JSONValue];
[viewController1 setBlogEntries:allBlogEntries];
[responseString release];
[HUD hide:YES];
}
- (void)dealloc
{
[_window release];
[rootController release];
[viewController release];
[viewController1 release];
[super dealloc];
}
#end
(FirstNavViewController.h):
#import <UIKit/UIKit.h>
#interface FirstNavViewController : UIViewController {
UINavigationController *navController;
}
#property (nonatomic, retain) UINavigationController *navController;
#end
(FirstNavViewController.m):
#import "FirstNavViewController.h"
#import "SecondTableViewController.h"
#implementation FirstNavViewController
#synthesize navController;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
UITabBarItem *tabBarItem = [self tabBarItem];
UIImage *tabBarImage = [UIImage imageNamed:#"blog.png"];
[tabBarItem setImage:tabBarImage];
[tabBarItem setTitle:#"Blog"];
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
navController = [[UINavigationController alloc] initWithRootViewController:self];
SecondTableViewController *secondViewController = [[SecondTableViewController alloc] initWithNibName:#"BlogOverviewViewController_iPhone" bundle:nil];
[navController pushViewController:secondViewController animated:NO];
[blogOverviewViewController release];
[self.view addSubview:navController.view];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
(SecondTableViewController.h):
#import <UIKit/UIKit.h>
#import "SBJson.h"
#interface SecondTableViewController : UIViewController {
NSMutableArray *blogEntries;
IBOutlet UITableView *tView;
}
#property (nonatomic, retain) NSMutableArray *blogEntries;
#property (nonatomic, retain) NSArray *arryData;
#property (nonatomic, retain) IBOutlet UITableView *tView;
#end
(SecondTableViewController.m):
#import "SecondTableViewController.h"
#import "ThirdDetailViewController.h"
#import "NSString+HTML.h"
NSString *convertedString;
#implementation SecondTableViewController
#synthesize arryData;
#synthesize tView;
-(NSMutableArray*)blogEntries {
return [[blogEntries retain] autorelease];
}
-(void)setBlogEntries:(NSMutableArray*)newBlogEntries {
if(newBlogEntries != blogEntries) {
[newBlogEntries retain];
[blogEntries release];
blogEntries = newBlogEntries;
[tView reloadData];
}
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [blogEntries count];
}
// 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...
NSDictionary *aBlogEntry = [blogEntries objectAtIndex:[indexPath row]];
NSArray *bPosts = (NSArray *)[aBlogEntry objectForKey:#"posts"];
NSString *stringToConvert = [bPosts valueForKey:#"title_plain"];
NSString *convertedString = [stringToConvert stringByConvertingHTMLToPlainText];
cell.textLabel.text = convertedString;
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.font = [UIFont systemFontOfSize:12];
cell.textLabel.minimumFontSize = 10;
cell.textLabel.numberOfLines = 4;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
NSString *stringToConvert1 = [bPosts valueForKey:#"excerpt"];
NSString *convertedString1 = [stringToConvert1 stringByConvertingHTMLToPlainText];
cell.detailTextLabel.text = convertedString1;
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ThirdDetailViewController *detailViewController = [[ThirdDetailViewController alloc] initWithNibName:#"BlogContentViewController_iPhone" bundle:nil];
[self.navigationController pushViewController:detailViewController animated:YES];
NSDictionary *aBlogEntry = [blogEntries objectAtIndex:[indexPath row]];
NSArray *bPosts = (NSArray *)[aBlogEntry objectForKey:#"posts"];
NSString *stringToConvert = [bPosts valueForKey:#"title"];
NSString *convertedString = [stringToConvert stringByConvertingHTMLToPlainText];
[contentViewController changeTitleTextLabel:convertedString];
NSString *stringToConvert1 = [bPosts valueForKey:#"content"];
NSString *convertedString1 = [stringToConvert1 stringByConvertingHTMLToPlainText];
NSString *newConvertedString1 = [convertedString1 stringByReplacingOccurrencesOfString: #"\n" withString:#"\n\n"];
[detailViewController changeContentTextLabel:newConvertedString1];
[tableView deselectRowAtIndexPath: indexPath animated: YES];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
blogEntries = [[NSMutableArray alloc]init];
self.title = #"Blog";
[self.navigationItem setHidesBackButton:YES animated:NO];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)dealloc {
[blogEntries release];
[super dealloc];
}
#end
Does anyone know what the problem is? I am stuck on why the UITableView will not reloadData.
EDIT: Small background: I am using a UITabBarController (AppDelegate) with a UIViewController in it with a UINavigationController as a subview of that UIViewController (FirstNavViewController). The UINavigationController then has a subview with another UIViewController in it. The latter UIViewController (SecondTableViewController) includes a UITableView.
I've just been having this issue. Turned out to be a threading problem for me. For those those who end up here after a search, here is my quick fix:
[tView performSelectorOnMainThread:#selector(reloadData)
withObject:nil
waitUntilDone:false];
It seems reloadData needs to be called on the main thread. I hope this helps (^_^)
In your viewDidLoad method, add: tView.delegate = self;
Your view setup might be the cause of your problems.
I don't really understand the details of your implementation but right now you are adding that SecondTableViewController to both the tab bar controller and then on the stack of a navigation controller in your FistNavViewController viewDidLoad method.
Create the navigation controller with FistNavViewController as its rootViewController, then add the navigation controller as the first view controller to your UITabBarViewController
(code here is typed from memory so please excuse any typos)
FirstNavViewController *vc = [[FirstNavViewController alloc] initWithNibName:#"nibname" andBundleName:nil];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:vc];
UITabBarController *tbc = [UITabBarController setViewControllers:[NSArray arrayWithObjects:nc, otherVc1Example, otherVc2Example, nil] animated:NO];
In your FirstNavViewController viewDidLoad method, you can then instantiate SecondTableViewController and push it onto the stack with
[self.navigationController pushViewController:secondTableViewController animated:YES];
Finally, within that nav controller you need to make sure you have your UITableView setup correcly either in Interface Builder (by connecting the datasource and delegate outlets to the file owner) or in code by manually setting the tableview delegate and datasource to self.
Bottom line is everything you are trying to do above is WAY easier and less error prone if you use Interface Builder. In MainWindow.xib simple add a tab bar controller and under it add navigation controllers and view controllers as you see fit. It should work "pretty much" out of the box.
Good luck.
Rog

Resources