Pass values from a UIViewController to another - iphone

before the closing of my FlipsideViewController I have these values
shours
sminutes
sseconds
srecharge
change
from the declaration
int shours;
int sminutes;
int sseconds;
int srecharge;
bool change;
Now I want to pass these variables to another UIViewController (MainViewController) in these other variables
mhours
mminutes
mseconds
mrecharge
mchange
What's the simplest method to do this?

Create a custom object property on your MainViewController and set it on your FlipsideViewController or you can't do it for some reason: Create an object to hold these values and put it into NSUserDefaults and read on MainViewController.

I would simply create a "Model" class that holds those vars and pass the model class from one view controller to the next. Once it's linked in view1 & view2 during transition from view1 to view2, then it's automatically updated when transitioning back from view2 to view1. Use #property (assign) int shours so you have setters and getters created.
With this approach, using segues will work just fine. You don't need to use NSUserDefaults or NSNotificationCenter.

I would create a class to hold these values. Then pass this object between view controllers.
Something like this:
Interface file:
//
// MyObject.h
// SOObjectPassing
//
// Created by Wilson, LJ on 11/15/12.
// Copyright (c) 2012 Arkansas Children's Hospital. All rights reserved.
//
#import <Foundation/Foundation.h>
#interface MyObject : NSObject {
int shours;
int sminutes;
int sseconds;
int srecharge;
bool change;
}
#property (nonatomic, assign) int shours;
#property (nonatomic, assign) int sminutes;
#property (nonatomic, assign) int sseconds;
#property (nonatomic, assign) int srecharge;
#property (nonatomic, assign) BOOL change;
-(id) initWithHours:(int)hours
minutes:(int)minutes
seconds:(int)seconds
recharge:(int)recharge
changed:(BOOL)changed;
#end
Implementation file:
//
// MyObject.m
// SOObjectPassing
//
// Created by Wilson, LJ on 11/15/12.
// Copyright (c) 2012 Arkansas Children's Hospital. All rights reserved.
//
#import "MyObject.h"
#implementation MyObject
#synthesize shours = _shours;
#synthesize sminutes = _sminutes;
#synthesize sseconds = _sseconds;
#synthesize srecharge = _srecharge;
#synthesize change = _change;
-(id) initWithHours:(int)hours
minutes:(int)minutes
seconds:(int)seconds
recharge:(int)recharge
changed:(BOOL)changed {
if ((self = [super init])) {
_shours = hours;
_sminutes = minutes;
_sseconds = seconds;
_srecharge = recharge;
_change = changed;
}
return self;
}
#end
And instantiate your object like this:
MyObject *myObject = [[MyObject alloc] initWithHours:2
minutes:3
seconds:4
recharge:1
changed:NO];
Then just pass that entire object to your other VC (s).
Here is a sample project illustrating this.

Related

Class Extension - unrecognized setter

The following codes crashed:
#interface AppDelegate (PrivateMethods)
#property (nonatomic, strong) NSString * name;
#end
#implementation AppDelegate
- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.name = #"foobar";
...
Error is:
'-[AppDelegate setName:]: unrecognized selector sent to instance 0x6d73df0'
When I change
#interface AppDelegate (PrivateMethods)
to
#interface AppDelegate ()
Then it is okay, what would be the reason?
Update: As answered below, since I must use class extension for this purpose, now this question become: Is the use of class extension to declare private methods acceptable?
e.g.
#interface AppDelegate ()
- (void) start;
#property (nonatomic, strong) NSString * name;
#end
Class extension is basically used to enhance the public property variable. Suppose you have exposed readonly object, or getter method of any variable, then you have make the same object as readwrite in extension.Whereas Category is only used to enhance the method/functionality of class.
check this
#interface MyClass : NSObject
// property here is used as readonly.
#property (retain, readonly) float value;
#end
// Private extension, typically hidden in the main implementation file.
#interface MyClass ()
#property (retain, readwrite) float value;
#end
or
#interface MyClass : NSObject
// here we have exposed getter method of private instance.
- (float) value;
#end
// Private extension, typically hidden in the main implementation file.
#interface MyClass ()
#property (retain, strong) float value;
#end
One is a category, the other is a class extension. If you want to add properties to an existing class, you need to use the latter.
This is the right approach:
#interface AppDelegate ()
#property (nonatomic, strong) NSString * name;
#end

Object released too soon using ARC on iOS 5?

I created a class AppSettings containing booleans:
#import <Foundation/Foundation.h>
#interface AppSettings : NSObject{
bool bip10secCountdown;
bool jv10secCountdown;
bool jv30secAlert;
bool jv1minAlert;
bool jvp5minAlert;
}
#property bool bip10secCountdown;
#property bool jv10secCountdown;
#property bool jv30secAlert;
#property bool jv1minAlert;
#property bool jv5minAlert;
#end
And the implementation:
#import "AppSettings.h"
#implementation AppSettings
#synthesize bip10secCountdown, jv10secCountdown, jv30secAlert, jv1minAlert, jv5minAlert;
- (id)init
{
self = [super init];
if (self){
}
return self;
}
#end
Then I'm trying to use this class in my main class but after initializing the object in the viewDidLoad, when I want to use it again it appears as null.. So I guess it's released too early. I'm using ARC so I don't manually manage the memory. Am I doing something wrong ?
The declaration in the main class:
AppSettings *appSettings;
}
#property(nonatomic)bool activated;
#property (nonatomic, strong) AppSettings *appSettings;
And the implementation:
#synthetize appSettings
...
- (void)viewDidLoad
{
// Initialize the model
self.appSettings = [[AppSettings alloc]init];
NSLog(#"appSettings = %#",self.appSettings);
The first output is OK.
But then when I try to access appSettings from another method in the Main class, the appSettings is (null)
Thank you for your help.
The view has most likely unloaded, or your view controller has been released. Try moving the initialization code to the method where your view controller is initiated(- (id)initWithNibName: bundle:)
Instead of:
#property (nonatomic, strong) AppSettings *appSettings;
Try:
#property (nonatomic, retain) AppSettings *appSettings;
And I'd recommend to make your AppSettings as a Singleton-class.
When you say you initialise the view contoller in AppDelegate I presume you mean MyViewController *theView = [[MyViewController alloc] init]; or something like that. That will be your first view and you should initialise AppSettings in viewDidLoad of MyViewController, not the AppDelegate.
demon9733 suggestion regarding making AppSettings a singleton is a good one as you will be able to easily access your settings from anywhere in the app.
Also verify whether ARC is being used for MyViewController (or whatever it might be)

Override #synthesize method?

I have one class called dog and another class called cat.
Dog has an variable, "name" declared with #property in the .h file.
In the cat class, I have set the name by using the command, myDog.name = "buster", after creating the variable "myDog" of type dog.
I would like to do additional operations when the name is set by overriding the set method normally created by the #synthesize command.
How can I do that? Thanks for the help!
All you have to do is leave the #synthesize then create whichever methods you want to be custom. Example:
In .h
#property(nonatomic, retain)NSString *Bob;
In .m
#synthesize bob;
-(void)setBob:(NSString *)bobValue{
[bobValue retain];
[bob release];
bob = bobValue;
//your custom stuffs here
}
This has been pretty much answered on SO already - see Objective-C synthesize property name overriding for details. In particular, #Dev Kanchen's answer which includes example code.
You cannot override (and call it within) a synthesized method from within the very same class.
You can however override it from a subclass (or rather: synthesize it in an abstract superclass).
If you simply want to perform additional (vs. different) operations upon property change I would use KVO by simply adding each dog as observer to its own "name" property in -(id)init;.
Edit:
There is a way to add additional logic to synthesized methods from within the same class:
Define a private intermediate property in a class extension.
I've attached source code for a class which uses synthesized properties and takes care(sic!) of keeping the dog's owner in sync with its own identity.
Dog.h:
#import <Foundation/Foundation.h>
#interface Dog : NSObject {
#private
NSString *name;
NSString *owner;
}
#property (nonatomic, readwrite, retain) NSString *name;
#property (nonatomic, readwrite, retain) NSString *owner;
#end
Dog.m:
#import "Dog.h"
#interface Dog ()
#property (nonatomic, readwrite, retain) NSString *primitiveName;
#end
#implementation Dog
#dynamic name;
#synthesize primitiveName = name;
#synthesize owner;
- (id)init {
if ((self = [super init])) {
name = #"Snowy";
owner = #"Tintin";
}
return self;
}
- (void)dealloc {
[super dealloc];
}
- (NSString *)name {
return self.primitiveName;
}
- (void)setName:(NSString *)aName {
self.primitiveName = aName;
if ([aName isEqualToString:#"Snoopy"]) {
self.owner = #"Charlie Brown";
}
else if ([aName isEqualToString:#"Snowy"]) {
self.owner = #"Tintin";
}
}
- (NSString *)description {
return [NSString stringWithFormat:#"<%# name:'%#' owner:'%#'>", [self class], self.name, self.owner];
}
#end
Test:
Dog *dog = [[Dog alloc] init];
NSLog(#"%#", dog);
dog.name = #"Snoopy";
NSLog(#"%#", dog);
dog.name = #"Snowy";
NSLog(#"%#", dog);
Result:
<Dog name:'Snowy' owner:'Tintin'>
<Dog name:'Snoopy' owner:'Charlie Brown'>
<Dog name:'Snowy' owner:'Tintin'>

What’s the point of repeated class interface declaration in the implementation file?

In some of the Apple Iphone examples, some of the properties are declared in the header file and some properties in the implementation file. For example in the Siesmic XML examples
ParseOperation.h
#interface ParseOperation : NSOperation {
NSData *earthquakeData;
#private
NSDateFormatter *dateFormatter;
// these variables are used during parsing
Earthquake *currentEarthquakeObject;
Contact *currentContactObject;
NSMutableArray *currentParseBatch;
NSMutableString *currentParsedCharacterData;
BOOL accumulatingParsedCharacterData;
BOOL didAbortParsing;
NSUInteger parsedEarthquakesCounter;
}
#property (copy, readonly) NSData *earthquakeData;
#end
ParseOperation.m
#interface ParseOperation () <NSXMLParserDelegate>
#property (nonatomic, retain) Earthquake *currentEarthquakeObject;
#property (nonatomic, retain) NSMutableArray *currentParseBatch;
#property (nonatomic, retain) NSMutableString *currentParsedCharacterData;
#property (nonatomic, retain) Contact *currentContactObject;
#end
What is the use of the additional interface declaration in the implementation file ?
That’s simply a difference between a public and a private class interface. The header describes the public interface, but some of the properties are only meant to be used by the class itself, not by its collaborators. These private properties are usually declared the way you described, as a category or a class extension inside the implementation file.
// Foo.h – the public interface
#interface Foo : NSObject {…}
// Collaborators can only read bar.
#property(readonly) int bar;
#property(readonly) int baz;
#end
// Foo.m
#import "Foo.h"
// Private interface
#interface Foo ()
// Inside class implementation we can also change bar.
#property(assign) int bar;
#property(assign) int other;
#end
#implementation Foo
#synthesize bar, baz, other;
…
#end

How to obtain UITextFields from a singleton

I need just four parameters to drive the calculations in three view controllers. The parameters come from four UITextFields in the first view. I'm not using global variables but have developed a singleton class to enable the parameters to be available to each controller. I can reference the variables OK in the controllers but I don't know how to initialize them. I've obtained the variables from the first viewcontroller through a windows I developed with IB but can't seem to find a way to get these initialized in the singleton.
Help and guidance gratefully appreciated.
//
// GlobalParameters.h
// ProjectEstimator
//
// This is a SINGLETON class used to handle global parameters for use in the various view controllers.
//
//
//
// Created by Frank Williamson on 10/06/2010.
//
#import <Foundation/Foundation.h>
#interface GlobalParameters : NSObject {
// Place any "global" variables here
// float *processes;
// float *entities;
// float *transactions;
// float *users;
IBOutlet UITextField *noOfProcesses;
IBOutlet UITextField *noOfEntityClusters;
IBOutlet UITextField *noOfTransactions;
IBOutlet UITextField *noOfUserArea;
}
#property (retain, nonatomic) UITextField *noOfProcesses;
#property (retain, nonatomic) UITextField *noOfEntityClusters;
#property (retain, nonatomic) UITextField *noOfTransactions;
#property (retain, nonatomic) UITextField *noOfUserArea;
// message from which our instance is obtained
+ (GlobalParameters *)sharedInstance;
#end
//
// GlobalParameters.m
// ProjectEstimator Singleton for handling (global) parameters.
//
// Created by Frank Williamson on 10/06/2010.
//
#import "GlobalParameters.h"
#implementation GlobalParameters;
#synthesize noOfProcesses;
#synthesize noOfEntityClusters;
#synthesize noOfTransactions;
#synthesize noOfUserArea;
+ (GlobalParameters *)sharedInstance{
// the instance of this class is stored here
static GlobalParameters *noOfProcesses = nil;
static GlobalParameters *noOfEntityClusters = nil;
static GlobalParameters *noOfTransactions = nil;
static GlobalParameters *noOfUserArea = nil;
// check to see if an instance already exists
if (nil == noOfProcesses) {
noOfProcesses = [[[self class] alloc] init];
// **How to I initialize UITextFields from a ViewController in here??**
}
// return the instance of this class
return noOfProcesses;
if (nil == noOfEntityClusters) {
noOfEntityClusters = [[[self class] alloc] init];
// **How to I initialize UITextFields from a ViewController in here??**
}
// return the instance of this class
return noOfEntityClusters;
if (nil == noOfTransactions) {
noOfTransactions = [[[self class] alloc] init];
// **How to I initialize UITextFields from a ViewController in here??**
}
// return the instance of this class
return noOfTransactions;
if (nil == noOfUserArea) {
noOfUserArea = [[[self class] alloc] init];
// **How to I initialize UITextFields from a ViewController in here??**
}
// return the instance of this class
return noOfUserArea;
}
#end
There's a number of things here I would change. First, I wouldn't create a "Globals" class. Second, if I did, would never store UIView objects in class designed to be a "model". Third, if I absolutely needed to implement a singleton, I would follow the design pattern for Cocoa.
I need just four parameters to drive the calculations in three view controllers.
And at that point I recommend you throw out this class entirely and re-think your design problem. Is it simply that you need to store four NSString parameters (or NSNumbers or NSIntegers or floats or...)? If so, it's complete overkill to store the parameters inside a view class. Just create a simple class to store the parameters, whose header would look something like:
#interface MyParameters : NSObject
{
NSString* someString;
NSNumber* someNumber;
NSInteger someInteger;
float someFloat;
}
#property (nonatomic, retain) NSString* someString;
#property (nonatomic, retain) NSNumber* someNumber;
#property (nonatomic, assign) NSInteger someInteger;
#property (nonatomic, assign) float someFloat;
#end
I would instantiate an object of this class either in my application delegate or in my root view controller, and then I would pass it along to any other view controllers that needed access to it. Finally, I would use Key-Value Observing so every view controller that needs it will get automatic updates to any changes to the parameters.