This sets the delegate correctly and everything functions as normal:
UINavigationController *nc = [segue destinationViewController];
RecipeAddViewController *rc = [nc.viewControllers objectAtIndex:0];
rc.delegate = self;
When I do:
[[[[[segue destinationViewController] viewControllers]objectAtIndex:0]delegate]self];
The delegate method is never called. Why is this?
The '.' Syntax would call getter and setter based on the usage. However in message syntax we need to call the explicit setter like bellow.
[[[[segue destinationViewController] viewControllers]objectAtIndex:0] setDelegate:self]
Related
Quick Question:
I am creating an object from the MainWindowController:
about = [[About alloc]init];
In the Class About I do my Init:
-(id)init{
if(!_viewAbout){
[NSBundle loadNibNamed:#"About" owner:self];
[NSApp beginSheet:self.viewAbout modalForWindow:*?????* modalDelegate:self didEndSelector:NULL contextInfo:NULL];
}
return self;
}
My problem is that the Window is created in the MainWindowController. My question is how to call/send a message to the creator of the class if the class itself doesn't know the master class?
If I understand you correctly, most classes have self.superclass and just super, like
[super someMethod....
or
[self.superclass blegh....
Or are you asking for the class that creates another class ? If that is the case, you need to declare the creator class inside the other one, some (id) variable would do the trick.
But the most popular design pattern on the mac is the delegate pattern, and once you start using that you will love it. Declaring a delegate is usually the way Cocoa and UIKit do things, but other programming languages might not. Obj-C doesn't have any magic variables like python f.ex. has. Either you have a delegate or you have a declared variable which you would set right after the init/alloc stuff.
Also your (init) call doesn't look right. Usually it looks like :
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Here you could declare your setting.
}
return self;
}
But my opinion is that if you are declaring a singular pattern, you would call a specific method in your class, like you do with so many classes on the iOS/Cocoa, like :
[someclass DefaultClass]
This would be your init class where you would do init, unless the class had been declared before and then you would just return the object.
I want override all methods of a subclass automatically on xcode, for example I have a class extended of UiViewControler, how I override all methods of UiViewController on xcode to be more or less well:
- (id) init
{
return [super init];
}
My intention with this is to log all methods to see when they are called, then my methods will be more or less well
- (id) init
{
[self log];
return [super init];
}
where log is as follow method:
-(void) log
{
NSLog(#"%#",[(NSString *) (NSArray *) [NSThread callStackSymbols][1] componentsSeparatedByString:#"-["][1]);
}
thanks a lot!
In this case you don't have to do anything. If you don't provide an implementation, then the superclass's implementation will be used.
Edited after the question was edited
If you put the log statement in the superclass's implementation then it doesn't matter what you do with your own initialiser.
Why?
One of the many conventions in Cocoa is that each class has a designated initialiser. All the other designated initialisers then call this initialiser. And when you subclass the class, then you create a new designated initialiser for the new class, and as part of the initialisation - this calls the superclass's designated initialiser.
Which is why you see NSObject subclass initialisers calling [super init], because NSObject's designated initialiser is init.
So, just call your logging method in the designated initialiser of your class, and as long as you follow the above convention, this initialiser will always be called by a subclass, and so your logging method will always be called.
I have these methods in a class at the moment which seem to work fine. I would like to create a subclass which inherits these methods. The problem I have is that in the third method (shiftViewUpForKeyboard) I want the if statement to be a different UITextField (mirror being the current example).
I've read that to override a method in the subclass, you have to basically copy it exactly with the new coding, but if I want to just change that small section what is the best way to do it?
Thank you in advance.
- (void) viewWillAppear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(shiftViewUpForKeyboard:)
name: UIKeyboardWillShowNotification
object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(shiftViewDownAfterKeyboard)
name: UIKeyboardWillHideNotification
object: nil];
}
- (void) viewDidDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver: self
name: UIKeyboardWillShowNotification
object: nil];
[[NSNotificationCenter defaultCenter] removeObserver: self
name: UIKeyboardWillHideNotification
object: nil];
}
- (void) shiftViewUpForKeyboard: (NSNotification*) theNotification;
{
if(mirror.isEditing == YES)
{
CGRect keyboardFrame;
NSDictionary* userInfo = theNotification.userInfo;
keyboardSlideDuration = [[userInfo objectForKey: UIKeyboardAnimationDurationUserInfoKey] floatValue];
keyboardFrame = [[userInfo objectForKey: UIKeyboardFrameBeginUserInfoKey] CGRectValue];
UIInterfaceOrientation theStatusBarOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if UIInterfaceOrientationIsLandscape(theStatusBarOrientation)
keyboardShiftAmount = keyboardFrame.size.width;
else
keyboardShiftAmount = keyboardFrame.size.height;
[UIView beginAnimations: #"ShiftUp" context: nil];
[UIView setAnimationDuration: keyboardSlideDuration];
self.view.center = CGPointMake( self.view.center.x, self.view.center.y - keyboardShiftAmount);
[UIView commitAnimations];
viewShiftedForKeyboard = TRUE;
}
}
In any case if you don't want to copy the full method in the subclass, and adding your little customization, the only other possible approach I see is to change the original class. To do it I can suggest two possibilities:
1)
You could create in the original class a method called:
-(UITextField *)keyboardShiftTextField
and then in this class replace the mirror.isEditing code with:
[[self keyboardShiftTextField] isEditing]
In such case the only difference between the two classes will be in the implementation of the new method, that for the original class will be:-(UITextField *)keyboardShiftTextField {
return mirror;
}
while in the subclass this return the right text field.
2)
A second approach is more elegant as it requires the definition of the delegate pattern. This requires some overhead in term of code but we'll provide you more flexibility. Besides if the only reason to make the subclass is just to override this third method, then using the delegate pattern you can avoid creating the subclass at all, as the "custom" work will be done by the delegate. If the number of methods to override is more than one, you can still use this mechanism by moving into the protocol section all the parts that need customization. This is a quite common technique for Obj-C and Cocoa, which limits the need for some classes in many cases. Typically you use a subclass when you want to provide a different functionality, but in your case you're not providing a different functionality, but just a customization for the same functionality (the view shift up).
The usual approach would be the http://en.wikipedia.org/wiki/Template_method_pattern: pull out just the bit of the method that varies between classes, make that a separate method, and override that in subclasses.
[EDITED to add ...] An alternative approach -- I can't tell whether it would work well here without seeing more of your code -- would be to make the thing that varies a parameter that's passed into the method (or select it on the basis of a parameter passed into the method, or something else of the kind). (You'd typically then use other mechanisms rather than inheritance+polymorphism to get the effect you want, of multiple things with similar behaviour: they'd be instances of the same class but fed with different data.)
.m coding:
-(void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"MathMusic2" ofType:#"wav"];
self.theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL]
autorelease]; //error: expected ';' before 'autorelease' and // error: expected statement before ']' token
theAudio.delegate = self;
[theAudio play];
theAudio.numberOfLoops = -1;
}
related warnings:
warning: property 'theAudio' requires
method '-theAudio' to be defined - use
#synthesize, #dynamic or provide a
method implementation
warning: property 'theAudio' requires
the method 'setTheAudio:' to be
defined - use #synthesize, #dynamic or
provide a method implementation
tell me if you need .h coding. But there are no errors there.
The two errors are because you are missing an opening [ in the previous line:
self.theAudio = [[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL] autorelease];
The warnings are because you forgot #synthesize theAudio; in your #implementation (or forgot to write custom getter and setter methods). At runtime, you'll get an unknown selector exception if you don't fix that.
It was me in the previous question, my code was erroneous, this should correct it:
self.theAudio = [[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL] autorelease];
To this error:
warning: property 'theAudio' requires
method '-theAudio' to be defined - use
#synthesize, #dynamic or provide a
method implementation
Do you know what a property is? If not, look at this short tutorial. I actually provided the code in your previous question, but you have to know where to put it.
I have a singleton in my FTP app designed to store all of the types of servers that the app can handle, such as FTP or Amazon S3. These types are plugins which are located in the app bundle. Their path is located by applicationWillFinishLoading: and sent to the addServerType: method inside the singleton to be loaded and stored in an NSMutableDictionary.
My question is this:
How do I bind an NSDictionaryController to the dictionary inside the singleton instance? Can it be done in IB, or do I have to do it in code? I need to be able to display the dictionary's keys in an NSPopupButton so the user can select a server type.
Thanks in advance!
SphereCat1
I found / made up the answer to this: I simply override the init method so when it's called from the XIB file, it still returns the singleton. I then provide a method named realInit to do an actual initialization the first time init is called.
Code:
-(id)init
{
#synchronized(self)
{
if (_sharedInstance == nil)
{
_sharedInstance = [[VayprServerTypes alloc] realInit];
}
}
[self release];
return _sharedInstance;
}
-(id)realInit
{
if (self = [super init])
{
serverTypesArray = [[NSMutableArray alloc] init];
}
return self;
}
EDIT: Of course you'll need to define _sharedInstance as a static variable at the top of your class implementation:
static ClassTypeGoesHere *_sharedInstance;
ALSO EDIT: Since you now know for sure that your init method will be called at least once, you can go ahead and replace your normal singleton sharedInstance method with this:
+(ClassTypeGoesHere *)sharedInstance
{
return _sharedInstance;
}
If anyone sees any obvious problems with this design, please let me know!
SphereCat1