pass core data record from uiview - core-data

I've a little issue in my app. my app is based on core data using magical record.
In my first view ( a tableview) I have all the data, when one of the cell is tapped, it open the second view (detail UIview).
But i don't have enough space to show all the detail so i create a second detail view from the first one ( I don't want a scroll view).
the segue between the tableView and the firstDetailView work perfectly
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
DetailViewController*dvc = segue.destinationViewController;
dvc.indice = indexPath.row;
}
}
But when I go to the second detail UIview I always get the detail of the first record in the tableview. I think the problem is in the prepareForSegue method, but I can't figure out how to solve it,
Somebody could help me??

I created another property in the second detail view and set it equal to the property "indice" of the first detail view
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showMaking"]) {
DettaglioPreferito2*dvc = segue.destinationViewController;
dvc.indiceDue = self.indice;
}
}

Related

Why isn't my custom UICollectionViewController's GetCell method called

I have a storyboard set up like so:
As you can see, I have a home screen. It has access to a navigation controller. It has two ContainerViews, one used as a sidepane, the other as the main content. I plan to swap things into this main content container as I need them.
One of the things I would like to show in this container, when it is selected from the sidepane, is a CollectionView of cells that show people. Each cell has a photo and the person's details.
The best code example I could find for CollectionView was the Xamarin StateRestoration sample project. It includes a storyboard. I have followed the recipe as best I can while working around my own specific storyboard.
The problem now is that the GetCell(UICollectionView collectionView, NSIndexPath indexPath) method used to populate each cell in the CollectionView is not being called. As far as I know I'm supposed to instantiate the CollectionViewController's Datasource property. I've tried this in AppDelegate and in the ViewDidLoad of my CollectionViewController itself, and GetCell is still not getting called. Why is this?
Any help is appreciated! Ask me to edit if you need more information.
You need to set both datasource and the delegate. As you've mentioned you've set the datasource. To set the delegate open up the storyboard in xcode, select UICollectionView and control drag to the its parent view controller. Have a look at this gif.
Also make sure you implement IUICollectionViewSource interface in your target view controller
public partial class DetailViewController : UIViewController, IUICollectionViewSource
{
protected DetailViewController(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public nint GetItemsCount(UICollectionView collectionView, nint section)
{
return 10;
}
public UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = collectionView.DequeueReusableCell("PersonCell", indexPath) as UICollectionViewCell;
return cell;
}
}
EDIT 1:
You can also do this programmatically. Enter the storyboard, in Widget properties set the name for the UICollectionView - PersonCollection. Then in code behind view controller override ViewDidLoad and set WeakDelegate and WeakDataSource (weak because we definitely not want to create cyclic reference and memory leaks for iOS)
public override void ViewDidLoad()
{
base.ViewDidLoad();
PersonCollection.WeakDataSource = this;
PersonCollection.WeakDelegate = this;
}
Hope this helps!

How the detail view controller told the main controller about the changes made?

I'm reading the Big Nerd Ranch book and I'm at the 10th chapter about the navigation controller.
In the main controller, there is a TableView ( https://github.com/bignerdranch/iOS3eSolutions/blob/master/11.%20Homepwner/Homepwner/Homepwner/ItemsViewController.m ) where there are two methods that interact with the detail view :
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[self tableView] reloadData];
}
- (void)tableView:(UITableView *)aTableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detailViewController = [[DetailViewController alloc] init];
NSArray *items = [[BNRItemStore sharedStore] allItems];
BNRItem *selectedItem = [items objectAtIndex:[indexPath row]];
// Give detail view controller a pointer to the item object in row
[detailViewController setItem:selectedItem];
// Push it onto the top of the navigation controller's stack
[[self navigationController] pushViewController:detailViewController
animated:YES];
}
In the detail view controller (https://github.com/bignerdranch/iOS3eSolutions/blob/master/11.%20Homepwner/Homepwner/Homepwner/DetailViewController.m), there is a method that "saves" the BNRItem being changed :
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// Clear first responder
[[self view] endEditing:YES];
// "Save" changes to item
[item setItemName:[nameField text]];
[item setSerialNumber:[serialNumberField text]];
[item setValueInDollars:[[valueField text] intValue]];
}
The code works well :
I understand how the main controller set the object to edit but I don't understand how the main view controller knows that the BNRItem has been changed and then set it back to the tableview ?
I was excepting the author to write a setter in the main controller (ItemsViewController.m ) that could be called by the detail view controller (DetailViewController.m) giving the new BNRItem.
But this part works "automatically".
Thank you.
As you are pointing to the same memory chunk in both controllers, changed made in the DetailViewController are obviously reported in ItemsViewController.m.

Missing Reference to Navigation Controller in Monotouch

I am new to Monotouch and attempting to understand how some of the basics hang together. Hopefully someone out there will be able to assist.
I've created a test project in MonoDevelop based on the Multi-Screened Apps tutorial on the Xamarin site and have extended it to include a tableView. I am having issues with referencing the Navigation Controller in a view that I need to push a detail view onto to display the detail of an item tapped in the table via an accessory button. I know some of the coding is scrappy, just been trying to get it working at this stage rather than the clarity in the code! (I'm using the latest versions of all Mono tools/libraries etc and XCode 4 on Lion). Starting at the beginning here's the code in FinishedLaunching in AppDelegate.
window = new UIWindow (UIScreen.MainScreen.Bounds);
this.rootNavigationController = new UINavigationController();
// Create a new homescreen
HomeScreen homeScreen = new HomeScreen();
// Add the homescreen to the root navigation controller
this.rootNavigationController.PushViewController(homeScreen, false);
// Set the root view controller on the window - the navigation controller
// will handle the rest.
this.window.RootViewController = this.rootNavigationController;
// make the window visible
this.window.MakeKeyAndVisible ();
homeScreen just contains a button which loads a new view containing a table view (OrderList). Here's the button event handler.
void HandleOrdersButtonhandleTouchUpInside (object sender, EventArgs e)
{
if (orderListScreen == null)
orderListScreen = new OrderList();
NavigationController.PushViewController(orderListScreen, true);
}
This all works fine. I've got some dummy data that loads into the table view, which also works fine. OrderData is a simple class for testing which just contains a couple of properties. I've added an AccessoryButton to the cells and am trying to load a detail view when this is tapped. Here's the code that does this - comment in code where issue is! (I'd previously tested the AccessoryButtonTapped functionilty was working by just displaying an alert).
public override void AccessoryButtonTapped (UITableView tableView, NSIndexPath indexPath)
{
var dataSource = (OrdersTableViewDataSource)tableView.DataSource;
if (detailScreen == null)
detailScreen = new OrderDetailScreen();
OrderData theOrder = dataSource.OrdersData[indexPath.Row];
detailScreen.currentOrder = theOrder;
// Cant get a reference to NavigationController here to push the detail view!
// this.NavigationController is not available
this.NavigationController.PushViewController(detailScreen, true);
}
My understanding of NavigationControllers from what I've read so far is that this reference should be available through all views that originate from the root ViewController/NavigationController without the need to pass the reference from AppDelegate through the various view constructors?
Can anyone tell me what I might be missing here?
Thanks in advance.
** An update after reviewing Jason's comment: (Please let me know if this is the incorrect way to post updates)
So, I tried the following:
I saved a reference to the NavigationController in the constructor for the ViewController that contains the table view as follows:
public partial class OrderList : UIViewController
{
UINavigationController navController;
public OrderList () : base ("OrderList", null)
{
this.Title = "Orders";
navController = this.NavigationController;
}
Then passed that into the TableViewDelegate, where the AccessoryButtonTapped is handled, in the ViewDidLoad method.
public override void ViewDidLoad ()
{
orderTableView.DataSource = new OrdersTableViewDataSource();
orderTableView.Delegate = new OrdersTableViewDelegate(navController);
base.ViewDidLoad ();
}
Then referenced that in the TableViewDelegate:
public class OrdersTableViewDelegate : UITableViewDelegate
{
UINavigationController navController;
public OrdersTableViewDelegate(UINavigationController controller)
{
navController = controller;
}
// Rest of class definition
}
Then the reference to the NavigationController using navController compiles with the code as previously described using the following in the AccessoryButtonTapped method:
navController.PushViewController(detailScreen, true);
When I run this and tap on the AccessoryButton I get a null reference exception on navController. The reference to this.NavigationController in the ViewController constructor is null. Am I doing something in the wrong place or sequence?
Cheers
The NavigationController property is on your table's view controller. If you are trying to reference it from your table's datasource, you need to pass a reference to the controller when you create the datasource.

Manually add more tabs to UITabController with Storyboard and Monotouch

I am currently using the new iOS 5 Storyboard approach to creating my Tabbed Application with Monotouch. I have developed two of my tab views in Xcode with Storyboard and linked them appropriately to the Tab Bar Controller. I also want to develop (in Xcode) a third tab view that would be shared among two additional tabs. I want to reuse the same layout, but display different data depending on which tab is selected (think something like a "Popular" and a "Recent" that would have the same layout but different data).
To do this, I figured I could add the tab manually twice after the Storyboard-driven tabs are added. How do I do this with the Storyboard approach? I'm not sure where in the code to do this since the loading of the Storyboard seems pretty transparent (i.e. no code in AppDelegate that I see). Or, is there another (easier/better) way to share a view between two tabs using the Storyboard approach?
I don't know Monotouch, but here's how I did it in Objective-c. I didn't find anything about this topic, so if something is wrong, people please comment :) By the way, I'm using ARC, so I don't manually manage memory! What I needed to achieve was like you, having a tab bar, loading the same viewController, but loading different data for each tab.
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UITabBarController *root = (UITabBarController*)self.window.rootViewController;
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
TeamViewController *home = [[mainStoryboard instantiateViewControllerWithIdentifier:#"Team"] initHome];
TeamViewController *visitor = [[mainStoryboard instantiateViewControllerWithIdentifier:#"Team"] initVisitor];
[root setViewControllers:[NSArray arrayWithObjects:home, visitor, nil] animated:NO];
UITabBar *tabs = root.tabBar;
UITabBarItem *homeTab = [tabs.items objectAtIndex:0];
UITabBarItem *visitorTab = [tabs.items objectAtIndex:1];
homeTab.title = #"Home team";
visitorTab.title = #"Visitor team";
return YES;
}
You can see I call initHome and initVisitor when I load my two TeamViewController, here is the code about it.
TeamViewController.h
#interface TeamViewController : UIViewController
{
enum
{
HOME,
VISITOR
};
int team;
}
TeamViewController.m
- (id)initHome
{
team = HOME;
return self;
}
- (id)initVisitor
{
team = VISITOR;
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if(team == HOME)
{
label.text = #"home data";
}
else if(team == VISITOR)
{
label.text = #"visitor data";
}
}
I don't know how well you can translate that to your project, but I hope you get the big picture of it :)
If you need to read a bit about how to access the first view controller using the storyboard: http://developer.apple.com/library/ios/#releasenotes/Miscellaneous/RN-AdoptingStoryboards/_index.html#//apple_ref/doc/uid/TP40011297
There is a section called "Accessing the First View Controller"

Passing Managed Object Data Through didSelectRow UIPickerView

I'm a bit lost on how to pass my fetched managed object data through a didSelectRow UIPickerView action.
On the previous view, I passed the CalcInfo object like this:
CalcInfo *calc = (CalcInfo *)[_calcInfos objectAtIndex:indexPath.row];
self.myPageOneViewController.calcInfos = calc;
I was successfully able to use calcInfos.attribute for all my IBAction:(id)sender buttons, but the pickerView isn't able to fetch / use the data. The updateLabel action always has calcInfos.attribute as NULL. Here's a bit of my code
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
[self updateLabel];
}
- (void)updateLabel {
double stdrate = [calcInfos.infusionstd doubleValue];
double lowrate = [calcInfos.infusionlow doubleValue];
if (calcInfos.infusionlow == NULL) {
NSLog(#"It's null");
}
}
Your help is much appreciated!
The picker view is a subview with its own hardwired controller. It returns the row and column/component picked in its delegate message `didSelectRow:inComponent'.
You need to pass that info along to your updateLabel method so that you can relate the pickerview selection to your managed objects. Right now, the method does nothing at all.

Resources