Custom TableViewCell with Core Data - ios

I have a Destination View Controller that allows you to edit information displayed in the TableViewController..I am attempting to set this up in a custom cell..I have my UITableViewCell file with the custom property class and I also have my Model Class for the Core Data with the attributes. I managed to get my root table view controller to show the custom label when I add a NEW player but once I click on the cell and edit it in the new view controller it goes back to the default on the table view. I believe it has something to do with this code but I can not figure it out.
my NsManagedObject Subclass
#property (nonatomic, retain) NSString *playerFirstName;
I have a pointer to my Player Class of currentPlayer in my viewcontroller.h file and the firstnameTextfield is my UITextField
-(IBAction)doneEditing:(id)sender {
_currentPlayer.playerFirstName = firstnameTextField.text;
AppDelegate *myApp = (AppDelegate *) [[UIApplication sharedApplication]delegate]'
[myApp saveContext];
}
Update
I believe this is my line of code that is the problem after messing with it
_currentPlayer.playerFirstName = firstnameTextField.text;
how do I get the currentPlayer pointer to go to my playerNameCell property in my customcell class

You should do something like:
- (IBAction)newPlayer {
_currentPlayer = (Player*) [NSEntityDescription insertNewObjectForEntityForName:#"Player" inManagedObjectContext:_managedObjectContext];
}
The _managedObjectContext should be passed to the view controller from the app delegate or some other view controller.

Related

Can I use one custom created UIViewController to populating cells text value of parent UITableViewController?

I have created one custom ViewController named SetValueVC with UITextView in it. During creating new product in my app I display UITableViewController with cell that need to be specify. If user click on some cell I display my UIViewController as detailView to allow setting parent UITableViewCells detailLabel.text value. I know how to pass data from child view by using delegate but how it works when there is for example 10 rows? Should I create 10 delegates methods for every row or just create object of SetValueVC for every row in didselectForRow method and use just one delegate method ? Thanks in advance
That could be an answer : Work with a singleton and use your model in your ViewController and your UITableViewController
in the .h :
+(MyModel *)shared;
in the .m :
static MyModel *myModel;
#implementation MyModel
+(MyModel *) shared{
if (nil != myModel) {
return myModel;
}
static dispatch_once_t pred;
dispatch_once(&pred, ^{
myModel = [[MyModel alloc] init];
});
return myModel;
}
In this way, you can access to your model anywhere of your app.
Hope that will help.

Where to initialise an object

I have a UITableView in my main view and an 'add' button in a UINavigationBar that will push to another view that allows the user to add another object to the tableview. I have a protocol in this view that allows the information to be sent back to the main view.
My problem is that whenever I try to add this new object sent from the protocol (which is a NSMutableDictionary) to a NSMutableDictionary property in the main view, it does not add. I have tried adding an NSLog and it says that this object is null. If I initialise this object in the viewDidLoad method, it will run whenever the UINavigationController pops the view, and resets everything in the dictionary. I do not know where to initialise the object to make sure that it keeps everything stored in it.
The protocol works fine, but I cannot do anything with the object it sends.
In AddCellViewController.h:
#import <UIKit/UIKit.h>
#protocol AddCellDelegate <NSObject>
#required
-(void)passCellInfo:(NSMutableDictionary *)cellInfo;
#end
#interface AddCellViewController : UITableViewController <UITextFieldDelegate> {
id <AddCellDelegate> delegate;
}
#property (strong) id <AddCellDelegate> delegate;
#end
in AddCellViewController.m (the method that utilises the protocol):
-(void)sendObject{
[[self delegate] passCellInfo:newCellInfo];
[self.navigationController popToRootViewControllerAnimated:YES];
}
in MainView.m:
-(void)passCellInfo:(NSMutableDictionary *)cellInfo{
[self.cellInformation setValue:cellInfo forKey:[cellInfo objectForKey:#"cell_title"]];
[self.cells addObject:[cellInfo objectForKey:#"cell_title"]];
[self.tableView reloadData];
NSLog(#"%#: cellInfo - cellInformation: %# - cells: %#",cellInfo ,self.cellInformation,self.cells); //logs the object passed from the protocol (this works), the cellInformation object, and cells object (these return null)
}
You can use a NSMutableDictionary property in a static or global class, and access it very easy from the tableview or any other view:
You feed your table from that dictionary
And you add elements from your other view into that dictionary (the protocol is not needed anymore).
Everytime your tableView appears, you should refresh the data of the table from this global class.
Some example of how to use it:
How to implement global static class
In your code you do this. You using same key every time. So it will get replaced.
[self.cells addObject:cellInfo];
I will tell you a simple way instead. Send your mutableDictionary to secondView from init method. Copy in class level mutableDictionary. Do not allocate or initialize. Add new item in that Dictionary. It will reflect in mainView dictionary. Call [tableView reloadData] in mainView viewWillAppear method.

How do I access a Model Object from different viewControllers

I'm not sure if I'm taking the right approach to this, but I want to access my model for a Shopping Cart Class from different viewControllers. My first approach was to init a Cart * object in each viewController, but I think I just ended up with multiple cart objects when all I want is one that can be accessed globally. After searching I came up with a different approach that seems better, but no luck yet.
I have a button that is supposed to add a deal to a shopping cart. but when I try to add it, the method is not getting called. Here is how I have it set up.
In my Cart class I have a NSMutableArray to hold my deals.
In my viewController I set up a property of type Cart *cart and initialized like this
#property (strong, nonatomic) Cart *cart;
...
-(id)initWithModel:(Cart *)cart {
self = [super init];
if(self){
self.cart = cart;
}
return self;
}
Then my button method is this
-(IBAction)addDealToCart {
NSLog(#"The Cart has %i items", [self.cart qtyOfItemsInCart]);
NSLog(#"Added the Deal to the Cart");
[self.cart addDealsToCart:self.deal];
NSLog(#"The Cart now has %i items", [self.cart qtyOfItemsInCart]);
self.deal.qtyInCart = self.deal.qtyInCart + 1;
NSLog(#"the deal has %i items in the Cart", self.deal.qtyInCart);
}
In this line addDealsToCart:deal never gets called.
here is my addDealsToCart:deal method in my Cart Class
-(void)addDealsToCart:(Deals *)deal {
[self.cartContents addObject:deal];
NSLog(#"the deal was added to the cart %#",deal);
}
any help would be great. thanks
Without going for a whole re-architecturing, why don't you pass your cart object to each view controller? I personally wouldn't go the singleton route that your description hints of.
Update (example):
UIViewController *yourNextVC = [[YourNextVC alloc] init];
yourNextVC.cart = self.cart //The current cart in your current vc, passing it along.
[self presentViewController:yourNextVC animated:YES completion:nil];
I you just want one Cart variable througout the app you can have it in appDelegate if you want
#property (strong, nonatomic) Cart *cart;
And taking out is simple
AppDelegate *appDelegateObject=(AppDelegate*)[[UIApplication shareApplication] delegate];
appDelegateObject.cart.qtyOfItemsInCart= 1; //initialize where you want.
Take out in another view controller like this:
AppDelegate *appDelegateObject=(AppDelegate*)[[UIApplication shareApplication] delegate];
NSLog(#"cart value: %d,appDelegateObject.cart.qtyOfItemsInCart);

CoreData: Accessing the instance of NSManagedObject

I have 3 Scenes each collecting User's input. Each Scene has 5 UITextFields. The 4th Scene shows all the 15 Text Field in a UITableView.
I'm not sure if this is the best way to do do this, but I have the following code for scene 1:
//Meetings is NSManagedObject class. Meetings.h and .m was created from the Meetings entity from Core Data
//I have this code once in the file right before I start saving the data
Meetings *meetings = (Meetings *) [NSEntityDescription insertNewObjectForEntityForName:#"Meetings" inManagedObjectContext:self.managedObjectContext];
// I have similar code below for each user's input.
NSString *date = [[NSString alloc] initWithFormat:#"%#", [dateFormatter stringFromDate:selectedDate]];
DateLabel.text = date;
[meetings setDateLabel:date];
...
[meetings setTimeLabel:time];
..
//Code below is to save. I have this once at the end of the file to save the data
NSError *error = nil;
if (![managedObjectContext save:&error]) {
// Handle the error.
}
//The log below shows the saved data fine. Thus, the data is being saved in managnedObjectContext.
NSLog (#"This is the DateLabel %#", meetings.DateLabel);
Question: How do I access the pointer *meetings from Scene 2 and 3 to save rest of the fields in managedObjectContext? I did a NSLog from Scene 2 and it shows as Null:
//In Scene 2 viewDidLoad method I did the following to check:
self.managedObjectContext = [(STAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
Meetings *meetings = (Meetings *) [NSEntityDescription insertNewObjectForEntityForName:#"Meetings" inManagedObjectContext:self.managedObjectContext];
NSLog (#"This is the DateLabel from Scene 2 %#", meetings.DateLabel);
The log shows:
2013-02-11 18:04:05.447 MyApp[3505:c07] This is the DateLabel from Scene 2 (null)
You either need to pass a pointer to the Meetings object from the previous screens forward to the next by storing them in a property, or you can pass the object's id's and fetch them as needed for the final screen.
Assume the following is a reflection of your code. The class names may not be identical, but I think you will be able follow and change them as needed.
Scene 1 Header File:
//
// Scene1ViewController.h
// ... etc.
#import <UIKit/UIKit.h>
#import "Meetings.h"
#interface Scene1ViewController : UIViewController
#property (nonatomic, strong) Meetings *meetingsForScene1;
// ... etc.
#end
Scene 2 Header File:
//
// Scene2ViewController.h
// ... etc.
#import <UIKit/UIKit.h>
#import "Meetings.h"
#interface Scene2ViewController : UIViewController
#property (nonatomic, strong) Meetings *meetingsFromScene1;
#property (nonatomic, strong) Meetings *meetingsForScene2;
// ... etc.
#end
meetingsForScene2 may or may not be appropriate depending on your requirements. You might just add data from Scene2 to the meetingsFromScene1 and pass that instance on to the next scene.
Scene 1 Implementation's -prepareForSegue:sender::
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *destinationViewController = segue.destinationViewController;
if ([segue.identifier isEqualToString:#"YourSegueIdentifierForTransistionFromScene1ToScene2"]) {
Scene2ViewController *scene2 = [destinationViewController isKindOfClass:[Scene2ViewController class]] ? (Scene2ViewController *)destinationViewController : nil;
NSAssert(scene2, #"scene2 should not be nil");
NSAssert(self.meetingsForScene1, #"self.meetingsForSecen1 should not be nil");
scene2.meetingsFromScene1 = self.meetingsForScene1;
}
}
Note you might have two properties on Scene2. One for the current scene's data and one for the previous scene's data. The important property is the one that holds the data from the previous scene. The -prepareForSegue:sender: method in Scene1 is an appropriate time to set Scene1's data to the property on Scene2.
I've included some NSAssert calls to do some checking. Consider removing those in your production code. Also, note the check when assigning *scene2. If your destination controller is not the right "kind", you'll find out right away.
I am not necessarily advocating this approach as the "best" for your problem, but this approach will at least provide a path to a solution, if not address the issue entirely.
Well, what you do in your viewDidLoad method is creating a new object in your NSManagedObjectContext instance.
What you should do is to make a fetch request for your previously created Meetings object.
Maybe you should read a tutorial about Core Data. The following is very easy to understand: http://www.raywenderlich.com/934/core-data-on-ios-5-tutorial-getting-started

Modify tableview (lied on another view controller ) based on table row selected

How to change the Images in table view which is lied in the new view controller based on row selected .
e.g. Say I hv category table in my Category view controller.Now when user taps on Camera,a new view controller should load containing all the camera images and on tap of any image,it should display its Detail.
how to implement this , as I am new to this tech.,Please help me ...
you can follow some simple steps to make it working.
1. First View: add the following code in your didSelectRowAtIndexPath method of tableview
-(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Fetch the value of the selected row in NSString
NSString *tableRowValue = cell.textLable.text;
//Call the next view
secondView *secondViewController = [[secondVIew alloc] initWithNibName:#"secondView" bundle:nil];
secondViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve ;
//Initialize the view with the clicked row value thwough NSString variable
[secondViewController initializeWith:tableRowValue];
}
2.Second View:
In your .h file, add the following initialization method:
-(void)initializeWith:(NSString *)sentRowValue;
IN your .m file, implement the initilization method:
-(void)initializeWith:(NSString*)sentRowValue
{
NSString *receivedRowValue = sentRowValue;
//take log to check
}
// now perform all the table view delegate methods using the value you have received.
NOTE: declare all the variables in your .h file and make them as property and synthesize them in your .m file
hope this helps

Resources