When I override the method viewDidLoad, should I call it first and then write my code or is it the other way around?
Call super's implementation. The approach is FIFO:
- (void)viewDidLoad
{
[super viewDidLoad];
// code...
}
- (void)viewDidUnload
{
// code...
[super viewDidUnload];
}
To gain a little more insight, look at Apple's documentation on View Controller: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/BasicViewControllers/BasicViewControllers.html
Also see this similar (dup?) question and answer: `[super viewDidLoad]` convention
No, you don't need to call [super viewDidLoad].
Let's be real here: Apple is not going to break thousands of apps, including those based on their published sample code, by deciding an event they're not currently handling suddenly needs to do something that developers may or may not want to stop and it's critical that if you don't need different behavior you not stop the event.
If Apple needs to do something like this, they'd add a specific new event. For example, and this is a ridiculous example, viewConvertTo3D.
Call the super if it matches your pattern. In fact, you probably should make the effort to learn Apple's standard nesting pattern. Don't call it if it doesn't, or if you care more about keeping your sources small. Extra code is not future proofing.
from: here
Related
I was doing some iOS 5 tutorials and in several tutorials, it says things like "Add at end of viewWillAppear" or "Modify viewWillDisappear" in MasterViewController.m but in my project, MasterViewController.m does not have any of those methods.
Since it doesn't say "create those methods", I'm guessing they are automatically created by something but I do not know what I need to do to make them appear in MasterViewController.m.
Please somebody help me?
These methods are typically inherited from a parent class (e.g., UIViewController). What you probably should do is add something like
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Your new stuff here
}
The method prototype was taken from Apple's documentation of UIViewController; depending on the class you're subclassing (the thing after the colons in the .h file, in the #interface line) you might need different method prototypes.
I'm still very new to Objective C, and I was wondering something regarding viewDidDisappear.
I have an app that plays a sound (using AVAudioPlayer), and I want to stop the sound when the view is switched.
If I do this in my view controller implementation:
- (void)viewDidDisappear:(BOOL)animated {
[self.audioPlayer stop];
}
it works fine. But the small programmer in my brain is saying that I'm not using this correctly.
I'm pretty sure you are supposed to CALL viewDidDisappear with a boolean argument, rather than just specify (BOOL)animated; besides, it would be nice to have some animation in my view switching... then again, that might be a whole different discussion!
So, what am I doing wrong, and how would I correctly use this? Do I have to link the call a button action? Where is the correct play to actually declare the function itself?
Thanks.
I implement viewDidDisappear:(BOOL)animated EXTENSIVELY, along with viewWillAppear, viewWillDisappear and viewWillDisappear The main reason to implement this method is to make your view controller to do something at the event, such as viewDidDisappear You don't call this method, but your app will call your view controller to do what's implemented there. Since this is inherited method, as long as you make sure all the inherited implementation from the super class can be done, it's great to implement viewDidDisappear. So, I suggest you to change your code to be like this:
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:(BOOL)animated]; // Call the super class implementation.
// Usually calling super class implementation is done before self class implementation, but it's up to your application.
[self.audioPlayer stop];
}
- (void)viewDidDisappear:(BOOL)animated is a method declaration, not a call of any sort. The method itself is called by UIKit as view controllers are manipulated; you don't need to call it yourself unless you're writing your own code that makes view controllers appear and disappear by directly manipulating the views they control (e.g. if you were rewriting UINavigationController for some reason).
You are doing something wrong, though: you must call [super viewDidDisappear:animated] somewhere in your implementation, or things may break.
The "small programmer" voice in your mind is probably more used to procedural coding, where you call the OS and tell it what to do. Cocoa Touch instead uses an event driven paradigm, where your program has routines (methods) that the OS(framework)calls when it is good and ready. viewDidDisappear is one of those routines. Just sit tight, and wait for the OS to call it (assuming you've set everything up properly.)
viewDidDisappear: is an optional method that your view can utilize to execute custom code when the view does indeed disappear. You aren't required to have this in your view, and your code should (almost?) never need to call it.
In viewDidLoad do you put [super viewDidLoad] before or after your code? Is it the same for all other methods?
Before. You want the super initialization to happen before yours, so that your code could rely on the super state.
As for the other methods - it depends whether you want your code to touch the parameters before calling the super method or it needs to process the result of it.
[This is my first post here (but I've browsed answers many times; thanks to all for a very useful site). If I'm committing any great sins with this post, please forgive me and point me in the right direction.]
I am trying to debug some complicated startup code in my iPhone application; I really need to draw some images to make debugging more insightful, and to radically reduce debug tedium.
The state I need to draw does not really exist as a model object; it is somewhat transient during initialization. I especially want to be able to draw one bit of state at a time, rather than all of it in one big image (to help me see which components are right/wrong). In my case, there is lots of potentially overlapping stuff and a single image cannot easily, clearly display what's going on.
Creating a static view which draws to the screen using the normal drawing architecture might be possible, if I add a special debug mode, and additional controls to navigate / highlight / draw components, but it will require a lot of unnatural scaffolding, and is not, IMO, the right way to debug my problem.
So, what I hope to do is:
get or create an appropriate CGContextRef
draw in it
flush it to screen immediately
wait for some input from the user, that doesn't involve UIEvents
repeat 1-4 many times
Item 4 seems to be almost impossible (is there a way to get something like simple C or C++ console I/O working in the iPhone, or the iPhone simulator?), so I've given up on it for now; I'll settle for just using the Xcode debugger to stop between drawing operations.
But more of interest is how to get a CGContextRef outside of a UIView draw method, in which to draw the debug output. Caching a previously valid context, even if it were possible in my situation (not possible, since I'm debugging at app startup), appears not to work. It seems as if contexts may be created anew for each drawing operation, which strikes me as incurring a lot of overhead; I would have assumed a UIWindow, and maybe a UIView, saved and could provide a reference to an appropriate drawing context. Seems I must be wrong (but if not, how do I get a context from a view or window? I've found no methods for this).
So, if I must create a drawing context, how do I do it? I guess I really don't quite understand what exactly is bound together by a context: to what extent does it know about, and bind to, some specific display output device? How do I control what portion of the screen a context maps to? There seem to be very few ways to create a context, and they don't seem to provide such control. UIGraphicsBeginImageContext seems to be the only routine that might help me, and I don't see how creating and drawing into one, only to produce a CGImage as a result will be useful; how would I get the resulting image onto the screen?
I won't be surprised to find I'm confused about some basic stuff related to CG contexts. Hopefully, this question isn't so basic and obvious that I'll be annoying everyone who reads it, but if I've completely missed the right documentation, I'd be very appreciative of a few pointers.
Thanks for your mental bandwidth, and any help. -jar
You are correct in that you cannot draw directly to the screen. That being said, a UIView can be instructed to refresh at will if you call [view setNeedsDisplay]. If you override - (void)drawRect:(CGRect)rect, this will be called upon refresh. My suggestion for your problem is to subclass UIView, expose your debug state on this class, and when you update the state, force a refresh. If you are updating state at a high frequency, you should use CADisplayLink to tie the view refresh to the display refresh. If you call [view setNeedsDisplay] multiple times before the view redrawn it will not matter.
For example:
#import "QuartzTestView.h"
#import <QuartzCore/QuartzCore.h>
#interface QuartzTestView()
- (void)refreshView:(CADisplayLink*)displayLink;
#end
#implementation QuartzTestView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(drawView:)];
[displayLink setFrameInterval:1];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
return self;
}
- (void)refreshView:(CADisplayLink*)displayLink {
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
// do updates
}
#end
NOTE: You must add the QuartzCore.framework to run this
In Apple's scrollView example they don't call that. I always thought that's a must. Why should I call that anyways?
If you are overriding the method you should still call the method in the super. Even if the super class is not doing anything with it today, Apple might one day change the implementation and your code will mysteriously stop working. If you really don't need to do anything in that method, leave it out of your code entirely, and the super's method will run as usual, without any intervention on your part.
No, you don't need to call [super viewDidLoad]. Edit: But read below, because I think you definitely should.
Let's be real here: Apple is not going to break thousands of apps, including those based on their published sample code, by deciding an event they're not currently handling suddenly needs to do something that developers may or may not want to stop and it's critical that if you don't need different behavior you not stop the event.
Edit: Having watched how Apple handles compatibility for an extra year, I now recommend learning and using the correct pattern. While I doubt your application binary will ever suddenly stop working, it's clear that the iPhone detects which SDK your binary was built against and modifies some OS behaviour based on this.
Apple might one day require a particular pattern be followed on some future SDK. This would not affect you until you rebuild with the latest Xcode + SDK, but then you'd get these breaks without any source code changes. Learn and follow the pattern to be safe.
As Markus says, UIViewController doesn't do anything in its viewDidLoad method, so you don't have to call it. However, it's a good habit to get into, in case you change your inheritance structure and suddenly the class that used to inherit from UIViewController now inherits from something that does do something in the viewDidLoad method.
Lets say you have 2 class, a Parent and a Child. Child inherits from Parent. They have a method called greet which returns a string.
Here is what the parent method looks like:
Code:
-(NSString *)greet {
return #"Hello";
}
We want the child to learn from his parents. So we use super to say greet how Mommy would greet, but with our own little additions too.
Code:
// Inherits from Parent
-(NSString *)greet {
NSString *parentGreeting = [super greet];
return [parentGreeting stringByAppendingString:#", Mommy"]
}
So now Parent greets "Hello", and the Child greets "Hello, Mommy". Later on, if we change the parent's greet to return just "Hi", then both classes will be affected and you will have "Hi" and "Hi, Mommy".
super is used to call a method as defined by a superclass. It is used to access methods that have been overriden by subclasses so that the class can wrap its own code around a method that it's parent class implements. It's very handy if you are doing any sort of inheritance at all.
Apple's documentation for viewDidLoad does NOT state that you should call [super viewDidLoad], so I would go with what Apple's says. Note, however, that for other similar methods like viewDidAppear, you must call [super viewDidAppear].
You don't have to call the [super viewDidLoad]
As far as I know, the viewDidLoad in the superclass (UIViewController) is only an empty function that gets called when the ViewController gets initialized with a nib-file.
So if you need to do any initializing, you should override this function and put your code there.
Just noticed that the static analyzer of Xcode 6 issues a warning if you do not call super in these functions. So it seems Apple now definitely wants us to call it.
Although in xCode 7 Beta/Swift 2 super.viewDidLoad won't compile. The error says it's only available in osx 10.10 and the auto-fix does this
if #available(OSX 10.10, *){
super.viewDidLoad()}
else
{
// Fallback on earlier versions
}
// My code
}