I've been trying to save strings in Xcode such as email and password so i can open them in different view, So far every attempt for the past 2 weeks have failed.
does anyone have a working way, and if so can you post the code.
Thanks
*edit***
Almost done just having an error here
(MemberPage *)initWithString: (NSString) S {
self = [super init];
if ( self ) {
//DO STUFF;
UserNAME.text = S.text;
}
return self;
}
error is on the first line:
use of undeclared identifier with initWithString
Also get should be a ; before :
(MemberPage *)initWithString: (NSString *) s {
self = [super init];
if ( self ) {
//DO STUFF;
UserNAME = s;
}
return self;
}
Forgot the '*'?
One of the easiest way's I've done this in the past is just to pass them in when I create my View:
RecieverClass.m:
(RecieverClass*) initWithString: (NString) S {
self = [super init];
if ( self ) {
//DO STUFF;
myLocalString = S;
}
return self;
}
SenderClass (where you create your view)
RecieverClass *recieverClass= [[RecieverClass alloc] initWithString:sendString];
[[self navigationController] pushViewController:recieverClass animated:YES];
[recieverClass release];
You could pass them in as pointers or w/e really. Just depends what you're trying to do really.
I use a singleton class to share data between different views and for me it works. In the source viewController, I assign the value as a parameter to the "shared" class, and in the destination viewController I retrieve it.
Dunno if it's the "legal" way to do it, but it's simple and it works.
Check out this tutorial: http://www.bit-101.com/blog/?p=1969
At a certain point you arrive at this piece of code:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Custom initialization
Model *model = [Model sharedModel];
[model addObserver:self forKeyPath:#"text" options:NSKeyValueObservingOptionNew context:nil];
}
return self;
}
Adding the observer didn't immediately work for me, dunno why but I didn't look into this issue deeper.
I changed it into:
Model *model = [Model sharedModel];
model.parameter = #"btnMainToTarget";
Follow the instruction from beginning till end - it will work.
To any other people; don't hesitate to react if you didn't think my reply was accurate.
Greetings
Related
At first, sorry for my english. I trying to resolve problem with a few enter points (a few initializators like initWithFrame: and initWithCoder:). Not to repeat my setup code. At first i had a simple solution, just create method ("setup" for example) that called by initializators. But there is a little problem with subclasses. If my subclass have own initializator like initWithFrame:backgroundColor: and property "backgroundColor" then its own overriden "setup" will be called by super initializator but "backgroundColor" will still nil. So this "setup" will cant use this property. I think its common problem and its have nice common solution, that i cant find.Thanks.
Typically, I'll create static function called _commonInit(MyClass *self) and call that from each initializer. It is a function because it won't be inherited.
base class
-(instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self setup];
}
return self;
}
-(instancetype)initWithCoder:(NSCoder*)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self setup];
}
return self;
}
-(void)setup
{
//some setup code
}
child class
-(instancetype)initWithFrame:(CGRect)frame param:(id)param
{
self = [super initWithFrame:frame];
if(self)
{
self.param = param;
//setup will be run by parent
}
return self;
}
-(void)setup
{
[super setup];
//child setup code
//when this code will work self.param will still nil!
}
thats what i mean
I've been programming in Objective-C for years now, and I always bump into this problem: If you have an object with multiple initializers, but there is code in common to all of them, how do you extract it out?
The best I've been able to come up with is something like this:
#implementation Example
- (void)privateInitWithString:(NSString*)aString
{
self.str = aString;
}
- (id)init
{
self = [super initWithWindowNibName:#"MyNib"]
if(self) {
[self privateInitWithString:#""];
}
return self;
}
- (id)initWithString:(NSString*)aString
{
self = [super initWithWindowNibName:#"MyNib"]
if(self) {
[self privateInitWithString:aString];
}
return self;
}
#end
There is a lot of duplication in the individual initializers which a code smell. However I can't think of a way to get one initializer to "fall through" to another one because there is no guarantee that self has been set before calling [super init]
Is there a best practice for this that I'm missing?
You write one "designated initialiser". That initialiser handles all the different situations. In your case, initWithString seems a good candidate. And init just becomes
- (instancetype)init { return [self initWithString:#""]; }
You can read more about it here:
https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/Initialization/Initialization.html
I have a class named IGMapViewController
In that I have
static IGMapViewController *instance =nil;
+(IGMapViewController *)getInstance {
#synchronized(self) {
if (instance==nil) {
instance= [IGMapViewController new];
}
}
return instance;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// more code
instance = self;
}
return self;
}
If use the object in more then 1 class but only use initWithNibName in one class.
In a class named IGRouteController in the init method i use _mapViewController = [IGMapViewController getInstance]; this happens before the initWithNibName gets executed in another class.
In IGRouteController I have a method updateRouteList in that method I use:
[_mapViewController drawSuggestedRoute:suggestedRoute];
It all does run but I can't see the result.
If i use:
IGMapViewController *wtf = [IGMapViewController getInstance];
[wtf drawSuggestedRoute:suggestedRoute];
Then it does work great.
So is it possible to get a instance and init later with a nib?
I believe I see what you are trying to accomplish. You want to initialize a singleton instance of your class from a nib. Correct?
When you initialize your instance, you are using [IGMapViewController new] which is presumably not the intended behavior. How about this (untested...)?
+ (id)sharedController
{
static dispatch_once_t pred;
static IGMapViewController *cSharedInstance = nil;
dispatch_once(&pred, ^{
cSharedInstance = [[self alloc] initWithNibName:#"YourNibName" bundle:nil];
});
return cSharedInstance;
}
clankill3r,
You should avoid creating singleton UIViewControllers (see comments in this discussion UIViewController as a singleton). This has been also highlighted by #CarlVeazey.
IMHO, you should create a UIViewController each time you need it. In this case your view controller would be a reusable component. When you create a new instance of your controller, just inject (though a property or in the initializer the data you are interested in, suggestedRoute in this case).
A simple example could be the following:
// YourViewController.h
- (id)initWithSuggestedRoute:(id)theSuggestedRoute;
// YourViewController.m
- (id)initWithSuggestedRoute:(id)theSuggestedRoute
{
self = [super initWithNibName:#"YourViewController" bundle:nil];
if (self) {
// set the internal suggested route, e.g.
_suggestedRoute = theSuggestedRoute; // without ARC enabled _suggestedRoute = [theSuggestedRoute retain];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self drawSuggestedRoute:[self suggestedRoute]];
}
For further info about UIViewControllers, I really advice to read two interesting post by #Ole Begemann.
Passing Data Between View Controllers
initWithNibName:bundle: Breaks Encapsulation
Hope that helps.
Most of the time I am doing this:
self.someVC = [myVC alloc] initWithFrame:frame];
self.someVC.delegate = self;
Is there a way to set the delegate variable automatically?
-(void)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.delegate = [the object that is calling initWithFrame];
..
No, this isn't possible. You would have to inspect the call stack or something which I would not recommend. There are no standard facilities for this.
Even if it was possible, it would be a bad idea. You should use constructor or property injection as usual so the dependencies are clear and you don't confuse people that are reading your code.
Add a custom initializer that takes in the delegate object as a parameter.
Like this:
-(void)initWithFrame:(CGRect)frame delegate:(id)delegate
{
self = [super initWithFrame:frame];
if (self) {
self.delegate = delegate;
..
You could always provide a new initWithFrame method:
- (id)initWithFrame:(CGRect) aFrame delegate:(id)aDelegate {
self = [super initWithFrame:aFrame];
if (self) {
self.delegate = aDelegate;
}
return self;
}
I am new to Core Animation and having trouble implementing a CALayer object with the drawLayer method in a delegate.
I have narrowed the problem down to a very simple test. I have a main viewController named LBViewController that pushes a secondary viewController called Level2ViewController. In the level 2 controller, in viewWillAppear:, I create a CALayer object with it's delegate=self (i.e. the level 2 controller). Whether or not I actually implement the drawLayer:inContext: method I have the same problem -- when I return to the main viewController I get a zombie crash. In the profiler it appears that the object in trouble is the level 2 viewController object -- which is being dealloc'ed after it's popped.
I've tried using a subclassed CALayer object instead of the delegate and it works fine. If I comment out the delegate assignment it also runs fine. I would like to understand why delegation is causing this problem. Any advice is greatly appreciated.
Here's my code ---
Level2ViewController
#implementation Level2ViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CALayer *box1 = [[CALayer alloc] init];
box1.delegate = self; // problem disappears if I comment out this assignment
box1.backgroundColor = [UIColor redColor].CGColor;
box1.frame = CGRectMake(10,10,200,300);
[self.view.layer addSublayer:box1];
[box1 setNeedsDisplay];
}
// makes no difference whether or not this method is defined as long
// as box1.delegate == self
- (void)drawLayer:(CALayer *)theLayer inContext:(CGContextRef)theContext
{
CGContextSaveGState(theContext);
CGContextSetStrokeColorWithColor(theContext, [UIColor blackColor].CGColor);
CGContextSetLineWidth(theContext, 3);
CGContextAddRect(theContext, CGRectMake(5, 5, 40, 40));
CGContextStrokePath(theContext);
CGContextRestoreGState(theContext);
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
The method in LBViewController (the main controller) that pushes the level 2 view controller
- (IBAction)testAction:(id)sender {
Level2ViewController *controller = [[Level2ViewController alloc]
initWithNibName:#"Level2ViewController" bundle:nil];
controller.title = #"Level2";
// this push statement is where the profiler tells me the messaged zombie has been malloc'ed
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
You may want to set the layer's delegate to nil before the delegate object is released. So in your Leve2ViewController do this:
-(void)viewWillDisappear:(BOOL)animated
{
if (box1) {
box1.delegate = nil;
}
box1 = nil;
}
Obviously this requires, that box1 is turned into a field (so it is accessible in viewWillDisappear:)
Since you create box1in viewWillAppear: the code above uses viewWillDisappear:. Recently, when I ran into a similar problem, I had a separate delegate object in which I used init and dealloc.
Note: You call [super viewDidAppear:animated]; in viewWillAppear. Looks like a typo or copy/paste glitch :-)