I am trying to connect a UITableViewController to a UIView using storyboards. I have a TabBarController that connects to a Navigation Controller that displays a UITableViewController, displaying a small array. I want to click on a row and that trigger a simple UIView with a label, still displayed in the UINavigationController so I can navigate back to the UITableViewController
I can get the UITableViewController to display OK, with the array, but I can't get the row to trigger when I select it.
This is my UITableViewController (AtoZController.m) file:
#import "AtoZController.h"
#import "StoreDetailsView.h"
#interface AtoZController ()
#end
#implementation AtoZController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = NSLocalizedString(#"A to Z", #"An A to Z List of Stores");
AtoZArray = [[NSMutableArray alloc] init];
[AtoZArray addObject:#"Apple"];
[AtoZArray addObject:#"Boots"];
[AtoZArray addObject:#"Topman"];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
}
#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.
return [AtoZArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSInteger row = [indexPath row];
cell.textLabel.text = [AtoZArray objectAtIndex:row];
return cell;
}
I have a segue connected, named storeDetailsSegue, from the UITableViewController to a UIView. I am attempting to use the prepareForSeque method to trigger the next view but have had no luck with the following code.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
StoreDetailsView *detail = [self detailForIndexPath:path];
[segue.destinationViewController setDetail:detail];
}
As it keeps saying there is an error as there is 'No visible #interface for "AtoZController declares the selector 'detailForIndexPath'". I may be doing something completely wrong as I have never used storyboards before. What I want is for a simple UIView to display a label that dynamically changes to display the row number that has been selected.
I don't know if the UITableViewController should infact be a UITableView but as I have never used segues or storyboards I have no idea what could be causing the problem.
Any advice at all would be greatly appreciated.
UPDATE:
So I managed to get the UIViewController to display but still can't get the label to update before I display the view.
Related
I have several UIWindows in my app. Some UIWindows have very high window levels. i.e.
window.windowLevel = currentWindowLevel+1;
For some reason when turning on accessibility support, the system insists on reading out the accessibility labels of views located in the lower level window, even in cases where the views aren't even visible.
This minimal example exemplifies this behavior.
With accessibility support turned on, try to press the label in the red window. The system will read out the text from the underneath table view instead
#interface ViewController () <UITableViewDataSource>
#property (weak, nonatomic) IBOutlet UITableView *tableview;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableview.dataSource = self;
[self.tableview registerClass:[UITableViewCell class] forCellReuseIdentifier:#"cell"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
UIWindow *w = [[UIWindow alloc] initWithFrame:self.view.bounds];
w.windowLevel = self.view.window.windowLevel + 1;
w.backgroundColor = [UIColor redColor];
w.hidden = NO;
w.isAccessibilityElement = YES;
UILabel *l = [[UILabel alloc] init];
l.text = #"KUKUKUKUKUKUKUKLU";
[l sizeToFit];
l.frame = CGRectOffset(l.frame, 40, 100);
[w addSubview:l];
w.accessibilityLabel = #"Read this outloud instead";
static id window;
window = w;
});
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 100;
}
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
cell.textLabel.text = #"Test";
return cell;
}
#end
Solution is to set the attribute
Window.accessibilityViewIsModal = YES;
In Xcode 5.1, using StoryBoards, I'm having trouble getting a custom UITableViewCell to show it's contents. The cell appears -- I can tap to select it -- but the label text doesn't appear.
I've given the Cell my custom class GCell and identifier MyCell
I've connected an IBOutlets to a label in the prototype cell.
#import <UIKit/UIKit.h>
#interface GCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *nameLabel;
#end
In my class that extends UITableViewController, I have
#implementation PayGroupViewController
- (id)initWithStyle:(UITableViewStyle)style
{
NSLog (#"[PayGroupViewController] initWithStyle");
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
// [self.tableView registerClass:[GCell class] forCellReuseIdentifier:#"MyCell"];
_groups = [NSMutableArray arrayWithCapacity:20];
GroupModel *gm = [[GroupModel alloc] init];
gm.title = #"DINNER";
gm.names = [NSMutableArray arrayWithCapacity:10];
[gm.names addObject:#"Me"];
[gm.names addObject:#"Albert"];
[_groups addObject:gm];
NSLog (#"[PayGroupViewController] viewDidLoad. [self groups].count:%d" ,[self groups].count);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog (#"[PayGroupViewController] tableView. [self groups].count:%d" ,[self groups].count);
return [self groups].count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog (#"[PayGroupViewController] tableView cellForRowAtIndexPath");
GCell *c = (GCell *)[tableView dequeueReusableCellWithIdentifier:#"MyCell" forIndexPath:indexPath];
GroupModel *group = [self.groups objectAtIndex:indexPath.row];
NSLog (#"[PayGroupViewController] group.title: %#",group.title); // Outputs "DINNER"
c.nameLabel.text = group.title; // It does not show up
NSLog (#"[PayGroupViewController] cell: %#",c); // outputs <GCell: 0x9976ed0, etc. so it does exist
NSLog (#"[PayGroupViewController] cell.nameLabel: %#",c.nameLabel); // outputs (null)
return c;
}
Also, here is the entire xCode project if anyone cares to take a look.
http://www.brainjelly.com/WhoPaid.zip
Note that the prototype cell has a Disclosure Indicator Accessory, but that doesn't appear either.
Thanks… I've looked extensively over the other posts with this issue but none of those solutions helped me.
There are 2 problems in your xCode project.
You shouldn't register custom cell class in your code for prototype cells. Storyboard does that for you. When you register same class, you are basically overriding the one created by storyboard.
In your prototype cell there is an undefined outlet named "title", which is connected to Content View. Define or delete it.
After these, clear the project and recompile, it should be ok.
I'm pretty new to xcode so I'm having trouble performing this task. I've created a table with a search bar with names that are passed to a detail view with a UILabel that shows the corresponding name of the cell clicked. The search bar works and it filters the results. I used this tutorial to help me with it:
http://www.appcoda.com/how-to-add-search-bar-uitableview/
Now I want to have an image in the detail view instead of a UILabel, that corresponds to each of the cells but I'm having trouble figuring out how to do that. Here is the code I'm working with:
TableViewController.h:
#interface SearchViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, strong) IBOutlet UITableView *tableView;
TableViewController.m:
#interface SearchViewController ()
#end
#implementation SearchViewController {
NSArray *cards;
NSArray *searchResults;}
#synthesize tableView = _tableView;
-(void)viewDidLoad
{
[super viewDidLoad];
cards = [NSArray arrayWithObjects:
#"Snivy",
#"Servine",
#"Serperior",
#"Tepig",
#"Pignite",
#"Emboar",
#"Oshawott",
#"Dewott",
#"Samurott", nil];
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResults = [cards filteredArrayUsingPredicate:resultPredicate];}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return [cards count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SearchCardCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [cards objectAtIndex:indexPath.row];
}
return cell;}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"ShowSearchCard"]) {
SearchCardViewController *destViewController = segue.destinationViewController;
NSIndexPath *indexPath = nil;
if ([self.searchDisplayController isActive]) {
indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
destViewController.cardName = [searchResults objectAtIndex:indexPath.row];
} else {
indexPath = [self.tableView indexPathForSelectedRow];
destViewController.cardName = [cards objectAtIndex:indexPath.row];
}
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
[self performSegueWithIdentifier: #"ShowSearchCard" sender: self];
}
}
UIViewController.h:
#property (strong, nonatomic) IBOutlet UILabel *cardLabel;
#property (strong, nonatomic) NSString *cardName;
#property (strong, nonatomic) NSArray *searchCardDetail;
UIViewController.m:
#implementation SearchCardViewController
#synthesize cardLabel;
#synthesize cardName;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
cardLabel.text = cardName;
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidUnload {
[super viewDidUnload];
}
So in detail, the "cards" are the names in the table. Right now, it segue to a UILabel of the name of the card and I would like to have it instead, segue to the corresponding image of the card in the regular table and filtered table when searched. I appreciate your time and help! Thanks!
I'm not sure if I understanded your question correctly, but I would use one of these three approaches:
1st:
Easiest way is to follow this tutorial
2nd: Create custom cell which you will use instead of default cell. To get you on track, you can check this good tutorial How to create custom cell. In your custom cell, you'll declare additional variable, UIImage, which will or won't be displayed in your table view. Point is, you can send it in prepareForSegue method to your detailViewController.
3rd: Create NSDictionary where you will have values (images of your items) for keys (name of item). Then, pass it in prepareForSegue to your NSDictionary in detailViewController. After that, just assign your UIImage to UIImageView in your detailViewController based on what name of item did you receive. (So you'll still be sending name and then detailImage = [yourdict objectForKey:myItemName];)
I'm writing this on my windows laptop, because I'm not at work right now (that's where I have my mac mini), so there may be some syntax errors in my answer :)
Im trying to make a small project. Could someone help me understand why the segue does not work?
#import "CarTableViewController.h"
#import "CarTableViewCell.h"
#import "CarDetailViewController.h"
#interface CarTableViewController ()
#end
#implementation CarTableViewController
#synthesize carMakes = _carMakes;
#synthesize carModels = _carModels;
#synthesize carImages = _carImages;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.carMakes = [[NSArray alloc]
initWithObjects:#"Chevy",
#"BMW",
#"Toyota",
#"Volvo",
#"Smart", nil];
self.carModels = [[NSArray alloc]
initWithObjects:#"Volt",
#"Mini",
#"Venza",
#"S60",
#"Fortwo", nil];
self.carImages = [[NSArray alloc]
initWithObjects:#"chevy_volt.jpg",
#"mini_clubman.jpg",
#"toyota_venza.jpg",
#"volvo_s60.jpg",
#"smart_fortwo.jpg", nil];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (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.
return _carModels.count;
}
#pragma mark - Table view data source
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"carTableCell";
CarTableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CarTableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.makeLabel.text = [self.carMakes
objectAtIndex: [indexPath row]];
cell.modelLabel.text = [self.carModels
objectAtIndex:[indexPath row]];
UIImage *carPhoto = [UIImage imageNamed:
[self.carImages objectAtIndex: [indexPath row]]];
cell.carImage.image = carPhoto;
return cell;
}
The code work´s fine, and loads a tableView, but I need to go to CarDetailViewControler and I´m using the following code, but it does not work.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowCarDetails"])
{
CarDetailViewController *detailViewController =
[segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView
indexPathForSelectedRow];
detailViewController.carDetailModel = [[NSArray alloc]
initWithObjects: [self.carMakes
objectAtIndex:[myIndexPath row]],
[self.carModels objectAtIndex:[myIndexPath row]],
[self.carImages objectAtIndex:[myIndexPath row]],
nil];
}
}
In the storyboard did you use a cell prototype? If so, did you control-drag from the prototype to the destination viewcontroller and create the named segue?
The method you are using requires the segue to be defined completely in the storyboard, meaning the trigger for the segue is tied to the cell prototype.
You can manually trigger a segue using:
[self performSegueWithIdentifier:#"ShowCarDetails" sender:self];
in your:
tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath as an alternative.
i have created a xib file in Xcode 4.2 and i am looking at getting it to the tabbed application but i have been trying and I'm a little bit new to Xcode , coding so thats why i need your help i have my code below but there are a few little errors but what i would like you lot to help me with is maybe getting to a tabbed application... well telling me what to do anyhow. heres a video for you to have a look at in case i haven't explained it correct (this is my video i did just for this question http://www.youtube.com/watch?v=e7R5_kGClM0 hope the video help but more importantly you can help me.
There is the .h but the is no errors in this
#import <UIKit/UIKit.h>
#interface myview : UIViewController <UITableViewDelegate, UITableViewDataSource, UIPickerViewDelegate, UIPickerViewDataSource>
#property (strong, nonatomic) IBOutlet UITableView* tableView;
#property (strong, nonatomic) IBOutlet UIPickerView* pickerView;
#property (strong, nonatomic) NSMutableArray* tableData;
#property (strong, nonatomic) NSMutableArray* pickerData;
#end
This is the .m but i will break it up
#import "myview.h"
#implementation myview
#synthesize tableView, pickerView, tableData, pickerData;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
this is the -(void)viewDidLoad];etc..
- (void)viewDidUnload
{
[super viewDidUnload];
tableView.delegate = self;
tableView.dataSource = self;
pickerView.delegate = self;
pickerView.dataSource = self;
tableData = [[NSMutableArray alloc] init]; // table starts empty
pickerData = [[NSMutableArray alloc] initWithObjects:#"1", #"2", #"3", #"4", #"5", nil]; // picker starts with values 1, 2, 3, 4, 5
[tableView reloadData];
[pickerView reloadAllComponents]; // Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(bool)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView {
//The number of sections in UITableView
return 1;
}
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {
// The number of rows in the UITableView
return [tableData count];
}
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [ [UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
// Set the table cell text to the appropriate value in tableDate
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Whatever happens when you select a table view row.
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
// The number of sections in the UIPickerView
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
// The number of rows in the UIPickerView
return [pickerData count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
// The data for each row in the UIPickerView
return [pickerData objectAtIndex:row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
// whatever you want to happen when a row is selected.
// here I am assuming you want to remove from the picker and add to the table on selection
[tableData addObject:[pickerData objectAtIndex:row]];
[pickerData removeObjectAtIndex:row];
[tableView reloadData];
[pickerView reloadAllComponents];
}
#end
Here Are The Errors In The Code There are Two
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
^^^^^^^^^^^^^^^^^
**Local declaration of 'tableView hides instance variable**
Second error
[pickerView reloadAllComponents];
^^^^^^^^^^^^^^
Local declaration of 'pickerView hides instance variable
Thanks Very Much I Hope To Here From You Soon !!!
Use this, "tableView hides instance variable" occurs if local variable and instance variable have the same name.
- (UITableViewCell*)tableView:(UITableView*)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cell";
UITableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [ [UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
and for pickerView use this
[self.pickerView reloadAllComponents];