Sorry this is probably a newbie question to alot of you but I've been going round in circles for the last few hours.
I have a table and when the row is pressed pops to second view.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
BlogDetailViewController *blogDetailViewController = [[BlogDetailViewController alloc] initWithNibName:#"BlogDetailViewController" bundle:nil];
blogDetailViewController.title = [idArray objectAtIndex:indexPath.row];
blogDetailViewController.newsArticle = [content objectAtIndex:indexPath.row];
[self.navigationController pushViewController:blogDetailViewController animated:YES];
}
Then on my next view I have a text box which i want to display the contents of [content objectAtIndex:indexPath.row];.
So far i have added this into the secoundview.h
#interface BlogDetailViewController : UIViewController{
NSDictionary *newArticle;
IBOutlet UITextView *descTextView;
}
#property (nonatomic, copy) NSDictionary *newsArticle;
I have also #synthesize newsArticle; on the secoundview.m, and linked up the IBOutlet.
So far i have
- (void)viewDidLoad
{
[super viewDidLoad];
descTextView.text = [content];
// Do any additional setup after loading the view from its nib.
}
Hope that explains things I can upload the zip if this does not make sense.
Thanks
I'm a bit puzzled with the question as it's not super clear, but I think what you're doing is passing data from the table view to another view, but the next view isn't displaying the data? The simplest thing to do in that case is add into viewWillAppear code that puts the content (newArticle?) into the descTextView.
descTextView.text = [NSString stringWithFormat:newsArticle]; this displayed the string inside the textview
Related
I have been trying to figure this out for a while and not coming up with a solution. I have a view controller with a table and the first cell of the table is allocated for a button called "Add Friends". When clicked, it takes you to another view controller with a list of contacts in a table. When you click on a person, it goes back to the other view controller and adds the selected person. This is what I have so far.
ContactsViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
FirstViewController *newVC = [self.storyboard instantiateViewControllerWithIdentifier:#"newVCSegue"];
newVC.peopleArray = [[NSMutableArray alloc] init];
Person *user = [contactsList objectAtIndex:indexPath.row];
NSArray *userKeys = [NSArray arrayWithObjects:#"FirstName", #"LastName", nil];
NSArray *userObjects = [NSArray arrayWithObjects:user.firstName, user.lastName, nil];
NSDictionary *userDictionary = [NSDictionary dictionaryWithObjects:userObjects forKeys:userKeys];
[newVC.peopleArray addObject:userDictionary];
[self.navigationController pushViewController:newVC animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
FirstViewController.h
#property (strong, nonatomic) NSMutableArray *peopleArray;
FirstViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//...
if (indexPath.row == 0) {
contactName.text = #"Add Person";
imgView.image = [UIImage imageNamed:#"plus-icon.png"];
} else {
NSString *firstName = [[peopleArray objectAtIndex:(indexPath.row)-1] objectForKey:#"firstName"];
NSString *lastName = [[peopleArray objectAtIndex:(indexPath.row)-1] objectForKey:#"lastName"];
contactName.text = [NSString stringWithFormat:#"%# %#", firstName, lastName];
}
return cell;
}
This lets me add one friend so far and if I decided to add another to the list, it replaces the first friend added.
What's basically happening is every time you select a new contact, you're recreating the array in the first view controller, hence it is replacing things. You ideally want to try and avoid getting the FirstViewController using the storyboard like that as well, it's pretty bad practice and may well lead to various problems later.
What I'd suggest in this situation is creating a protocol (look at the delegate pattern). This way, what you'd have is :
Use taps "Add Contact"
Contacts list appears, and FirstViewController is set as the delegate
User taps contact to add them
ContactsViewController informs the delegate of the user that was selected
FirstViewController adds the user, and dismissed the view controller
This is generally the approach you'd take, and it's pretty simple to implement. Start with the protocol
#protocol ContactsDelegate
-(void) contactsViewController:(ContactsViewController *)vc didSelectContact:(Person *)person;
#end
Then, make your FirstViewController implement this protocol. To do this, in your header file, in the angle brackets after the name (< >) add ContactsDelegate
In the implementation of FirstViewController, add the new method of the contacts delegate.
In your ContactsViewController.h file, add
#property (nonatomic, assign) NSObject<ContactsDelegate> *delegate;
Then when you display your contacts view controller, set the delegate
userVc.delegate = self;
[self presentModalViewController:userVc];
Then, in the user view controllers didSelectRowAtIndexPath:, simply inform the delegate that you've selected that person
[delegate contactsViewController:self didSelectContact:[contactsList objectAtIndex:indexPath.row]];
And lastly, in your FirstViewController, in the delegate method you added, we need to ADD the user to the list, not re-create the list
[peopleArray addObject:person];
And that should do what you're after :)
From what I understand, you are instantiating a new FirstViewController every time you select a contact in the ContactsViewController. Instead, you should reference the original FirstViewController (perhaps save it before transitioning to ContactsViewController), and use this reference to add the contact to the original array [original.people addObject:userDict]. As long as you make sure to reload the table, this should work.
I have a question pertaining to why my UITableView won't load a detailView...
I've done it before with an interface builder, but now I'm just trying to do it programatically, purely.
In my tableView.h:
#property (strong, nonatomic) RLCASearchDetailViewControllerViewController *searchDetailViewController;
In my tableView.m:
#synthesize searchDetailViewController = _searchDetailViewController;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!self.searchDetailViewController)
{
self.searchDetailViewController = [[RLCASearchDetailViewControllerViewController alloc] initWithNibName:#"" bundle:nil];
}
SearchItem *item = [ content objectAtIndex:indexPath.row ];
[self.navigationController pushViewController:self.searchDetailViewController animated:YES];
self.searchDetailViewController.detailItem = item;
}
By the way, I'd tried the initWithNibName: value to be nil, empty string as above, and even #"RLCASearchDetailViewControllerViewController". Nothing works...
in my RLCASearchDetailViewControllerViewController.h:
#interface RLCASearchDetailViewControllerViewController : UIViewController
{
SearchItem *detailItem;
}
#property (strong, nonatomic) id detailItem;
#end
in my RLCASearchDetailViewControllerViewController.m:
#synthesize detailItem = _detailItem;
- (void)setDetailItem:(SearchItem*)newDetailItem
{
NSLog( #"GETS HERE" );
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem)
{
NSLog( #"GETS HERE" );
}
}
- (void)loadView
{
[super loadView];
// If you create your views manually, you MUST override this method and use it to create your views.
// If you use Interface Builder to create your views, then you must NOT override this method.
NSLog( #"DOES NOT GET HERE" );
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog( #"DOES NOT GET HERE" );
}
As seen above, when I'd implemented a few debugging prints... It does what it's supposed to in theory but for some reason does not load the views. This manifests itself in the GUI by nothing happening when a table cell is clicked, when the view should change into the subview.
What am I doing wrong? Please help... It's been driving me crazy, and I'd been rummaging through the interweb for a while now in hopes of answers.
Thanks a bunch - I really appreciate it! ;)
Sincerely,
Piotr.
If you aren't using a nib, change this line of code:
self.searchDetailViewController = [[RLCASearchDetailViewControllerViewController alloc] initWithNibName:#"" bundle:nil];
To
self.searchDetailViewController = [[RLCASearchDetailViewControllerViewController alloc] init];
Hope it helps !
Your table view is not embedded in a navigation controller, so it can't push a new view controller.
Since the detail view controller is never displayed on the screen, it never bothers loading its view, which is why you are seeing nothing from your loadView or viewDidLoad methods.
You don't show how you set up the initial view controller for your app, but it should be a navigation controller, with your table view controller as the root view controller.
If you're a beginner, storyboards are much better to use than trying to do it all in code. There are few benefits and lots of drawbacks to avoiding interface builder.
My problem is how to reload the tableview
I have 2 viewcontrollers.
In first Viewcontroller I have one tableview. if I select any row in tableview it goes to second viewcontroller.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
NextPageController *nextView = [[NextPageController alloc] initWithNibName:#"NextPageView" bundle:nil];
[self.navigationController presentModalViewController:nextView animated:YES];
[nextView release];
}
in second view controller I have one textfield. If I enter any value into the textfield I need to disaplay that value into the first viewcontroller tableview.
can any one help me?
Thanks in advance.
give NextPageController a protocol and a delegate,just like this:
#protocol (NextPageControllerDelegate)
-(void)displayString:(NSString *)inputString;
#end
#interface FirstTableViewController : UITableViewController {
id<NextPageControllerDelegate> stringDelegate;
}
#property (nonatomic, assign) id<NextPageControllerDelegate> stringDelegate;
and in the .m file:
#implementation
#synthesize stringDelegate;
then, when you alloc the NextPageViewController, insert this:
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
NextPageController *nextView = [[NextPageController alloc] initWithNibName:#"NextPageView" bundle:nil];
nextView.stringDelegate = self;
[self.navigationController presentModalViewController:nextView animated:YES];
[nextView release];
}
of course, your table view controller must conforms to the NextPageControllerDelegate protocol, and give the implementation of
-(void)displayString:(NSString *)inputString;
after that, when you are in nextView, and want to have the table view display that string, you may do this:
if(nil != self.stringDelegate)
[self.stringDelegate displayString:someString];
ant then it's done
Make Global String ,
Assign it in secondViewController and when you pop from secondViewController to FirstViewController , viewWillAppear will call.
make logic such it uses global variable and then reload table ..
you need to have a global NSString variable in appDelegate that stores your text of text filed in second view.
Now, when you come back to previous page, in
- (void) viewWillAppear
{
[yourDataSourceArray addObject:appDelegate.yourGlobalString];
[yourTableView reloadData];
}
and yes make sure that your yourDataSourceArray is NSMutableArray.
Hope it helps you.
You could create a property for an NSString in your first view, and a property for an instance of the first view controller (UITableViewController?) in your second view. Then upon saving or popping or whatever you're doing in the second view controller once you have entered the text you want, you could set the property of the NSString, pop the view, and reload the tableView in viewWillAppear. Alternatively you could use delegation as Lewen described.
create global NSMutableArray.
Store and add all data in that NSMutableArray.
In -(void) viewwillappear of first class, call [tablename reloadData];
I have a bit of a dilemma and I was wondering if the good folk here could lend me their programming expertise. I'll try to be as simple and precise as I possibly can so here goes:
I'm a new IOS developer and have only been learning for a couple of months. I am developing an iPhone application for my dissertation at university. The app is simply a guide for people who wish to develop for the iPhone themselves, consisting of tutorials. It consists of numerous Table Views but there is one thing that has got me stumped.
What im trying to do:
One feature im trying to include in my app is a bookmarks facility, this will be accessible from a tab bar. I want to be able to click on a button from any nib file (tutorial) which adds a string to an existing NSMutableArray. This string will correspond with the name of the tutorial where the IB-Action was performed and after added to the Array I can load the nib file when selecting the row at index path.
The Problem:
I can add any object to the array from within the implementation file that contains the array but cannot figure out how to add it from a different implementation file. The UITable view populates from the array perfectly but adding a new entry is another story.
I'll show you my code but i'll leave out anything that is unrelated.
BookmarksViewController.h
#interface BookmarksViewController : UITableViewController {
NSMutableArray *bookmarksArray;
}
#property (nonatomic, retain) NSMutableArray *bookmarksArray;
#end
BookmarksViewController.m
-(void)viewDidLoad {
bookmarksArray = [[NSMutableArray alloc] init];
NSLog(#"String Added");
[bookmarksArray addObject:#"String"];
[super viewDidLoad];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Configure the cell...
cell.textLabel.text = [bookmarksArray objectAtIndex:indexPath.row];
return cell;
}
-(void)dealloc {
[bookmarksArray release];
[super dealloc];
}
NOW FOR THE SECOND VIEW CONTROLLER
Ch01GettingStarted.h
#interface Ch01GettingStarted : UIViewController {
IBOutlet UIScrollView *ScrollView;
}
-(IBAction) pushChap01Bookmark:(id)sender;
#end
Ch01GettingStarted.m
-(IBAction) pushChap01Bookmark:(id)sender{
BookmarksViewController *bookmarksViewController = [[BookmarksViewController alloc]init];
[bookmarksViewController.bookmarksArray addObject:#"NewString"];
NSLog(#"ADD ENTRY");
[bookmarksViewController.tableView reloadData];
NSLog(#"RELOAD TABLE");
[bookmarksViewController release];
NSLog(#"ADD BOOKMARK RELEASE");
}
BTW - the IB-Action was declared in the header file.
Ah, i originally tried doing this as '[BookmarksViewController.bookmarksArray addObject:#"NewString"];' but I came up with an "expected ':' at '.'" error and I read somewhere that I needed to use an instance variable of BookmarksViewController so i declared it just above the addObject method.
Please be gentle with me as I haven't been doing this for long but this is certainly something that's going to be a big part of my professional future.
Any insight anyone could offer to me would be magical.
Thank you, thank you, thank you.
The problem lies in this method:
-(IBAction) pushChap01Bookmark:(id)sender
You are creating a NEW bookmarksViewController here, by doing this:
BookmarksViewController *bookmarksViewController = [[BookmarksViewController alloc]init];
You don't want to do that because you want to update the current view controller. You need to create a link from Ch01GettingStarted.
Assuming you are using Interface Builder, you could create this link using an IBOutlet. In the Ch01GettingStarted interface, add the following line:
IBOutlet BookmarksViewController *bookmarksViewController;
(Between the brackets)
I think you already know how to link this in Interface Builder.
Then just remove this line:
BookmarksViewController *bookmarksViewController = [[BookmarksViewController alloc]init];
And this line:
[bookmarksViewController release];
And it should work.
Why? The 'bookmarksViewController' variable now references the original object (the one you created in Interface Builder) that is actually displayed.
Just to be sure.
Do you have this method in BookmarksViewController.m?
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
[bookmarksArray count];
}
Because after bookmarksViewController is created. ViewDidLoad method not run yet. bookmarksArray has not been created. So bookmarksArray = nil. You can't add object to nil object. In Second Viewcontroller, You should create bookmarksViewController in loadView method. And addobject in pushChap01Bookmark.
I'm not good English. I hope you can understand it. :D
Hello future friends who is gonna help me big time on this project,
I have these Books parsed from XML file (adopted from this post I found). First view (RootViewController) has a list of book titles in a UITable. When user clicks on one of the books, instead of viewing the books detail (BooksDetailViewController) in a second UITable, I would like the Title, Author and Summary to be in a custom view laid out in Interface Builder with UILabels and UITextView.
IBOutlet UILabel *bookTitle;
IBOutlet UILabel *bookAuthor;
IBOutlet UITextView *bookSummary;
I believe my problem has to do with RootViewController.m "didSelectRowAtIndexPath". If I understand the example I had adapted properly (which I am not confident about), it passed the Book array into each row of the new table on my BooksDetailViewController.
Book *aBook = [appDelegate.books objectAtIndex:indexPath.row];
I have tried a few things to recreate didSelectRowAtIndexPath, but I am not having much luck. Below I have the example code commented out and with my own terrible guessed code /sigh.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// if(bdvController == nil)
// bdvController = [[BookDetailViewController alloc] initWithNibName:#"BookDetailView" bundle:[NSBundle mainBundle]];
// Book *aBook = [appDelegate.books objectAtIndex:indexPath.row];
// bdvController.aBook = aBook;
// [self.navigationController pushViewController:bdvController animated:YES];
NewBookDetailViewController *detailViewController = [[NewBookDetailViewController alloc] initWithNibName:#"NewBookDetailViewController" bundle:nil];
Book *aBook = appDelegate.books;
//detailViewController.aBook.title = bookTitle.text;
//detailViewController.aBook.author = bookAuthor.text;
//detailViewController.aBook.summary = bookSummary.text;
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
Do I actually connect the parsed data aBook.title to bookTitle (UILabel) in didSelectRowAtIndexPath of RootViewController?
or
Do I connect them in viewDidLoad in NewBookDetailViewController.m?
bookTitle.text = aBook.title;
bookAuthor.text = aBook.author;
bookSummary.text = aBook.summary;
What is the proper way to write the didSelectRowAtIndexPath in RootViewController for a custom view instead of a table view?
Please take it easy on me.
Clo
The purpose of NewBookDetailViewController is to display information about a single book, yes? So NewBookDetailViewController will need a way of being told which book it's supposed to display.
An easy way of doing this would be to add a property to this class to hold a reference to the Book it's supposed to display. You would not want to pass the entire array of books to the detail view controller. How is it supposed to know which single book to display?
Here' how my implementation would look:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Book *selectedBook = [appDelegate.books objectAtIndex:indexPath.row];
NewBookDetailViewController* viewController = [[NewBookDetailViewControlleralloc] initWithNibName:#"NewBookDetailViewController"];
viewController.book = selectedBook; // "book" is a property you'd add to NewBookDetailViewController
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
}
Here's how you add the book property to NewDetailViewController:
The .h file:
#class Book;
#interface NewDetailViewController : UIViewController {
// other instance variables
Book *_book;
}
#property (nonatomic, retain) Book *book;
#end
The .m file:
#import "NewDetailViewController.h"
#import "Book.h" // assuming the "Book" class is defined in Book.h
#implementation NewDetailViewController
#synthesize book = _book;
- (void)dealloc {
[_book release];
[super dealloc];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// set up your controls to display the book information
}
// other method implementations
#end