I have a tableviewcontroller and a custom headerview (uiview)
Headerview interface
#interface HMDiscoveryHeaderView : UIView <UISearchBarDelegate>
#property (nonatomic, strong) UISearchBar *searchBar;
#end
the searchbar is initialized in the layoutSubviews method
- (void)layoutSubviews {
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(20, 20, 250, 50)];
[self addSubview:self.searchBar];
}
and I'm able to get the text in it like so
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
NSLog(#"search text %#", searchBar.text);
}
in my tableview, the interface is this
#interface HMDiscoveryViewController () <UISearchBarDelegate>
#property (nonatomic, strong) NSString * stuff;
#property (nonatomic, strong) HMDiscoveryHeaderView *headerView;
#end
and i set the header in viewdidload like so
- (void)viewDidLoad {
[super viewDidLoad];
self.headerView = [[HMDiscoveryHeaderView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 100)];
[[self.headerView searchBar] setDelegate:self];
[self.tableView setTableHeaderView:self.headerView];
NSString *testy = [[self.headerView searchBar] text];
// this prints null
NSLog(#"test %#", testy);
}
and these 2 methods to attempt to get the text are never called
- (void)setStuff:(NSString *)stuff
{
_stuff = stuff;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[self setStuff:searchBar.text];
NSLog(#"lol shit %#", self.stuff);
}
How do i get the input text in the UISearchBar in the headerview in the tableviewcontroller?
"My headerview has a UISearchbar as a subview initialized in the viewdidload"
this isn't possible since the headerView is a UIview as you stated, and UIViews don't have a "viewDidLoad" method, however, I digress ... assuming that you meant that the UITAbleViewController declares the headerview in the view did load then you need to do something like this:
HeaderView.h
#interface HeaderView : UIView
#property (nonatomic) UISearchBar *searchBar
#end
Now you have exposed the UISearchBar to other classes by declaring the UISearchBar in the headerViews header file. then do this
headerview *headerView = [[headerview alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 100)];
self.tableView.tableHeaderView = headerView;
[headerview searchBar].text <==this is the search bar text!
Now, in order to force this Text into the table view, do this:
in the header file to your tableView declare an NSString property
#property (nonatomic) NSString * stuff;
Then, in the tableview implmentaiton file do this:
- (void)setStuff:(NSString *)stuff
{
_stuff = stuff;
}
Now _stuff holds a string value
In your table view controller, in this method:
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
NSLog(#"search text %#", searchBar.text);
}
change it to this:
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
[tableView setStuff:searchBar.text];
}
then, in your tableView you can screw around with the text form the search bar
Delegation is for those who don't know how to use setters and getters correctly, you don't have to use delegation almost ever, and I'd stay away form it because it will turn your app into a beast of of nightmare after you reach 10s of thousands of lines of code.
setters & getters with subclasses is about 4 trillion times better than delegation, use delegation when using UIKit elements that require you to know stuff about the object you are subclassing, otherwise, setters and getters mixed with block operations are bar far the simplest, easiest to read, and most portable ways to code. Pure encapsulation is what you want.
Oh yeah, and make your UITableViewController a UISearchBarDelegte so that you can use the above function in your UITableViewController, that's why you might be scratching your head right now, so this goes into your UITableViewController:
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
[tableView setStuff:searchBar.text];
}
troubles, you are having, this:
Implementation file for UITableViewController:
#interface CustomSuperStarTableViewController () <UISearchBarDelegate, UITableViewDataSource, UITableViewDelegate>
#end
#implementation CustomSuperStarTableViewController
{
SuperNiftyHeaderView * iLikeCats;
}
-(void)viewDidLoad
{
iLikeCats = [SuperNiftyHeaderView new];
[[iLikeCats iLikeCatsSearchBar] setDelegate:self];
[self.tableView setTableHeaderView:iLikeCats];
// you can now access the searchBar!
//here's how you access the searchBar
NSString * bubbleGum = [[iLikeCats iLikeCatsSearchBar] text]; <=== search bar text
UIColor * hello = [[iLikeCats iLikeCatsSearchBar] backGroundColor]; <=== search bar backGroundColor
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
}
I should also note, that this assumes that you actually created a separate .h and .m file that is a subclassed UITableView, correct? and that this subclass has in it's header file an exposed property like this:
#property (nonatomic) MyNiftyCustomHeaderView * customHeaderView
Okay, so different scenario:
headerView is custom and it contains the UISearchBar, right ? Right, excellent, so let's declare the headerview right now!
SuperNiftyHeaderView.h
#interface SuperNiftyHeaderView : UIView
#property (nonatomic) UISearchBar * iLikeCatsSearchBar;
#end
SuperNiftyHeaderView.m
#implementation SuperNiftyHeaderView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
_iLikeCatsSearchBar = [[UISearchBar alloc] init];
[_iLikeCatsSearchBar setPlaceholder:#" Search ..."];
[_iLikeCatsSearchBar setTranslucent:TRUE];
[_iLikeCatsSearchBar setBarStyle:UIBarStyleDefault];
[_iLikeCatsSearchBar setSearchBarStyle:UISearchBarStyleProminent];
[_iLikeCatsSearchBar setBackgroundColor:[UIColor blueColor]];
[_iLikeCatsSearchBar setTranslatesAutoresizingMaskIntoConstraints:FALSE];
[self addSubView:_iLikeCatsSearchBar];
/// do more work, and then more work
/// add constraints because you are going to learn to do all subviews programmatically from here on out and you love to program IOS so much that 1000s of lines of code are better than storyboard easy street
}
return self;
}
#end
Now, relook at the stuff I did for the CustomSuperStarTableViewController
And what's more, is that we could have had access to the search by text by just adding to the UITableViewController and forcing the SearchBar to be a delegate of the ViewController, BUT, we misunderstood each other at first, so the point is:
1. table view controller = search bar delegate
2. intercept text
3. send this text to the tableview to do as you wish, and if it's to use this to filter the tablview then there's about 1 billion tutorials out there on using predicates and arrays to make this magic happen, but of course it will be easier for you to do this because you used a UITableViewController instead of a UIViewController, excellent and have a good day.
this is where you capture goodness from the SearchBar:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[_categories removeAllObjects];
_searchText = searchText;
NSArray * ss = [test copy];
_categories = [NSMutableArray arrayWithArray:[ss filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF contains[c] %#", _searchText]]];
if (_categories.count ==0 && _searchText.length ==0) {
_categories = [NSMutableArray arrayWithArray:test];
}
[[[self contentView] tableView] reloadData];
}
don't freak out about the method calls in this call, they aren't important to what you are doing, just worry about this:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
_searchText = searchText;
}
and _searchText is declared in the implementation file like this, it's an IVAR
#implementation WhatEverYouWanttoNameItTableViewController
{
NSString * _searchText;
}
Related
I have a textfield on my MainViewController that I'd like to pass a string into from my TableViewController. Specifically when I select a cell (didSelectRowatIndexPath) I'd like to take the text for that indexpath.row and dismiss the TableViewController passing the string into the textfield on my MainViewController. I have attempted to create a delegate to get this to work but all it says in the debugging window is that the correct string is passing but never appears in the textfield... Here is my code showing everything necessary for the delegation.
My TableViewController.h where the delegate is declared...
#protocol sendDataProtocol <NSObject>
- (void)sendDataToMain:(NSString*)text;
#end
#interface TableViewController : UITableViewController<UITableViewDelegate, UITableViewDataSource> {
__weak id selectDataDelegate;
}
#property(nonatomic,weak)id<sendDataProtocol> selectedDataDelegate;
#property(strong,nonatomic)NSArray *presetList; //Holds the strings I want to pass
#end
Then my TableViewController.m file...
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize selectedDataDelegate;
-(void)viewDidLoad {
//http://morsecode.scphillips.com/morse.html
self.presetList = [NSArray arrayWithObjects:#"AS",
#"BCNU",
#"CL",
#"CT",
#"CUL",
#"K",
#"QSL",
#"QSL?",
#"QRX?",
#"QRV",
#"QRV?",
#"QTH",
#"QTH?",
#"R",
#"SN",
#"SOS",
#"73",
#"88",
nil];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.selectedDataDelegate sendDataToMain:self.presetList[indexPath.row]];
NSLog(#"Delegate says: %#", self.presetList[indexPath.row]);
//The NSLog does display the correct cell I pressed, but no data passes back
[self dismissViewControllerAnimated:YES completion:nil];
}
Now here is my MainViewController.h file, this is where my textfield resides, and how I implement the delegate into this file...
#interface MainViewController : UIViewController<UITextFieldDelegate, CAAnimationDelegate, sendDataProtocol> //include protocol here
#property(strong,nonatomic)UITextField *morseTextfield;
- (void)sendDataToMain:(NSString*)text; //conform to protocol
#end
Now the MainViewController.m file...
- (void)viewDidLoad {
[super viewDidLoad];
TableViewController *tvc = [TableViewController new];
tvc.selectedDataDelegate = self;
}
//Protocol method declared here
- (void)sendDataToMain:(NSString*)text {
NSString *str = text;
self.morseTextfield.text = str;
NSLog(#"text: %#",text);
}
The textField NSLog never displays anything, so its not connecting to the delegate or something.
So something is clearly wrong but I'm not sure what. I used this stackoverflow answer as a reference but even then couldn't get it to work (refer to the passing data back section)
Passing Data between View Controllers
Also as a side note I'm coding everything programmatically. Any help is appreciated, thank you.
This is how i created the textfield...
//CONFORMING TO DELEGATES
self.morseTextfield.delegate = self;
//CREATING AND ADDING TEXTFIELD TO VIEW
self.morseTextfield = [[UITextField alloc]initWithFrame:CGRectMake((self.view.frame.size.width-300)/2,
(self.view.frame.size.height)/7, 300, 30.0)];
self.morseTextfield.borderStyle = UITextBorderStyleRoundedRect;
self.morseTextfield.font = [UIFont fontWithName:#"Avenir Next" size:20];
self.morseTextfield.textAlignment = NSTextAlignmentCenter;
self.morseTextfield.placeholder = #"Translate text into morse code";
[self.morseTextfield addTarget:self action:#selector(dismissKeyboard) forControlEvents:UIControlEventEditingDidEndOnExit];
self.morseTextfield.autocorrectionType = UITextAutocorrectionTypeNo;
self.morseTextfield.spellCheckingType = UITextSpellCheckingTypeNo;
self.morseTextfield.autocapitalizationType = UITextAutocapitalizationTypeNone;
[self.morseTextfield setReturnKeyType:UIReturnKeyDone];
[self.view addSubview:self.morseTextfield];
Possibly you set delegate to one instance of TableViewController and display another one.
- (void)viewDidLoad {
[super viewDidLoad];
TableViewController *tvc = [TableViewController new];
tvc.selectedDataDelegate = self;
}
in your code tvc will be just released from memory and you delegate will not work.
Also in you .h file this row is useless.
- (void)sendDataToMain:(NSString*)text; //conform to protocol
In your MainViewController update next method. You have to set delegate in it
- (void) tableViewBtnPressed:(UIBarButtonItem *)sender {
MCTableViewController *tableVC = [[MCTableViewController alloc] init];
tableVC.selectedDataDelegate = self;
UINavigationController *navBar = [[UINavigationController alloc]initWithRootViewController:tableVC];
[self.navigationController presentViewController:navBar animated:YES completion:nil];
}
As will be seen from my question, I'm a beginner to iOS development. I have looked at several tutorials and several questions but none seem to be covering my case (I'm probably missing something). I am simply trying to add elements to an array from one class, then call the method that reloads the table data from another class. However, when I try to reload the data after calling the relevant method from another class, the table fails to be loaded (no new data seems to be added). In fact, even the previous values of the array in the table seem to be gone.
Class A:
MyClassA.h
#interface MyClassA : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
UITableView *tableView;
NSMutableArray *Elements;
}
#property UITableView *tableView;
#property NSMutableArray *Elements;
-(void) addElement: (NSString *) ElementName;
#end
MyClassA.m
#implementation MyClassA
{
NSString *ElementName[10];
}
- (void) viewWillAppear:(BOOL)animated
{
NSLog(#"MyClassA: viewWillAppear");
ElementName[0] = #" 1 ";
ElementName[1] = #" 2 ";
ElementName[2] = #" 3 ";
Elements = [[NSMutableArray alloc]initWithObjects:ElementName[0], ElementName[1], ElementName[2],nil];
self.tableView.dataSource = self; // The table successfully loads with the data element
}
-(void) addElement: (NSString *) ElementName
{
NSLog(#"Entered addElement"); // This method is successfully accessed
Elements = [[NSMutableArray alloc]initWithObjects:ElementName[0], ElementName[1], ElementName[2],nil]; // The problem is here, printing data in this array shows they have no value
[self.tableView reloadData]; // The problem is here. This does not load the data
}
Class B:
MyClassB.h
#class MyClassA
#interface MyClassB : UIViewController
#property (nonatomic, strong) MyClassA *MyClassACall
-(IBAction) MyButtonClicked: (id) sender;
#end
MyClassB.m
#implementation MyClassB
#synthesize MyClassACall;
-(id) init
{
self = [super init]
if (self) {
NSLog(#"MyClassB init");
MyClassACall = [[MyClassA alloc] init];
}
return self;
}
-(IBAction)MyButtonClicked:(id)sender
{
NSLog("My button is clicked");
[self.MyClassAcall addElement:#"NewElement"];
}
I successfully get all the NSlogs, and the table loads the first time correctly with the provided data. However, when trying to add data by loading a method from another class, the table data remains the same and does not get reloaded. What am I missing here?
I have not loaded the whole code to keep this simple. I hope that this makes sense and please let me know if I could clarify. If a similar question exists, please point me to it and I appreciate your help.
I've made a mini tutorial here for you.
OK, so let's say we got a scenario like this:
There are two view controllers - ViewControllerA and ViewControllerB.
ViewControllerA will be in charge of adding items.
ViewControllerB will be in charge of displaying the items.
So ViewControllerA will look like this:
and ViewControllerB will look like this:
ViewControllerA.h
#import <UIKit/UIKit.h>
#interface ViewControllerA : UIViewController
#property (nonatomic, strong) NSMutableArray *arrItems;
#end
Here, we store the data source called arrItems as a NSMutableArray. We will pass this array to ViewControllerB later.
ViewControllerA.m
#import "ViewControllerA.h"
#import "ViewControllerB.h"
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self initViews];
}
-(void)initViews
{
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = #"View Controller A";
UIButton *btnAddItem = [[UIButton alloc] initWithFrame:CGRectMake(60, 200, 200, 50)];
[btnAddItem setTitle:#"Add Item" forState:UIControlStateNormal];
btnAddItem.backgroundColor = [UIColor greenColor];
btnAddItem.layer.cornerRadius = 5.0;
[btnAddItem addTarget:self action:#selector(addItem) forControlEvents:UIControlEventTouchUpInside];
UIButton *btnViewData = [[UIButton alloc] initWithFrame:CGRectMake(60, 300, 200, 50)];
[btnViewData setTitle:#"View Data" forState:UIControlStateNormal];
btnViewData.backgroundColor = [UIColor blueColor];
btnViewData.layer.cornerRadius = 5.0;
[btnViewData addTarget:self action:#selector(viewData) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btnAddItem];
[self.view addSubview:btnViewData];
// init empty array to hold data source items
self.arrItems = [[NSMutableArray alloc] init];
}
-(void)addItem
{
[self.arrItems addObject:#"New Element"];
NSLog(#"added a new element to arrItems, arrItems now has %u items", self.arrItems.count);
}
-(void)viewData
{
ViewControllerB *vcB = [[ViewControllerB alloc] initWithItems:self.arrItems];
[self.navigationController pushViewController:vcB animated:YES];
}
For the green "Add Item" button, we use a method like this to add item to our data source:
-(void)addItem
{
[self.arrItems addObject:#"New Element"];
NSLog(#"added a new element to arrItems, arrItems now has %u items", self.arrItems.count);
}
You'll notice when you tap on the green button, you'll get a console log telling you how many items is currently in your array.
Now when we're done adding items, we have the blue "View Data" button which pushes ViewControllerB onto the navigation stack:
-(void)viewData
{
ViewControllerB *vcB = [[ViewControllerB alloc] initWithItems:self.arrItems];
[self.navigationController pushViewController:vcB animated:YES];
}
ViewControllerB.h
#import <UIKit/UIKit.h>
#interface ViewControllerB : UIViewController <UITableViewDataSource, UITableViewDelegate>
-(id)initWithItems:(NSArray *)arrItems;
// ----------------------------------------------------------------
// view controller B data source is set from
// view controller A using init method shown above
// ----------------------------------------------------------------
#property (nonatomic, copy) NSArray *arrItems;
#property (nonatomic, strong) UITableView *tableView;
#end
Here, we've declared a init method that takes a NSArray parameter. This method will allow us to inject the data source array from ViewControllerA into ViewControllerB.
Per the usual, we also have the tableView in ViewControllerB.
ViewControllerB.m
-(id)initWithItems:(NSArray *)arrItems
{
self = [super init];
if(self)
{
self.arrItems = arrItems;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self initViews];
}
-(void)initViews
{
self.navigationItem.title = #"View Controller B";
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
self.tableView.dataSource = self;
self.tableView.delegate = self;
[self.view addSubview:self.tableView];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.arrItems.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
cell.textLabel.text = self.arrItems[indexPath.row];
return cell;
}
Notice in the initWithItems: method, we're storing the data source from the passed in parameter arrItems into ViewControllerB's self.arrItems:
-(id)initWithItems:(NSArray *)arrItems
{
self = [super init];
if(self)
{
self.arrItems = arrItems;
}
return self;
}
ViewControllerB can then use this data and display it in the tableView data source methods.
So you end up with something like this if you click Add Item five times:
Xcode's console also logs 5 items added:
2014-12-08 10:33:39.195 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 1 items
2014-12-08 10:33:40.099 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 2 items
2014-12-08 10:33:40.619 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 3 items
2014-12-08 10:33:41.123 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 4 items
2014-12-08 10:33:41.667 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 5 items
Is that more clear ?
First of all, i think, it's eligible way to make array in C way as elementName[10], but at this way it's overflow, you can simply use objective-c style with literals, or "initWithCapacity:10". Also Simplify your code, change it at this way:
#implementation MyClassA
{
//NSString *ElementName[10]; // you already have NSMutableArray, why did you do this ?
}
- (void) viewWillAppear:(BOOL)animated
{
NSLog(#"MyClassA: viewWillAppear");
Elements = [#[#"1",#"2",#"3"] mutableCopy];
self.tableView.dataSource = self;
}
-(void) addElement: (NSString *) ElementName
{
NSLog(#"Entered addElement"); // This method is successfully accessed
// You already have initialized array, you need simply to add new element
[elements addObject: elementName];
[self.tableView reloadData];
}
Okay, so. Couple of things...
The way you defined your Elements array is an old method of doing things, You do not need to declare the ivar just the property.
MyClassACall = [[MyClassA alloc] init]; is creating a new instance of MyClassA so whatever you set on that will not actually appear on your view controller you had.
If you need to display a model on one view controller and update it in another view controller i would recommend centralising that model so that both view controllers can access/mutate this model. Singleton is probably the easiest way to achieve that.
I have a programatically created UITextField added to the NavigationController as below (within a UITableViewController since I wanted a custom fixed search bar at the top).
In .h file
#property (nonatomic, strong) UITextField *searchText;
In .m file
#synthesize searchText;
self.searchText = [[UITextField alloc] init];
self.searchText.frame = CGRectMake(35, 234, 250, 27);
self.searchText.backgroundColor = Rgb2UIColor(255, 255, 255);
[self.navigationController.view addSubview:self.searchText];
self.searchText.delegate = self;
However none of the following methods get triggered
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
}
-(void)textFieldDidBeginEditing:(UITextField *)textField{
self.searchText.returnKeyType = UIReturnKeySearch;
}
- (void)textFieldDidEndEditing:(UITextField *)textField{
}
Can someone point me to the right direction on why my delegate does not work?
Better use uiseachbar from the objects panel. This comes with default search bar style and effects but is similar to uitextfield. You can set the delegate and listen to it the same way as you do for textview.
I want to create a custom tableView class, Which can be used in any view Controller. I have to just create tableview object and set an array and frame of tableview . Then this tableview will be add as subview on my view. and also give me a click event.
I just want to avoid writing tableview datasource and delegate method in every viewController class.
Take a viewController or tableviewController class and code all the delegates and data source methods there. now in you view controller where you want to make it as a subview call the tableview class and add it as a subview.
EX:
TableviewContrller *libaray =[TableviewContrller new];
[libaray willMoveToParentViewController:self];
[self.view addSubview:libaray.view];
[self addChildViewController:libaray];
To hide write this code in your tableview controller class
[self.view removeFromSuperView];
As you are using a reusable class you need to send the array information to that class. along with it it will be better to send either class name or setting tag value to tableview
So in your tableview class write this
-(id)initWithInformationArray :(NSMutableArray *)dataArray andTagValueforTableview :(int) tagValue
{
self = [super init];
if (self != nil)
{
NSLog(#"%#", dataArray);
}
return self;
}
Now sub viewing will be like this
TableviewContrller *libaray =[[TableviewContrller alloc]initWithInformationArray:YOURARRAY andTagValueforTableview:TAGVALUE];
[libaray willMoveToParentViewController:self];
[self.view addSubview:libaray.view];
[self addChildViewController:libaray];
Hope this will help.
May be you can use UITableViewController.
UITableViewController is a subclass of UIViewController, when you create a subclass of UITableViewController, the template has the usual methods of tableview datasource and delegate methods.
You'll need to create a custom class and create your own delegate in that class for UITableView. Now whenever you create a UITableView assign that custom class as the class for UITableView.
If you don't know how to create custom delegates then check below links:
http://www.alexefish.com/post/522641eb31fa2a0015000002
http://ios-blog.co.uk/tutorials/quick-tip-create-your-own-objective-c-delegate-protocol/
Hope this will help you :)
You can create BaseTableView class.
#interface BaseTableView : UITableView <UITableViewDelegate, UITableViewDataSource>
{
NSArray* listObject;
}
#property (nonatomic, retain) NSArray *listObject;
-(id) initWithFrame:(CGRect)frame style:(UITableViewStyle)style;
#end
#implementation BaseTable
#synthesize listObject;
-(id) initWithFrame:(CGRect)frame style:(UITableViewStyle)style
{
if(self = [super initWithFrame:frame style:style])
{
self.dataSource = self;
self.delegate = self;
}
return self;
}
-(void)setListObject:(NSArray *)listObjectRef
{
[listObject release];
listObject = [listObjectRef retain];
[self reloadData];
}
-(void) dealloc
{
[listObject release];
[super dealloc];
}
#end
Inherit this class for specific use and override following methods according to needs
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
In your ViewController class use following code
SpecificTableView *table = [[SpecificTableView alloc] init];
[table setListObject:((FRFTReportList*)obj)];
Hopefully this will help.
I have been following this tutorial on YouTube (part 1 and part 2).
I have completed both videos and have hooked up the view controller with the parent view controller using this code:
- (IBAction)searchButtonClicked:(id)sender {
NSLog(#"It works.");
SearchViewController *searchViewControl = [self.storyboard instantiateViewControllerWithIdentifier:#"SearchControllerNav"];
[self presentViewController:searchViewControl animated:YES completion:nil];
}
This code indeed works since this is the same format that I use for my other modal view controllers, so i know that's not the problem.
Anyway, when I tap on the search button in the view controller, it should pop up the SearchViewController. However, the app crashes instead and it gives me this error message:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UITableViewController loadView] loaded the "jp7-vt-IdA-view-Jer-xW-qlD" nib but didn't get a UITableView.'
I am using Storyboards for this app.
Is there something that I'm missing? Thank you in advance.
A side question: I'm also getting a warning, saying Comparison between pointer and integer ('BOOL *' (aka 'signed char *') and 'int') whenever isFiltered == YES is shown. Is there anyway to fix it?
Here is the code for SearchViewController:
SearchController.h
#import <UIKit/UIKit.h>
#interface SearchViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate> {
}
- (IBAction)cancelButtonTapped:(id)sender;
#property (weak, nonatomic) IBOutlet UISearchBar *mySearchBar;
#property (weak, nonatomic) IBOutlet UITableView *myTableView;
#property (nonatomic, strong) NSMutableArray *itemsInCloudApp;
#property (nonatomic, strong) NSMutableArray *filteredList;
#property BOOL *isFiltered;
#end
SearchViewController.m
#import "SearchViewController.h"
#interface SearchViewController ()
#end
#implementation SearchViewController
#synthesize mySearchBar, myTableView, itemsInCloudApp, filteredList, isFiltered;
- (void)viewDidLoad
{
[super viewDidLoad];
// Set title.
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
titleLabel.text = #"Search";
titleLabel.adjustsFontSizeToFitWidth = YES;
titleLabel.clipsToBounds = YES;
titleLabel.numberOfLines = 1;
titleLabel.font = [UIFont fontWithName:#"Avenir-Medium" size:18];
titleLabel.textColor = [UIColor blackColor];
titleLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight;
titleLabel.textAlignment = NSTextAlignmentCenter;
[titleLabel sizeToFit];
self.navigationItem.titleView = titleLabel;
// Alloc and init list.
itemsInCloudApp = [[NSMutableArray alloc]initWithObjects:#"http://www.apple.com/", #"http://www.trijstudios.com/", #"http://www.google.com/", #"http://www.squarespace.com/", #"http://www.youtube.com/", nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (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 [filteredList count];
} else {
return [itemsInCloudApp count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
if (isFiltered == YES) {
cell.textLabel.text = [filteredList objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [filteredList objectAtIndex:indexPath.row];;
} else {
cell.textLabel.text = [itemsInCloudApp objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [itemsInCloudApp objectAtIndex:indexPath.row];
}
return cell;
}
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (searchText.length == 0) {
// Set bollean flag
isFiltered = NO;
} else {
// Set boolean flag
isFiltered = YES;
// Alloc and init our fliteredData
filteredList = [[NSMutableArray alloc] init];
// Fast enumeration
for (NSString *name in itemsInCloudApp) {
NSRange nameRange = [name rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (nameRange.location != NSNotFound) {
[filteredList addObject:name];
}
}
}
// Reload tableView
[myTableView reloadData];
}
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[mySearchBar resignFirstResponder];
}
- (IBAction)cancelButtonTapped:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
NOTE: There are a few edits that I made to fit my needs.
have you tried changing your #interface SearchViewController : UITableViewController to #interface SearchViewController : UIViewController
I strongly suspect that either you have not attached your UITableview as View in XIB or your class should be derived UIViewController instead of UITableviewController class..
I had a similar error. I was able to resolve it using #Dinesh's suggestion, but I didn't like this because I was afraid that there could be some unintended consequences.
What I figured out was that when I looked at the scene hierarchy in the storyboard, I noticed that I had this structure (sorry, I don't know how to format this - it's supposed to be a tree structure):
View Controller
View
Table View
When I took out the View that sat in the middle, my problem went away. However, before doing so, you need to delete any outlets that might exist between the view and either the view controller or the table view. After you make sure that these are gone, follow these final steps:
Drag the Table View so that it is a direct descendant of the View Controller.
Delete the View
Command-Drag from the View Controller to the Table View, thereby creating a new outlet directly between the two.
Also, leave the .h file as a subclass of UITableView (not UIView).
Anyway, that solved the issue for me. If anyone comes across this, I hope that it helps.
For you side question regrading the warning, the warning comes because you have made the BOOL isFiltered as a pointer.
For your first problem, you needed to check the storyboard. I am sure that your file owner's view is connected to a UIView. To solve this, you must drag UITableView and view must be connected to the UITableView.
For your second problem, declare BOOL as
#property(assign,nonatomic) BOOL isFiltered;
I encountered this when building a iOS7 Universal app with a simple, dumb error: I'd built part of the iPhone app only, but had the scheme set to iPad simulator. After getting the error and looking here, I saw my mistake, switched the scheme to iPhone, and the app ran with the proper storyboard for the proper simulator. Hope that helps.