UIPopoverController showing empty frame - ios

So I am trying to display a UITableView inside a UIPopoverController using the piece of code shown below
vc = [[ActionsViewController alloc] init];
initWithContentViewController:vc];
actionsController = [[UIPopoverController alloc] initWithContentViewController:vc];
actionsController.delegate = self;
NSLog(#"Try to sho it ");
[actionsController presentPopoverFromBarButtonItem:(UIBarButtonItem*)sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
And this is ActionsViewController.m which is a subclass of UITableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray* list = [[NSMutableArray alloc] initWithCapacity:4];
self.actionList = list;
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 400.0);
[self.actionList addObject:#"Print as book"];
[self.actionList addObject:#"Print page"];
[self.actionList addObject:#"Save Page"];
[self.actionList addObject:#"Share"];
}
- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(#"in number of section");
return 1;
}
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString* lab = [self.actionList objectAtIndex:indexPath.row];
NSLog(#"here in there");
cell.textLabel.text = lab;
return cell;
}
- (NSInteger)numberOfRowsInSection:(NSInteger)section
{
return [self.actionList count];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.delegate != nil) {
[self.delegate actionSelected:indexPath.row];
}
}
The corresponding .h file
#import <UIKit/UIKit.h>
#protocol KLActionsViewControllerDelegate
- (void)actionSelected:(NSInteger)index;
#end
#interface KLActionsViewController : UITableViewController <UITableViewDataSource,UITableViewDelegate>
#property (nonatomic, retain) NSMutableArray* actionList;
#property (nonatomic, assign) id<KLActionsViewControllerDelegate> delegate;
#end
Also, I don't think the functions cellForRowAtIndexPath and numberOfSectionsInTableView are getting called because I don't see any console output.
EDIT: This is what I see in the popover
:

In viewDidLoad I added self.tableView = [[UITableView alloc] init]

I guess, the problem would be in that line:
vc = [[ActionsViewController alloc] init];
if you have a NIB file, you should load the UIViewController with using it.
vc = [[ActionsViewController alloc] initWithNibName:#"ActionViewController" bundle:nil];
// the NibName must be the exact name of XIB file without extension.
OR/AND
you should set the popoverContentSize:
[actionController setPopoverContentSize:vc.view.frame.size];
I hope it helps a bit for you.
UPDATE:
it seems it is not an UIPopoverController problem, just a simple UITableViewController delegate issue.
in that line:
actionsController.delegate = self;
you should set that class as delegate which implements the UITableViewDelegate. basically it is the UITableViewController itself like
actionsController.delegate = actionController;
therefore you should not replace this in that case if you haven't implemented the delegate callback methods in the self which the new delegate class is. you simple steal the chance from the class which was really delegated to answer the callbacks, and in you new delegate class you don't answer the callbacks.
this would be the reason why you are seeing the empty table, without the datas.

You need to load the table view via (last line of viewdidload :
[self.tableView reloadData];
that will trigger the table view methods to action. Put a breakpoint in the various tableview methods particularly in -
(NSInteger)numberOfRowsInSection:(NSInteger)section
{
return [self.actionList count];
}
If this does not get called your tableview is not loaded.

UITableViewController is implicit set datasource and delegate, there is no need to set explicitly datasource and delegate.
Remove UITableViewDataSource,UITableViewDelegate from .h file
#import <UIKit/UIKit.h>
#protocol KLActionsViewControllerDelegate
- (void)actionSelected:(NSInteger)index;
#end
#interface KLActionsViewController : UITableViewController
#property (nonatomic, retain) NSMutableArray* actionList;
#property (nonatomic, assign) id<KLActionsViewControllerDelegate> delegate;
#end
and also remove this line **actionsController.delegate = self;
vc = [[ActionsViewController alloc] init];
actionsController = [[UIPopoverController alloc] initWithContentViewController:vc];
[actionsController presentPopoverFromBarButtonItem:(UIBarButtonItem*)sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

Related

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"];
}

UITableView from separate class

Case is following: I want to create UITableView from separate class.
Currently I have following:
// Menu.h
#interface Menu : UITableViewController <UITableViewDelegate, UIAlertViewDelegate> {
UITableView *tableView;
}
#property (nonatomic,retain) NSMutableArray *navigationItems;
- (void)initMenu:(UIView *)view;
#end;
Then
// Menu.m
#import <Foundation/Foundation.h>
#import "Menu.h"
#implementation Menu
- (void) initMenu:(UIView *)view {
self.navigationItems = [[NSMutableArray alloc] initWithObjects:#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight",#"Nine",#"Ten",nil];
UIView *mainmenu=[[UIView alloc]initWithFrame:CGRectMake(0, 50, 320, 420)];
[mainmenu setBackgroundColor:[UIColor yellowColor]];
[view addSubview:mainmenu];
UITableView *menutableView = [[UITableView alloc] initWithFrame:view.bounds style:UITableViewStylePlain];
menutableView.backgroundColor = [UIColor whiteColor];
menutableView.delegate = self;
menutableView.dataSource = self;
[mainmenu addSubview:menutableView];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableViewi cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableViewi dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [self.navigationItems objectAtIndex:indexPath.row];
return cell;
}
#end
And in different .m file I call method:
...
#import "Menu.h"
...
- (void)viewDidLoad
{
[super viewDidLoad];
...
Menu *menu = [[Menu alloc] init];
[menu initMenu: self.view];
}
Running this will crash application and Xcode won't give any detailed report. However, if I combine Menu.m to the .m file where I'm calling "initMenu" it won't crash.
Also if I comment out menutableView.dataSource = self; it will run with our crash (no rows in table of course...).
Passing a view into an init method and then creating/adding subviews in said init method is an odd design pattern. Change your Menu class to a viewcontroller, then move your UIView and UITableView declarations to the viewDidLoad method. The crash is likely happening because the tableview is trying to display data before its parent view has finished loading.

UITableViewController delegate

I have a UITableViewController class that I call "MasterViewController".
From within MasterViewController I want to display a tableview that uses a different UITableViewController (not MasterViewController). I am doing this as another tableview is already using MasterViewController as its delegate and datasource.
I have the following logic in a method of MasterViewController;
ToTableViewController *toController = [[ToTableViewController alloc] init];
UIView *toView = [[UIView alloc] initWithFrame:CGRectMake(10,10,250,200)];
//toView.backgroundColor = [UIColor redColor];
UITableView *toTableView = [[UITableView alloc] initWithFrame:CGRectMake(10,10,220,180) style:UITableViewStylePlain];
[toTableView setDelegate:toController];
[toTableView setDataSource:toController];
[toView addSubview:toTableView];
[self.view addSubview:toView];
[toTableView reloadData];
I want the ToTableViewController to be the delegate and datasource for this new tableview (toTableView).
The problem is that my ToTableViewController cellForRowAtIndexPath method is not being called. In fact, none of the delegate methods are being called.
Any feedback would be appreciated.
Tim
I am pretty sure your issue is that the toController is being released too early. Using ARC (I assume you are too), I played around with it following what you are trying todo. And I got the same result where the delegate methods appeared NOT to get called. What solved it was to NOT use a local variable for the toController. Instead declare it as a member to the MasterViewController class like
#property (strong, nonatomic) ToTableViewController *toController;
then use the variable name _toController to refer to it in the code.
EDIT: just to be clear in my first test I had ToTableViewController inherit from a UITableViewController. Since as such I really didn't need that added UITableView you are creating and attaching the delegates too (you could just use the _toController.view directly) SO on this second test I created a ToTableViewController from scratch inheriting from the delegate protocols where the separate UITableView becomes necessary. Just for completeness here is the code that works:
ToTableViewController.h
#import <Foundation/Foundation.h>
#interface ToTableViewController : NSObject <UITableViewDelegate, UITableViewDataSource>
#end
ToTableViewController.m
#import "ToTableViewController.h"
#implementation ToTableViewController
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 13;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *str1 = #"Row #";
cell.textLabel.text = [str1 stringByAppendingFormat:#"%d", indexPath.row+1];
return cell;
}
#end
MasterViewController.m (I declare the toController in the .m file as shown but could do so the .h file instead...)
#import "MasterViewController.h"
#import "ToTableViewController.h"
#interface MasterViewController ()
#property (strong, nonatomic) ToTableViewController *toController;
#end
#implementation MasterViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_toController = [[ToTableViewController alloc] init];
UIView *toView = [[UIView alloc] initWithFrame:CGRectMake(10,10,250,200)];
toView.backgroundColor = [UIColor redColor];
UITableView *toTableView = [[UITableView alloc] initWithFrame:CGRectMake(10,10,220,180) style:UITableViewStylePlain];
[toTableView setDelegate:_toController];
[toTableView setDataSource:_toController];
[toView addSubview:toTableView];
[self.view addSubview:toView];
}
#end

How to pass a value from one UIViewController to another

I am making an app where I have to pass a value from a second class to a first class. I have created a delegate method for that in second class.
In second class I have a UITextField, and if enter any text in this textfield it should be passed to a cell in a UITableView in first view.
However, in my case the value is not being passed properly. What have I done wrong?
This is my code:
second.h
#import <UIKit/UIKit.h>
#protocol secondDelegate<NSObject>
#required
- (void)setsecond:(NSString *)inputString;
#end
#interface second : UIViewController {
IBOutlet UITextField *secondtextfield;
id<secondDelegate>stringdelegate;
NSString *favoriteColorString;
}
#property (nonatomic, retain) UITextField *secondtextfield;
#property (nonatomic, assign) id<secondDelegate>stringdelegate;
#property (nonatomic, copy) NSString *favoriteColorString;
#end
second.m
#import "second.h"
#implementation second
#synthesize stringdelegate, secondtextfield, favoriteColorString;
- (void)viewWillDisappear:(BOOL)animated {
[[self stringdelegate] setsecond:secondtextfield.text];
favoriteColorString=secondtextfield.text;
NSLog(#"thuis check:%#", favoriteColorString);
}
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
[theTextField resignFirstResponder];
return YES;
}
- (void)viewDidLoad {
[super viewDidLoad];
//[[self stringdelegate] setsecond:secondtextfield.text];
//favoriteColorString = secondtextfield.text;
//NSLog(#"thuis check:%#", favoriteColorString);
}
#end
first.h
#import <UIKit/UIKit.h>
#import "second.h"
#import "TextviewExampleAppDelegate.h"
#interface first : UITableViewController<secondDelegate> {
//TextviewExampleAppDelegate *app;
TextviewExampleAppDelegate *check;
}
first.m
#implementation first
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
cell.textLabel.text = #"message";
cell.detailTextLabel.text = check.favoriteColorString;
NSLog(#"this second check:%#", check.favoriteColorString);
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
second *viewtwo = [[second alloc] initWithNibName:#"second" bundle:nil];
//viewtwo.favoriteColorString = indexPath;
viewtwo.stringdelegate = self;
[self.navigationController pushViewController:viewtwo animated:YES];
[viewtwo release];
}
- (void)setsecond:(NSString *)inputString {
if (nil != self.stringdelegate) {
[self.stringdelegate setsecond:inputString];
}
[self.tableView reloadData];
}
#end
remove delegate methods.
import your second class to first one.
in 2nd class import first class and implement id firstClass variable there.
when you pushing 2nd class, set id from (3) to self.
when you'v done and ready to pass it, set firstClass.passedValue = passingValue
pop second class
for example:
//first.h:
#import "second.h"
#class second
//second.h:
#import "first.h"
#class first
...
id firstClass;
//first.m:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
second *viewtwo =[[second alloc]initWithNibName:#"second" bundle:nil];
[self.navigationController pushViewController:viewtwo animated:YES];
viewtwo.firstClass = self;
[viewtwo release];
}
//second.m:
firstClass.passedValue = self.passingValue;
Please refer following rough scratch:
in application delegate .h
Create variable
NSString *varStr;
Assign Property
#propery (nonatomic, retain) NSString *valStr;
In delegate .m
#synthesize varStr;
initialize var
varStr = [NSString strinWithFormat:#"Hi"];
in First class
create delegate var;
delegate class *var = (delegate class*)[[UIApplication sharedApplication] delegate];
set value
var.varStr = [NSString strinWithFormat:#"First"];
get value
NSLog (#"%#",var.varStr);
in Second class
create delegate var;
delegate class *var = (delegate class*)[[UIApplication sharedApplication] delegate];
set value
var.varStr = [NSString strinWithFormat:#"Second"];
get value
NSLog (#"%#",var.varStr);

Resources