I've got a Master-Detail Applicaton in Xcode with a TableView and a SearchDisplayController.
In the TableView I have got a NSArray with 10 entries.
If I use the Searchbar, the DetailView shows correctly the entry I clicked on.
But if I do not use the Searchbar and click in the TableView on an entry, the DetailView every time shows me the first entry of the TableView.
What can I do to fix it?
MasterViewController.m: http://i.imgur.com/ZS1Oe.png
MasterViewController.h:
#import <UIKit/UIKit.h>
#interface DPMasterViewController : UITableViewController
#property (nonatomic, strong) IBOutlet UITableView *tableView;
#end
DetailViewController.m: http://i.imgur.com/AkVJ8.png
DetailViewController.h:
#import <UIKit/UIKit.h>
#interface DPDetailViewController : UIViewController
#property (strong, nonatomic) id detailItem;
#property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
#end
Sorry that I use pictures, but I think it is easier for you to check. :)
I hope you can help me!
If anything is missing, just tell me.
EDIT:
In This Method after the else every time the indexPath.row = 0. I don't know how to fix it :(
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showDetail"]) {
DPDetailViewController *destViewController = segue.destinationViewController;
NSIndexPath *indexPath = nil;
if ([self.searchDisplayController isActive]) {
indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
destViewController.detailItem = [searchItemList objectAtIndex:indexPath.row];
} else {
indexPath = [self.tableView indexPathForSelectedRow];
destViewController.detailItem = [itemList objectAtIndex:indexPath.row];
}
}
}
It looks like you are not performing any actions when you click on a cell of the tableView that is not part of the searchDisplayController, so try to change your tableView:didSelectRowAtIndexPath: method to
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"showDetail" sender:self];
}
Related
I have tableview with the cells and every cell pushes detailViewController. I want to assign text of the cell to a textLabel in detailViewController.
.h class of masterView
#property (strong,nonatomic) NSString *selectedCellText;
.m class of masterView
#synthesize selectedCellText = _selectedCellText;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedCellText = [[[tableView cellForRowAtIndexPath:indexPath] textLabel] text];
NSLog(#"%#",self.selectedCellText);
}
Here NSLog prints name of the cell
.h of detailViewController
#property (nonatomic, copy) listOfTricksViewController *aReference;
.m of detailViewController
#synthesize aReference = _aReference;
- (void)viewDidLoad
{
[super viewDidLoad];
self.detailViewName.text = self.aReference.selectedCellText;
NSLog(#"%#",self.aReference.selectedCellText);
}
Here NSLog prints null.
Modify your method prepareForSegue like this :
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"detailTrick"])
{
DetailViewController *detailViewController = (DetailViewController *)segue.
NSString *object = nil;
NSIndexPath *indexPath = nil;
indexPath = [self.tableView indexPathForSelectedRow];
// Pass data
detailViewController.aString = self.cellObjects[indexPath.row];
}
}
You need to call your DetailViewController and forward the data to this controller (supposing here you have a #property aString in your header of DetailViewController)
.h of detailViewController
#property (nonatomic, strong) NSString *aString;
.m of detailViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.detailViewName.text = self.aString;
NSLog(#"%#",self.aString);
}
This is essentially the layout I want:
The UITableView at the bottom should accomodate comments to a specific post, adding a row for each comment.
The UITableView at the bottom is wired to commentTable; all other elements are wired accordingly as well.
When I build and run, no errors, but I only see one empty table cell below the post.
I know there's something missing in loading/passing data to my table, but I wonder if someone can give me a direction on how to make this work.
DetailViewController.h
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController {
IBOutlet UIImageView *postThumbView;
IBOutlet UILabel *postTextLabel;
IBOutlet UIImageView *postAuthorPictureView;
IBOutlet UILabel *postAuthorNameLabel;
IBOutlet UILabel *postTimestampLabel;
IBOutlet UIScrollView *scroller;
IBOutlet UITableView *commentTable;
}
#property (strong, nonatomic) id detailItem;
#end
DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
- (void)configureView;
#end
#implementation DetailViewController;
- (void)viewDidLoad
{
[super viewDidLoad];
[self configureView];
}
- (void)configureView
{
if (self.detailItem) {
NSDictionary *post = self.detailItem;
NSString *postText = [post objectForKey:#"post_text"];
...
postTextLabel.text = postText;
...
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDictionary *post = self.detailItem;
NSDictionary *commentThread = [post objectForKey:#"comment"];
return commentThread.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"commentCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *post = self.detailItem;
NSDictionary *commentThread = [post objectForKey:#"comment"];
NSString *commentText = [commentThread objectForKey:#"comment_text"];
NSString *commentAuthorName = [commentThread objectForKey:#"comment_author_name"];
cell.textLabel.text = commentText;
cell.detailTextLabel.text = [NSString stringWithFormat:#"by %#", commentAuthorName];
return cell;
}
#end
It may be that the table view delegate method's you've written aren't being called. The first thing you should do is set breakpoints inside these methods, run your app, and see if they are being called.
If they're not being called, you may have failed to set your delegate. In this case, it appears that you are not using a discrete UITableViewController, rather you are attempting to have your DetailViewController supply the necessary information for the tableView to work as expected.
First, you need to conform your DetailViewController to the UITableViewDelegate protocol:
#interface DetailViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
Second, you need to actually set the delegate #property of your UITableView. You can do this in interface builder (select the tableview, right click, drag it's delegate property to connect to your DetailViewController, which may or may not be File's Owner). If you'd rather do it in code, you just need to call (early in the VC's life, in viewDidLoad, for example):
self.tableView.delegate = self;
self.tableView.datasource = self;
So... assuming your delegate is all wired up properly, you should then go back and test those breakpoints to see if the table view's methods are being called. If they are being called, the next step would be to evaluate the variables when the breakpoints are called, examine for example if the numbers being return in numberOfRowsInSection and the values in cellForRowAtIndexPath match what you anticipate.
You need to declare your view controller as the delegate and data source for the table view
change this line in your .h file
#interface DetailViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
Then in your viewDidLoad
commentTable.dataSource = self;
commentTableView.delegate = self;
[commentTableView reloadData];
[self configureView];
You can also look in the story board, and connect the outlets n the same way you connected commentTable to your UITableView, but by dragging in the opposite direction and selecting data source and delegate
I am creating and iPad application using XCode version 4.3.2. I am having trouble figuring out how to close a popover that is created in a storyboard.
On my main screen I have a button. On the storyboard, I have a segue defined from that button to my popover. My popover is a table view controller. After selecting an item in the popover table view, I am sending the selected information back to the parent and attempting to close the popover. Everything works except I cannot get the popover to close.
The code for the main screen .m file:
#import "SectionViewController.h"
#import "SortByTableViewController.h"
#interface SectionViewController () <SortByTableViewControllerDelegate>
#end
#implementation SectionViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"DisplaySortByOptions"])
{
SortByTableViewController *popup = (SortByTableViewController*)segue.destinationViewController;
popup.selectedSection = self.selectedSection;
popup.receivedOption = self.selectedItemCharacteristic;
popup.delegate = self;
}
}
- (void)sortByTableViewController:(SortByTableViewController *)sender
returnedOption:(ItemCharacteristic *)returnedOption
{
if(!returnedOption)
{
[self.sortByButton setTitle:#"SHOW ALL" forState:UIControlStateNormal];
}
else
{
[self.sortByButton setTitle:returnedOption.name forState:UIControlStateNormal];
}
self.itemCharacteristic = returnedOption;
[self dismissViewControllerAnimated:YES completion:nil]; //THIS DOES NOT CLOSE THE POPOVER
}
The code for the popover .h file:
#import <UIKit/UIKit.h>
#class SortByTableViewController;
#protocol SortByTableViewControllerDelegate <NSObject>
- (void)sortByTableViewController:(sortByTableViewController *)sender
returnedOption:(ItemCharacteristic *)returnedOption;
#end
#interface SortByTableViewController : UITableViewController
#property (nonatomic, strong) Section *selectedSection;
#property (nonatomic, strong) ItemCharacteristic *receivedOption;
#property (nonatomic, weak) id <SortByTableViewControllerDelegate> delegate;
#end
The code for the popover .m file:
#import "SortByTableViewController.h"
#interface SortByTableViewController () <UITableViewDelegate>
#end
#implementation SortByTableViewController
#synthesize selectedSection = _selectedSection;
#synthesize receivedOption = _receivedOption;
#synthesize delegate = _delegate;
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ItemCharacteristic *itemCharacteristic = [self.fetchedResultsController objectAtIndexPath:indexPath];
[self.delegate sortByTableViewController:self returnedOption:itemCharacteristic];
[self dismissViewControllerAnimated:YES completion:nil]; //THIS DOESN'T WORK
[self.navigationController popViewControllerAnimated:YES]; //THIS DOESN'T WORK EITHER
}
#end
Thanks for any help or guidance.
I found the answer. I had to add the following property to my main screen:
#property (nonatomic, strong) UIPopoverController *sortByPopoverController;
Then, when launching the popover, I included this:
UIStoryboardPopoverSegue *popoverSegue = (UIStoryboardPopoverSegue *)segue;
self.sortByPopoverController = popoverSegue.popoverController;
Including that code allowed me to properly dismiss the popover when the delegate called back:
[self.sortByPopoverController dismissPopoverAnimated:YES];
in swift just call this
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
self.dismissViewControllerAnimated(true, completion: nil)
}
I have created a custom cell with its own .m, .h and .xib file. In the cell, I have a UIButton that I added to the xib in IB.
I can receive the IBAction from the UIButton in this custom cell's .m, but really, I'd like to be forwarding that button press to the main view .m that is hosting the table (and so custom cell) and use an action there.
I've spent the last 4 hours attempting various ways of doing this - should I be using NSNotificationCenter? (I've tried Notifications lots but can't get it to work and not sure if i should be persevering)
You need to use delegate in .h file of cell.
Declare the delegate like this
#class MyCustomCell;
#protocol MyCustomCellDelegate
- (void) customCell:(MyCustomCell *)cell button1Pressed:(UIButton *)btn;
#end
then declare field and property
#interface MyCustomCell:UItableViewCell {
id<MyCustomCellDelegate> delegate;
}
#property (nonatomic, assign) id<MyCustomCellDelegate> delegate;
#end
in .m file
#synthesize delegate;
and in button method
- (void) buttonPressed {
if (delegate && [delegate respondToSelector:#selector(customCell: button1Pressed:)]) {
[delegate customCell:self button1Pressed:button];
}
}
Your view controller must adopt this protocol like this
.h file
#import "MyCustomCell.h"
#interface MyViewController:UIViewController <MyCustomCellDelegate>
.....
.....
#end
in .m file in cellForRow: method you need add property delegate to cell
cell.delegate = self;
and finally you implement the method from protocol
- (void) customCell:(MyCustomCell *)cell button1Pressed:(UIButton *)btn {
}
Sorry for my english, and code. Wrote it from my PC without XCODE
I had the same problem, and I solved it by subclassing the cell into it's own class, and put the buttons there as outlets, and filling the cell with data from the model, while using a method that returns the cell we're currently viewing.
For example, if you had a Person class, and each person had a name, a surname, and a number of friends. And each time you clicked a button in the cell, the number of friends for a specific person would increase by 1.
_______________DATA SOURCE___________________________
#import <Foundation/Foundation.h>
#interface Person : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *comment;
#property (nonatomic) NSInteger numberOfFriends;
+(instancetype)personWithName:(NSString *)aName Surname:(NSString *)aSurname;
#end
#import "Person.h"
#implementation Person
+(instancetype)personWithName:(NSString *)aName Surname:(NSString *)aSurname{
Person *person = [[Person alloc] init];
[person setName:aName];
[person setSurname:aSurname];
[person setNumberOfFriends:0];
return person;
}
#end
_____________________PERSON CELL________________________
#import <UIKit/UIKit.h>
#interface PersonCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *friendsNum;
#property (strong, nonatomic) IBOutlet UIButton *friendsBtn;
#property (strong, nonatomic) IBOutlet UILabel *nameLabel;
#property (strong, nonatomic) IBOutlet UILabel *surnameLabel;
#end
Personally I created a private NSArray to hold the names of my Person objects, and a private NSMutableDictionary to hold my Person objects, and I set the keys to be the names of the people.
_____________________PERSON TABLE VIEW________________________
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
PersonCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *name = [peopleNames objectAtIndex:indexPath.row];
Person *person = [people objectForKey:name];
if(cell == nil)
{
cell = [[PersonCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.nameLabel.text = person.name;
cell.surname.Label.text = person.surname
[cell.friendsButton addTarget:self action:#selector(moreFriends:) forControlEvents:UIControlEventTouchUpInside];
cell.friendsNum.text = [NSString stringWithFormat:#"%i", person.numberOfFriends];
return cell;
}
- (IBAction)moreFriends:(id)sender {
UIButton *btn = (UIButton *)sender;
PersonCell *cell = [self parentCellForView:btn];
Person *person = [people objectForKey:cell.nameLabel.text];
person.numberOfFriends++;
[self.tableView reloadData];
}
-(PersonCell *)parentCellForView:(id)theView
{
id viewSuperView = [theView superview];
while (viewSuperView != nil) {
if ([viewSuperView isKindOfClass:[PersonCell class]]) {
return (PersonCell *)viewSuperView;
}
else {
viewSuperView = [viewSuperView superview];
}
}
return nil;
}
I would recommend using a delegate.
You might want to just add a selector for the button in your view controller which has your tableview.
in your cellForIndexPath function
[yourCell.button addTarget:self action:#selector(customActionPressed:) forControlEvents:UIControlEventTouchDown];
then handle the button press in your "customActionPressed:(id) sender" method
//Get the superview from this button which will be our cell
UITableViewCell *owningCell = (UITableViewCell*)[sender superview];
//From the cell get its index path.
NSIndexPath *pathToCell = [myTableView indexPathForCell:owningCell];
//Do something with our path
This may be a better solution for you unless there are more factors that you haven't listed.
I have a tutorial which is might explain more http://www.roostersoftstudios.com/2011/05/01/iphone-custom-button-within-a-uitableviewcell/
Why not create a delegate (using #protocol) for your custom cell. You can then designate the main view as each cell's delegate and process the action appropriately.
I have a TableViewController called SecondViewController. The cells' name is ok and everything works fine, but when it comes to loading the detailed view, which in my case is called ArticleViewController, it does not want to communicate with the detailed view's properties. So basically, if I want to change a label in the detailed view, it just does not work.
Here is the code:
SecondViewController.h
#interface SecondViewController : UITableViewController
{
NSMutableArray *json;
}
#end
SecondViewController.m
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ArticleViewController *article = [self.storyboard instantiateViewControllerWithIdentifier:#"ArticleViewController"];
NSDictionary *info = [json objectAtIndex:indexPath.row];
NSLog(#"%#",[info objectForKey:#"username"]);
[article.usernameLabel setText:[info objectForKey:#"username"]];
[self.navigationController pushViewController:article animated:YES];
}
ArticleViewController.h
#import <UIKit/UIKit.h>
#interface ArticleViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *usernameLabel;
#property (weak, nonatomic) IBOutlet UILabel *articleTitle;
#end
ArticleViewController.m
--synthesizing properties--
I hooked the labels and the ArticleViewController up, but the label never changes.
I would guess that the article hadn't loaded its nib by the time you did article.usernameLabel setText:. So article.usernameLabel was still nil. You could force article to load its nib by doing [article view]. But OdNairy's advice is better.