showing data from tableview in a text field objective C/iOS - ios

can't for the life of me figure this out.
so I'm creating a contact list app, very similar to the one that comes with iOS7.
a user creates a name with the GUI on a detail view controller.
user goes back to the main contact list page (master view controller)
user taps on the name/contact they just created
brings them back to the view controller, but it shows what they had entered into the text fields.
User starts with this screen:
User hits the add contact button, adds in the user data here which brings them back to the first screen:
Next, they are brought to the first screen and are able to tap on the contact they've added and should bring up all the details entered (firstname,lastname,phone number etc):
here's my code in my master view controller:
- (void) detailViewControllerWillDissapear: (DetailViewController *) dvc {
NSLog(#"test");
DirectoryEntry *person = [[DirectoryEntry alloc] init];
person.firstName = dvc.txtFirstName.text;
person.lastName = dvc.txtLastName.text;
person.phoneNumber = dvc.txtPhoneNumber.text;
person.address = dvc.txtAddress.text;
[self.entries addObject:person];
NSLog(#"index is %#", person.firstName);
NSLog(#"count of array %lu", (unsigned long)self.entries.count);
dvc.holdData = person;
[self.tableView reloadData];
}
here's my segue:
#pragma mark - segue
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
//DirectoryEntry *person = [[DirectoryEntry alloc] init];
DetailViewController *dvc = segue.destinationViewController;
dvc.delegate = self;
if ([segue.identifier isEqualToString:(#"tappedData")]) {
NSLog(#"what is the person class have %#", dvc.holdData);
// NSLog(#"dvc.holdData = %#", person.firstName);
}
}
so I've created the public variable holdData which is meant to hold all the data which was entered from the array into the Person class. but whenever I add it, just comes up with a Null value. I am able to access the variables i.e. holdData.firstName, but just everything is null.
any ideas? really confused, thanks.

The dvc that you have in prepareForSegue is almost certainly not the same object that you had in the detailViewControllerWillDissapear method. (Try printing their addresses to prove that for yourself.) That means that either your main controller should save the Person data and provide it during the segue or you could create a separate data model that each DetailViewController would use directly.

Related

Only sometimes get EXC_BAD_ACCESS when setting uitabviewcontroller viewcontrollers

I'm trying to create and set VCs for my tab view controller. There is a next button in each VC that either opens the next tab or loads a new set of tabs when it reaches the end. Inside both Type1.m and Type2.m:
- (IBAction)next:(id)sender {
if (self.tabBarController.selectedIndex < [self.tabBarController.viewControllers count] - 1) {
self.tabBarController.selectedIndex += 1;
}
else {
// load nextData
NSLog(#"nextData: %#", nextData);
if (nextData == nil) {
// essentially stop the next button from working
return;
}
self.tabBarController.selectedIndex = 0U;
[self.tabBarController setTitle:[nextData display_name]];
[self.tabBarController setViewControllers:[nextData loadTabs]];
}
}
loadTabs is a method of the Data class (which is a Core Data NSManagedObject subclass with a category).
Inside ParentData+Helpers.m It looks like:
- (NSArray *)loadTabs {
NSMutableArray *mut = [NSMutableArray new];
for (SubData *d in self.datapoints) {
if ([d.field_x isEqual:#YES]) {
[mut addType1:d];
else {
[mut addType2:d];
}
return mut;
}
addType1 and addType2 are nearly identical in their fields, but have different implementations. They look like:
- (TypeVC *)addType1:(SubData *)data {
TypeVC *vc = [[TypeVC alloc] init];
vc.datapoint = data;
return vc;
}
where TypeVC is either Type1 or Type2
So now I have a table view and each cell has an associated ParentData which has an array of SubData objects. When selected, it loads a UITabViewController with Type1 and Type2 VCs.
inside TableVC.m:
- (void)- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"toTabs" sender:self];
}
where toTabs leads to a UITabBarController in the storyboard.
In prepareForSegue:
UITabBarController presentedTabBarController = [segue destinationViewController];
[presentedTabBarController setTitle:self.selectedTitleName];
[presentedTabBarController setViewControllers:[self.selectedParentData loadTabs]];
So all that works fine.
So I run my app, get to the UITabBarController and the thing that should be there is. The first set of tabs has 2 tabs, so I hit next and it goes to the second one. I hit next, and it loads the next set of tabs and opens to the correct tab. I hit next, alls working good. I hit next four or five times, each time it works correctly. It doesnt matter if its Type1 or Type2, it works.
But then suddenly, I get to a specific one that has 2 tabs. It loads the first one (the one at index 0) and then I hit next. And suddenly I have EXC_BAD_ACCESS(code=1, address=0xWHATEVER) at the line self.tabBarController.selectedIndex += 1;. I don't understand why this would happen.

Pass informaion back to mother view

I'd like to pass some object from one view (number 2) to view number 1. View 1 triggers view 2 and before that in "prepareForSeque" I'm passing "self" to the second view and store it in variable "delegate". After some time I'd like to pass back new created object to view 1 and I'm trying to achieve it but I got an error that method is not visible for this interface. How to pass created object to the mother view triggering method?
When I declare #property someObject and synthetize it, it works ok using delegate. Is there another option or am I forced to use delegate?
Code:
- (IBAction)saveAndClose:(id)sender {
KwejkModel *mod = [[KwejkModel alloc] init];
((ViewController *)self.delegate).model = mod;
}
It works ok, but is there another option triggering method not using the property? Like this:
[((ViewController *)self.delegate) someMethod];
but here is an error.
Here is my code:
VIEW 1
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"addItemSeque"]) {
ScrollViewViewController *destViewController = segue.destinationViewController;
destViewController.delegate = self;
}
}
-(void) addNewPosition:(KwejkModel *)newKwejk
{
//for testing only this
[modelArray count];
}
VIEW 2:
- (IBAction)saveAndClose:(id)sender {
KwejkModel *mod = [[KwejkModel alloc] init];
// ((ViewController *)self.delegate).model = mod;
//it crashes here with error:-[NSPlaceholderString initWithString:]: nil argument' but it sees method from VIEW 1
[self.delegate addNewPosition:mod];
}
Try this link: Passing Data between View Controllers
Take a look at the first answer under Passing Data Back.

Prepopulating a UITextField with Core Data and NSFetchedResultsControllers

I have a simple application and I require a bit of assistance with one new feature.
The application is a table view (TV1) which is populated by the user adding an entry (a button in the navigation bar which modally brings up a new view controller for the user filling in a name, event and amount text field and selecting a date from the date picker).
The table view controller is part of a tab bar controller where the first tab shows everything (timeline) and the second tab shows just the list of events. If you click on an event, you segue over to see all transactions with that event.
I've added a bar button item here as well which segues to the Add Entry view controller, with the aim of having the event already selected.
What I mean by this is:
Say you have 3 events called Wedding, Birthday and Anniversary in your transactions. If you click on the Event tab, you'll see Wedding, Birthday and Anniversary in a Table view. Clicking Birthday will show you all the transactions where event = Birthday.
I have a bar button item which will allow me to add entries from this screen, but because it's coming from the Birthday event, I want that event text field to already be filled in, in the Add Entry with the name of this event (Birthday in this case).
I'm using Core Data and NSFetchedResultsController.
The situation right now is, when I press the button to add a new entry from the Selected Event (Birthday), it's not pre-configuring the event text field with Birthday in the Add Entry screen.
Here's some code which should hopefully explain what I'm doing.
From the Event Tab
// This segues over to the selected event (Birthday).
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.eventTableView indexPathForCell:sender];
Occasion *selectedOccasion = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([segue.identifier isEqualToString:#"Selected Occasion Segue"])
{
ESelectedOccasionTableViewController *selectedOccasionTVC = [segue destinationViewController];
[selectedOccasionTVC setOccasion:selectedOccasion];
}
}
From the Selected Event Tab (Birthday), I create two segues, one for editing a cell and one for creating a new entry:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.selectedOccasionTableView indexPathForCell:sender];
Transaction *seletedTransaction = [self.fetchedResultsController objectAtIndexPath:indexPath];
// The first segue is to "edit" the existing entry
if ([segue.identifier isEqualToString:#"Editable Cell"])
{
EDetailViewController *dvc = (EDetailViewController *)segue.destinationViewController;
dvc.selectedTransaction = seletedTransaction;
}
// This segue is to create a new entry from the event
else if ([segue.identifier isEqualToString:#"Create New Entry From Event"])
{
EddEntryViewController *eAppEntryViewController = (EAddEntryViewController *)segue.destinationViewController;
[eAppEntryViewController setSelectedTransaction:selectedTransaction];
}
}
The first segue is for editing the cell (which works perfectly), but in the second segue, the one I'm interested in here, I'm not actually clicking on a cell; I'm clicking on a bar button item which will modally bring up the add entry. I want to take just the "event" (Birthday) from this Table View and pre-fill the "event text field" in the Add Entry.
The setSelectedTransaction in the Add Entry is:
- (void)setSelectedTransaction:(Transaction *)selectedTransaction
{
_selectedTransaction = selectedTransaction;
self.occasionTextField.text = _selectedTransaction.occasion.title;
}
I can't imagine I'm very far from getting this working, but any assistance on this would really be great because I'm really stuck.
Should I be setting something in viewDidLoad? (That did not work either).
I'm not selecting a table view cell which is why I understand that the [eAppEntryViewController setSelectedTransaction:selectedTransaction]; line isn't actually passing anything, because I'm clicking on a bar button item, not a table view cell.
The model is: a Transaction Entity that links to the Date and Event Entities.
I have resolved this issue in the following way:
EAddEntryViewController *eAppEntryViewController = (EAddEntryViewController *)segue.destinationViewController;
[eAppEntryViewController setSelectedEvent:self.occasion.title];
Which called:
- (void)setSelectedEvent:(NSString *)selectedEvent
{
_selectedEvent = selectedEvent;
}
In the viewWillAppear, I did:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.occasionTextField.text = self.selectedEvent;
}
This works the way it is and I'm happy with this.
So I might not be understanding the question fully. But you can add a "Touch Up Inside" event to the bar button item and then pull the text from the "sender" object. Then, either store that text as an NSString property in the interface for later use, or set your desired textbox straight from the bar button item action.

pass core data item between view controllers

i am making an app that requires core data to store some information, i have managed to get the app to create the entities and add the information, however i am unable to edit it
i have a list view controller that displays a brief outline of this information and another list view controller which acts as a modal view to allow the user to edit their information.
when the user taps a list item i need the app to show the modal view controller with the selected information loaded from the core data model into the relevant text boxes and when the user clicks save, i need the changes to be saved
at the moment when the user taps the list item the information is not passed into the modal view, NSLog confirms that for me - it tells me the item i tapped in the prepareForSegue: method and is null in the modal view's viewDidLoad:
here's the code:
this is from the MedsList view controller, it displays the information
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
} //selMed declared at top of file as NSManagedObject *selMed;
selMed = [self.meds objectAtIndex:indexPath.row];
NSLog(#"SELECTED MED: %#",[selMed valueForKey:#"name"] );
UIStoryboardSegue *segueString = [NSString stringWithFormat:#"%#",#"editMeds"];
NSLog(#"%#",segueString);
NSLog(#"%# %#", #"MED NAME",[self.meds objectAtIndex:indexPath.row]);
[self performSegueWithIdentifier:#"editMeds" sender:indexPath];
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue isEqual: #"editMeds"]) {
NSLog(#"%# %#", #"SELMED AT PREPARE FOR SEGUE: ",selMed);
UINavigationController *nav = segue.destinationViewController;
MedsEditViewController *dest = (MedsEditViewController *)nav.topViewController;
dest.med = selMed;
dest.chName = [selMed valueForKey:#"name"];//chosen med's name
}
}
}
here is MedsEdit.m
#import "MedsEditViewController.h"
#import "fibroMappAppDelegate.h"
#import <CoreData/CoreData.h>
#interface MedsEditViewController ()
{
NSManagedObjectContext *context;
}
#end
#implementation MedsEditViewController
#synthesize tbName;
#synthesize tbDose;
#synthesize tbMaxDose;
#synthesize tbType;
#synthesize med;
double dose;
double maxDose;
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%# %#", #"recieved MEDICATION", self.med);
NSLog(#"%# %#", #"recieved Name", _chName);
fibroMappAppDelegate *delegate = [[UIApplication sharedApplication]delegate];
context = [delegate managedObjectContext];
tbName.text = _chName;
}
chName is declared in the .h file as a NSString
could somebody please help me work out what i have done wrong? and how to fix it..... i've spent a lot of time on this on and off in the last few months
here is a copy of the log after prepare for segue starts
2013-11-07 14:21:15.475 fibromapp[660:70b] SELECTED MED: med1
2013-11-07 14:21:15.476 fibromapp[660:70b] editMeds
2013-11-07 14:21:15.477 fibromapp[660:70b] MED NAME (entity: Medication; id: 0x8a6b0a0 ;
data: {
dose = 3;
lastTaken = nil;
maxDose = 5;
name = med1;
type = Miligrams;
})
2013-11-07 14:21:15.479 fibromapp[660:70b] Warning: Attempt to present on while a presentation is in progress!
---------------------the following is in the MedsEdit viewDidLoad-------------------------
2013-11-07 14:21:15.497 fibromapp[660:70b] recieved MEDICATION (null)
2013-11-07 14:21:15.498 fibromapp[660:70b] recieved Name (null)
[segue isEqual: #"editMeds"] should be [segue.identifier isEqualToString: #"editMeds"] for a kick off...
Have you ever tried to set the MedsEditViewController as your segue.destinationViewController?
First of all, where in the code you posted are you actually setting the med on the destination controller? I see
dest.med = selMed
but it is commented out. If you never set it, then it won't ever be available. Could you please reformat and post the complete logs? It's not clear to me if your code ever reached the SELMED AT PREPARE FOR SEGUE log.
Assuming you did not mean to comment that out, or you received an error I think it may be here - UINavigationController *nav = segue.destinationViewController - unless your MedsEditViewController is actually a UINavigationController I suspect that the segue.destinationViewController is the navigation controller, which in turn is going to present your MedsEditViewController. Double check the documentiation for UINavigationController, but off the top of my head I think you need this:
dest.topViewController.med = selMed

NSMutableArray persistency while switching view controllers

I've searched a lot and still couldn't find an answer to this...
I'm working on an iphone App (for college) in xcode 5.0 using storyboards.
I have a View Controller with a table view and everything works fine (data sources, delegate...). Items are stored in an array (call it "array1"). I have an ADD button which brings up a list of items which I want to add (if checked) to array1. I store the checked items in another array ("array2"). The thing is, when I pass array2 to the previous view controller I lose all data in array1 (it becomes nil).
The code I'm using to pass data from array2 to the VC is:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"updateFavoritesSegue"]) {
FavoritesViewController *targetVC = (FavoritesViewController*) segue.destinationViewController;
[targetVC updateFavorites:[self newFavoritesArray]];
}
}
The updateFavorites method is implemented as below.
-(void) updateFavorites:(NSArray *)newFavorites {
[self.favorites addObjectsFromArray:newFavorites];
[self.favoritesTableView reloadData];
}
Thank you very much for your help.
Why don't you just use some handler?
secondVC.h
#property (nonatomic, copy) void (^didFinishPickingItemsHandler)(NSArray *items);
then from the firstVC:
- (void)showSecondScreen {
MYSecondVC *secondVC = /* initialisation code here */
__weak MyFirstVC *self_ = self;
secondVC.didFinishPickingItemsHandler = ^(NSArray *items) {
/* update you data here with your array1 and received picked items */
[self.navigationController popViewControllerAnimated:YES];
};
[self.navigationController pushViewController:secondVC animated:YES];
}

Resources