Is this why I use pointers? - objective-c

I know this is very basic but I need clarification. I'm trying to develop an iPad app but having trouble. My explanation may be a little too much information needed but bear with me.
I have two ViewControllers. One is called NewGameViewController while the other is called GameViewController. In the NewGameViewController I display the GameViewController like so:
GameViewController *controller = [[GameViewController alloc] initWithNibName:#"GameViewController" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
So this creates an instance of GameViewController in memory. GameViewController has some ivars and methods defined in it. One of the ivars is an array that gets filed with seat objects when GameViewController loads (in the viewWillAppear method).
I also have an object called player. This is just a subclass of UIView. When GameViewController loads it adds up to six player objects to the subview. I need each player object to be able to access the same instance in memory of GameViewController that was loaded by NewGameViewController. Would I use a pointer in my player objects to access the same instance of GameViewController? I've found that if I load a new instance of GameViewController into memory and attempt to use it the array ivar tends to be empty and therefore unuseable. How would I be sure that my pointer to GameViewController is pointing to the correct instance of GameViewController?

When GameViewController loads it adds up to six player objects to the
subview.
So, here's what you can do. Define a property on Player called containingViewController or gameViewController.
#property (nonatomic, retain) GameViewController *containingViewController;
Don't forget to also #synthesize containingViewController; in your implementation file (Player.m) and [containingViewController release]; in your dealloc.
Then, when you initialize the players in the viewWillAppear method, set the property:
player1.containingViewController = self;
That should take care of all of your issues.

Related

setHidden with NSSlider doesn't work - Objective C

Hy guys, I'm new at ObjC and I'm still learning;
[sliderContrast setHidden:YES] (i also used slider.hidden = YES) doesn't make the slider invisible, instead it works fine with textfields. Do you know why?
I've also tried using property and synthesize but the result doesn't change
---Interface
#interface Controller : NSWindowController{
IBOutlet NSTextField *labelContrast;
IBOutlet NSTextField *valueContrast;
IBOutlet NSSlider *sliderContrast;
}
- (IBAction)changeContrast:(id)sender;
#end
---Implementation
#import "Controller.h"
#interface Controller ()
#end
#implementation Controller
- (void)windowDidLoad {
[super windowDidLoad];
[labelContrast setHidden:YES];
[valueContrast setHidden:YES];
[sliderContrast setHidden:YES];
}
- (IBAction)changeContrast:(id)sender {
}
#end
If you declare pointers for your objects but you don't allocate them yourself you can not set anything that is not there. Your setHidden: method calls end up in local void aka nowhere.
programmatically
If you go the coding way you would declare, allocate and initiate first. With
labelContrast = [NSTextField alloc] initWithFrame:NSMakeRect(x,y,w,h)];
before you call other methods of the object class (Or similar init methods).After that you can call methods on the object.
Almost all objects inherit an according -(instancetype)init or -(instancetype)initWith... method you can use. If there is no init method given, then there is another way to do it right and the moment to start reading again :).
With Interface Builder
By typing IBOutlet or IBAction in front of a declaration you just give a hint for Xcodes Interface Builder where to hook up and apply onto (associate) the placed object in (nib,xib,storyboard) with its object ID in the XML scheme to a reference in code.
So after you connected your code and the object in IB you can avoid allocation and init process for that particular object. Be aware that calling methods on objects that are not instanced yet is not working. Which is why you code in - (void)windowDidLoad, -(void)viewDidLoad or -(void)awakeFromNib because those are the methods that get called after "IB" has done its job for you.

Dealloc on UIViewController

Everything is in the title.
I would like to know when the dealloc method is called on UIViewController using ARC ?
In my app I have a navigation controller with multiple view controllers. When I dismiss my main navigation controller, the dealloc method is not getting call in any of my controllers ..
Thanks,
Dealloc is called on a UIViewController when the memory for that viewController is going to be deallocated from memory. If the dealloc method is not being called on your viewControllers when you expect it to be, you probably have a memory leak. It sounds like your view controllers may be retaining strong references to each other.
#property (nonatomic) UIViewController *otherController;
Change one side of the relationship to
#property (nonatomic, weak) UIViewController *otherController;

IBOutlet is nil after initWithCoder is called

Simple problem, I have defined a UIImageView, called bigImageView in a UIViewController using the storyboard,
It's declared in the h file of that UIViewController as follows:
#property (retain, nonatomic) IBOutlet UIImageView *bigImageView;
on my appDelegate I init the UIViewController as follows:
imageViewController = [storyboard instantiateViewControllerWithIdentifier:#"chosenImageController"];
this calls initWithCoder on my UIViewController m file:
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// Custom initialization
}
return self;
}
This function is only called once so there's no double init.
However, later, when I check my bigImageView pointer, it's still nil.
Isn't the init supposed to allocate memory to it?
I think that's why when I try to set this UIImageview to hold a UIImage it doesn't display the image
Thanks
It's all working how it's meant to. First every object in the nib/storyboard gets alloc/init called on them, then all the connections are made, and then viewDidLoad is called.
You need to wait for - (void)viewDidLoad to be called on your controller, and then bigImageView should be set. If it's not set then you did something wrong in the storyboard.
init methods are not responsible for allocating any memory. All memory is allocated by the alloc method which is always called before init. Alloc will fill all your instance variables with nil/NULL/0 values, and then init gives the chance to assign initial values to each one (based on the contents of the NSCoder object usually, but it's up to you to decide what should be done).
For IB outlets however, those are setup by the nib loading process after init.
EDIT:
// ViewControllerA.m:
imageViewController = [storyboard instantiateViewControllerWithIdentifier:#"chosenImageController"];
imageViewController.image = imageToShow;
// ViewControllerB.h
#property (retain) NSImage *image;
#property (retain, nonatomic) IBOutlet UIImageView *bigImageView;
// ViewControllerB.m
- (void)viewDidLoad
{
self.bigImageView.image = self.image;
[super viewDidLoad];
}
You don't need to define initWithCoder, since you have no custom logic in there. I would delete that boilerplate code.
Here is what I would check:
In the storyboard, ensure that the class of the view controller is set properly.
Ensure that the outlet is hooked up properly in the storyboard by looking for a circle near your #property. It should be a filled in circle, not an outline of a circle.
Make sure you are reading the value only after viewDidLoad is called. Apple's only guarantee is that the outlet is set after this method call.
Update: It sounds like you want to access the image view before the view is loaded. There is no way to do this. One hack is to call viewController.view which will force the view to load, but there are many reasons why you should not do this.
A better approach would be to implement properties on your view controller which work for both when the view is not loaded and when the view is loaded. You can see an example of an elegant solution in this question. Notice how if the view is loaded, the photographerLabel will get set via the didSet method. On the other hand, if the view is not loaded, it will get set via the viewDidLoad method. For an Objective-C version of that code or for more details, see the linked video in that question.

iOS: how to get access viewController's methods

I have a trouble.
There is viewConntroller and an object inside this viewController. This object tries to get information via NSURLConnection later it has to notify viewController to run method. If i try to create object of viewController inside I catch problem: new viewController makes the same thing that first one do, so new viewController makes NSURLConnection, creates third viewController and so on.
You can pass reference to this object. But first create new property with assign attribute.
//property in your class
#property(nonatomic, assign) id myViewController;
//set reference to your UIViewController
[myClassInstance setMyViewController: self]; //self is MyViewController instance
//call UIViewController's method from your class
MyViewController *controller = (MyViewController *)self.myViewController;
[controller myMethodInUIViewController];
How about passing on a reference of the viewController to the object you´re making inside that viewController?
So something along the lines of:
Object *obj = [[Object alloc]init];
obj.viewController = self;
Obviously, you'd have to create an attribute to hold the viewController on the object class.
Then, when you need to call methods on the viewController, you could use:
[self.viewController performSelector:#selector(methodName:)];

Error when ViewController is implementing UITextFieldDelegate

When implementing the UITextFieldDelegate in my ViewController class, the following error is thrown when entering the first character in the text field:
-[MyViewController respondsToSelector:]: message sent to deallocated instance...
So, I tried creating a separate class (inheriting only NSObject) and implementing UITextFieldDelegate. Guess what, it worked perfectly. However, that introduces some other problems as I have to do a lot of ugly cross-class-communication that I'd like to avoid. Here's the relevant parts of my app delegate code:
#interface RMSAppDelegate : NSObject <UIApplicationDelegate,
UITabBarControllerDelegate>
#property (nonatomic, retain) UIViewController* myViewController;
#end
#implementation MyAppDelegate
#synthesize myViewController;
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
myViewController = [[MyViewController alloc]
initWithNibName:#"MyView" bundle:nil];
[self.window setRootViewController:myViewController];
[self.window makeKeyAndVisible];
return YES;
}
#end
.. and here's what is being displayed:
#interface MyViewController : UIViewController <UITextFieldDelegate>
#property (nonatomic, retain) IBOutlet UITextField* pinTextField;
- (void)viewDidLoad;
#end
#implementation MyViewController
#synthesize pinTextField;
- (void)viewDidLoad {
// DOES NOT WORK (WHY?)
//[pinTextField setDelegate:self];
// WORKS, BUT I'D LIKE TO AVOID
[pinTextField setDelegate:[[[MyTextFieldDelegate alloc] init] autorelease];
[pinTextField becomeFirstResponder];
[super viewDidLoad];
}
#end
And please, if you see any code (even off topic) that I could be doing better, leave a comment.
Since you asked for off-topic code comments: You forget to call [super viewDidLoad]. You also don't need to redeclare the prototype in order to override it. And the #synthesize textFieldDelegate is not valid, as you have no property in the class named textFieldDelegate. And your dealloc method is releasing an ivar named tfd which doesn't seem to actually exist in the class.
Your real problem is that you are not properly retaining the view controller at whatever point you allocate it. It may be that the view controller is being instantiated in a nib and associated with an ivar rather than a property declared retain, or is not being associated with anything. Or it could be that you are allocating it in code, adding its view as a subview of something, and then releasing it without ever retaining the view controller itself. Or it could just be that you are just releasing it when you shouldn't.
Your other class works specifically because you are leaking the object, so it never gets deallocated. The better solution, were you to go with this method, would be to store the object in an ivar when you allocate it and then release it (and set the ivar to nil) in both dealloc and viewDidUnload.
Okay, I finally solved this on my own. I have not changed the code. My NIB (.xib) was the culprit!
I thought that nested UIViewControllers was OK, and I still think they are in some cases (and maybe using another programmatic method). Anyway, I was initializing my class MyViewController with a NIB that in the Objects panel had a UIViewController as the first object.
I solved this by having the UIView as the first object in the Objects panel, and setting the File's Owner to be the UIViewController instead.
Correct code, incorrect NIB. Thank you for your help.