Passing Data from view Controller to NSObject class - objective-c

I know how to pass the data from one view controller to another view controller ,now i want to know how to pass a textfield value from view controller to NSObject class and how to store the recieved in nstring .Please help me to do this , Can anyone give a example for this ,

I think what you're asking is how to store data in a model object for use by your view controller. If this is not your meaning, then please forgive me.
You are right that a model object should inherit from NSObject. Optionally, you could also extend another model object to add property values. Model objects are a great way to separate the view objects from your data.
Let's say you have a CustomerViewController with some customer fields. You need to populate those customer fields, and potentially perform some processing on that data. The model object supports these relationships, by allowing you to separate your views from any processing logic related to your data and business rules.
Using the relationships below as a guide, you should be on your way to building effective view controllers, that separate your views from your data!
CustomModel Interface
#interface CustomerModel : NSObject
#property (strong, nonatomic) NSString *firstName, *lastName;
#property (strong, nonatomic) NSString *phoneNumber;
- (BOOL) isValidPhoneNumber:(NSString *)phoneNumber;
#end
CustomerModel Implementation
#import "CustomerModel.h"
#implementation CustomerModel
- (BOOL) isValidPhoneNumber:(NSString *)phoneNumber
{
//Check that phone number can be parsed and is valid
}
#end
CustomerViewController Implementation
#import "CustomerViewController.h"
#import "CustomerModel.h"
#interface CustomerViewController () <UITextFieldDelegate>
#property (strong, nonatomic) CustomerModel *customerModel;
...
#property (weak, nonatomic) IBOutlet UITextField *firstNameField
...
#end
#implementation CustomerViewController
- (void) viewDidLoad {
//Optionally instantiate the customer model with stored data,
// to pre-populate the view controller.
self.customerModel = [CustomerModel new];
self.firstNameField.delegate = self;
}
- (void) textFieldDidEndEditing:(UITextField *)textField {
//Validate the phone number
NSString *phoneNumber = textField.text;
if ([self.customerModel isValidPhoneNumber:phoneNumber]) {
self.customerModel.phoneNumber = phoneNumber;
} else {
//Alert the user that the data is invalid
}
}
- (BOOL) textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
#end
Possible improvements
It might be a little annoying to the User, to see alerts while filling out information. So, it might be better to defer the validation to when a save button is pressed.
Model objects can be populated from a data store, to be used to pre-populate a form.

Related

Change selected object with multiple nsarraycontrollers

I am trying to implement example as shown on developer.apple.com
Everything works but selectedWeapon does not change.
Q1: I have no idea what I forgot so the selection would work correctly
Q2: According to Apple "the example requires no actual code to set up the user interface". I am filling objects from code. Is there any way to add objects into arrayController in XIB?
#implementation Combatant
- (instancetype)initWithName:(NSString *)aName
{
self = [super init];
if (self) {
_weapons = #[#"Dagger", #"Sword", #"Pike"];
_name = aName;
_selectedWeapon = [_weapons firstObject];
}
return self;
}
#end
#interface Combatant : NSObject
#property (nonatomic, strong) NSString *name;
#property id selectedWeapon;
#property NSArray *weapons;
- (instancetype)initWithName:(NSString *)aName;
#end
Repository: https://github.com/xhruso00/moderatelyComplexBindings
Q1: The selection index of NSPopupButton wasn't linked to arrayController. Without it the arrayController did not know which option is selected.
Q2: Impossible. Apple talks about the glue code.

How to implement custom UIDynamicBehavior action

I have been looking for an example showing how to implement a custom UIDynamicBehavior in UIKit dynamics. All the tutorials and examples show only how to assemble a UIDynamicBehavior using primitives (collision, gravity, attachment, push, snap etc.)
In my app, some views are floating around the screen (using dynamics) and I want to make them disappear when they overlap other stationary views. To do this, I wanted to test for overlap in the UIDynamicAnimator and UICollisionBehavior delegate methods, but unfortunately those methods do not provide enough granularity to get perform the tests I need.
EDIT: apparently I had to wait a day before answering my own question (new user), so my solution is posted below as an answer now.
The approach I chose was to develop my own UIDynamicBehavior class and add that to the animator, and it now makes the floating views disappear when they overlap the stationary views.
Sample code below shows how to write your own UIDynamicBehavior class to plug your own behaviour into the UIDynamicAnimator. I called the class UISinkBehavior, because it "sinks" a view when the view moves over the "sinkhole".
// UISinkBehavior.h
#import <UIKit/UIKit.h>
#protocol UISinkBehaviorDelegate <NSObject>
- (void)sunk:(id)item;
#end
#interface UISinkBehavior : UIDynamicBehavior
#property (weak, nonatomic) id<UISinkBehaviorDelegate> delegate;
- (id)initWithItems:(NSMutableArray*)items withSinkhole:(UIView*)sinkhole;
#end
// UISinkBehavior.m
#import "UISinkBehavior.h"
#interface UISinkBehavior ()
#property (nonatomic) NSMutableArray *items;
#property (nonatomic) id<UIDynamicItem> sinkhole;
#end
#implementation UISinkBehavior
- (id)initWithItems:(NSMutableArray*)items withSinkhole:(UIView*)sinkhole
{
if (self = [super init])
{
_items = items;
_sinkhole = sinkhole;
// weak self ref to avoids compiler warning about retain cycles
__weak typeof(self) ref = self;
// this is called by the UIDynamicAnimator on every tick
self.action = ^{
UIView *item;
// check each item if it overlaps sinkhole
for (item in ref.items)
if (CGRectIntersectsRect(item.frame, sinkhole.frame))
{
// sink it (handled by delegate
[ref.delegate sunk:item];
// remove item from animation
[ref.items removeObject:item];
// remove behaviour from animator when last item sunk
if (ref.items.count < 1)
[ref.dynamicAnimator removeBehavior:ref];
}
};
}
return self;
}
#end

inherit methods declared in .m file

I now know there is no protected method in Objective-C and here is my problem.
I have two viewControllers with many functions and properties that are shared. My vision was to have a BaseViewController holding the shared methods and properties, and from it two classes will inherit and override the needed functionality while using the same variables,
I don't wish to convert the shared functions to public by placing them in the .h file
To help clarify my question I'm adding code :)
#interface BaseViewController ()
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *uiButtons;
- (void)setBtns:(NSArray *)p_btns; //tried with & without this line
#end
#implementation BaseViewController
- (void)setBtns:(NSArray *)p_btns {
uiButtons = p_btns;
//do something generic with the buttons (set font, image etc.)
}
#end
#interface DerivedViewController ()
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *buttonsConnectedToTheActualView;
#end
#implementation DerivedViewController
- (void) setBtns:(NSArray *)p_btns {
[super setBtns:p_btns];
//do something specific with the buttons (decide if they face up or down according to this class logic)
}
#end
The call to [super setBtns:p_btns]; raises an error:
DerivedGameViewController.m:No visible #interface for 'BaseViewController' declares the selector 'setBtns:'
How can I achieve this? Can someone post a snippet or point to my mistake (in code or concept).
Just create a second header with the protected methods declared in a category. Name and document the header appropriately.
UIGestureRecognizer.h and UIGestureRecognizerSubclass.h may server you as an example.

How to generate a generic table view controller?

I've created a custom TablePickerViewController which is a subclass of UITableViewController. I'm using this class to display a list of object of a custom type TablePickerItem.
I'm using TablePickerViewController multiple times in my iOS application to show different kinds of lists where the user has to pick an item -- and then another view controller MainViewController should react on this selection and do something.
I've created this protocol and created a delegate property in the TablePickerViewController:
#protocol TablePickerViewControllerDelegate <NSObject>
- (void)tablePickerViewController:(TablePickerViewController *)controller
didSelectItem:(TablePickerItem*)item;
#end
When I setup a new TablePickerViewController in MainViewController it is also set as delegate -- than it will be notified when the user taps an cell in the table view.
The problem is that my MainViewController will setup multiple TablePickerViewController with different data (TablePickerItem). How should I setup my MainViewController to handle these multiple TablePickerViewController? Events from each of them will results in calling to the same protocol-method in my MainViewController.
Further I need to get the element which the TablePickerItem represents, as I need to know for instance the elements ID when acting in the tablePickerViewController:didSelectItem method. Should I just handle this by adding something like #property (nonatomic) id element to the TablePickerItem and set the original object into this property then creating it?
Maybe someone can give me an example on how to create an generic table view controller, if my solutions seems being done in the wrong way.
I'm not entirely sure of your set up, but if you have multiple pickers that feedback to the main controller then you could just have a reference to the picker e.g.
// MainViewController.m
#interface MainViewController ()
#property (nonatomic, strong) TablePickerViewController *picker1;
#property (nonatomic, strong) TablePickerViewController *picker2;
// ... and so on. Obviously you know your problem domain so you can change
// the terrible naming above to something appropriate
#end
#implementation MainViewController
// ...
- (void)theMethodWhereYouSetUpYourPickers;
{
TablePickerViewController *picker1 = [[TablePickerViewController alloc] init];
picker1.delegate = self;
self.picker1 = picker1;
// ...
}
- (void)tablePickerViewController:(TablePickerViewController *)controller
didSelectItem:(TablePickerItem*)item;
{
if (controller == self.picker1) {
NSLog(#"Something was picked in picker 1 %#", item);
} else if (controller == self.picker2) {
NSLog(#"Something was picked in picker 2 %#", item);
}
}
// ...
#end

No access to global instance (build by factory) on iOS

this is a follow-up question to my last one here: iOS: Initialise object at start of application for all controllers to use .
I have set my application up as follows (ignore the DB Prefix):
DBFactoryClass // Built a DataManaging Object for later use in the app
DBDataModel // Is created by the factory, holds all data & access methods
DBViewControllerA // Will show some of the data that DBDataModel holds
moreViewControllers that will need access to the same DBDataModel Object
i will go step by step through the application, and then post the problem in the end
AppDelegate.h
#import "DBFactoryClass.h"
AppDelegate.m
- (BOOL)...didFinishLaunching...
{
DBFactoryClass *FACTORY = [[DBFactoryClass alloc ]init ];
return YES;
}
DBFactoryClass.h
#import <Foundation/Foundation.h>
#import "DBDataModel.h"
#interface DBFactoryClass : NSObject
#property (strong) DBDataModel *DATAMODEL;
#end
DBFactoryClass.m
#import "DBFactoryClass.h"
#implementation DBFactoryClass
#synthesize DATAMODEL;
-(id)init{
self = [super init];
[self setDATAMODEL:[[DBDataModel alloc]init ]];
return self;
}
#end
ViewControllerA.h
#import <UIKit/UIKit.h>
#import "DBDataModel.h"
#class DBDataModel;
#interface todayViewController : UIViewController
#property (strong)DBDataModel *DATAMODEL;
#property (weak, nonatomic) IBOutlet UILabel *testLabel;
#end
ViewControllerA.m
#import "todayViewController.h"
#implementation todayViewController
#synthesize testLabel;
#synthesize DATAMODEL;
- (void)viewDidLoad
{
todaySpentLabel.text = [[DATAMODEL test]stringValue]; // read testdata
}
#end
DBDataModel.h
#import <Foundation/Foundation.h>
#interface DBDataModel : NSObject
#property (nonatomic, retain) NSNumber* test;
#end
DBDataModel.m
#import "DBDataModel.h"
#implementation DBDataModel
#synthesize test;
-(id)init{
test = [[NSNumber alloc]initWithInt:4]; // only a testvalue
return self;
}
#end
the app builds fine, and starts up but the label stays blank. so either the object does not exist (but i guess this would result in an error message), or something else is wrong with my setup. any thoughts?
Two notes:
Your have a shotgun approach to asking questions: everytime you hit a stumbling block, you ask a question and if the answer does not work immediately, you ask another one. You have to spend some energy in between the questions debugging and poking into the code on your own, otherwise you will depend on the external help forever.
Use the common coding style please. CAPS are reserved for macros.
Now to the code:
- (BOOL) …didFinishLaunching…
{
DBFactoryClass *factory = [[DBFactoryClass alloc] init];
return YES;
}
This simply creates an instance of the DBFactoryClass and then throws it away. In other words, it’s essentially a no-op. Judging by the comments in the previous answer you create the controllers using the Storyboard feature. How are they supposed to receive the reference to the data model? The reference isn’t going to show up by magic, you have to assign it somewhere.
I’m not familiar with the Storyboard feature. The way I would do it is to create the view controllers using separate XIB files, then you can create the controller instances in the Factory class and pass them the needed reference to the model. In the end the application delegate would create the factory, ask it to assemble the main controller and then set it as the root view controller for the window. Just like in my sample project. It’s possible that there’s a way to make it work with storyboards, but as I said, I am not familiar with them.