Xcode override all methods - xcode

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.

Related

Functionality put in a convenience init - unusable in sub-classes?

Isn't functionality put in a convenience init - unusable in sub-classes?
If so, why are the Cocoa's interfaces for Swift defining so many initializers as convenience.
For example - I have a sub-class of NSWindowController and I would like to create a designated init, which will not get any parameters and should directly know what NIB file to instantiate with.
But I don't have any access to super.init's/methods to get the already implemented behaviour and build up on it. Here is the definition of the inits of NSWindowController:
class NSWindowController : NSResponder, NSCoding, NSSeguePerforming, NSObjectProtocol {
init(window: NSWindow?)
init?(coder: NSCoder)
convenience init(windowNibName: String)
convenience init(windowNibName: String, owner: AnyObject)
convenience init(windowNibPath: String, owner: AnyObject)
// ...
}
Instead I am forced to reimplement the NIB loading, thus duplicating and potentially getting it wrong.
Edit:
Here is a small passage from a blogpost by Mike Ash, mentioning NSWindowController subclasses and the reasoning behind what I do in my case is exactly the same:
NSWindowController provides a initWithWindowNibName: method. However, your subclass is built to work with only a single nib, so it's pointless to make clients specify that nib name. Instead, we'll provide a plain init method that does the right thing internally. Simply override it to call super and provide the nib name:
- (id)init
{
return [super initWithWindowNibName: #"MAImportantThingWindow"];
}
So it's possible in ObjectiveC, but how can this be done in Swift?
Convenience initializers are inherited in subclasses. They can be overriden, too.
In order to call init(windowNibName: String), you need to declare a convenience initializer to call it from, and you should call it on self, rather than super:
class MAImportantThingWindowController : NSWindowController {
override convenience init() {
self.init(windowNibName: "MAImportantThingWindow")
}
}

NSWindowController in Swift. Subclassing and initializing with Nib

In a test Swift project, I am subclassing NSWindowController. My NSWindowController subclass is designed to work with a particular Nib file. It is desirable, then, that when my window controller is initialized, the nib file is automatically loaded by the window controller instance. In Objective-C, this was achieved by doing:
#implementation MyWindowController
- (id)init {
self = [super initWithWindowNibName:"MyWindowNib"]
if (self) {
// whatever
}
return self
}
#end
Now, in Swift this is not possible: init() cannot call super.init(windowNibName:), because the later is declared not as a designated initializer, but as a convenience one by NSWindowController.
How can this be done in Swift? I don't see a strightforward way of doing it.
P.S.: I have seen other questions regarding this topic, but, as long as I've been able to understand, the solutions all point to initialize the Window Controller by calling init(windowNibName:). Please note that this is not the desired beheaviour. The Window Controller should be initialized with init(), and it should be the Window Controller itself who "picks up" its Nib file and loads it.
If you use the init() just to call super.init(windowNibName:), you could instead just override the windowNibName variable.
override var windowNibName: String {
get {
return "MyWindowNib"
}
}
Then there should be no need to mess with the initializers.
You can create your own convenience initializer instead:
override convenience init() {
self.init(windowNibName: "MyWindowNib")
}
You should instead opt in to replacing all designated initializers in your subclass, simply delegating to super where appropriate. Confer https://stackoverflow.com/a/24220904/1460929

How to send a message to the Master Class of a class?

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.

How to bind a control to a singleton in Cocoa?

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

Methods in super that will be subclassed anyway (Cocoa)

Sorry if this is a repost but I couldn't quite search for it because I can't explain it in a few words. I have a super class with lots of methods but they will always (not all of them) be subclassed. From the super I need to run those methods. I could either leave the methods in super empty or I could just not type them in super but call them anyway like so [self myMethod] and it will call my subclassed method even if it doesn't exist in super. This works but Xcode gives me an error though. 'superclass' may not respond to '-subclassmethod'
What should I do so I won't get the warnings?
I prefer to define the unimplemented methods in the superclass like this:
#interface GLObject : NSObject {}
- (id)someSubclassProvidedMethod;
#end
#implementation GLObject
- (id)someSubclassProvidedMethod {
[self doesNotRecognizeSelector: _cmd];
}
#end
It's almost entirely redundant, because the Objective-C runtime would eventually call -doesNotRecognizeSelector: if I didn't define the method at all. But because I do define it, it's in the class's interface which both keeps the compiler happy and provides me with some documentation.
Rather than the superclass, you could declare the methods in a protocol, what is called a "interface" in other languages.
#protocol MyProtocol
-(id)myMethodWith:(id)arg;
#end
Change the type declaration of the variables to declare that the object conforms to the protocol.
-(id)doStuffWith:(SuperClass <MyProtocol> *)aThing and:(id)another {
return [aThing myMethodWith:another]
}
Note that you won't be able to pass an instance of your SuperClass to doStuffWith:and:, since it won't implement MyProtocol, but it sounds like that's what you want.
My solution was a little weird, but here it is:
#protocol JSDog <NSObject>
- (void)yipe;
#end
#interface JSDog : NSObject
#end
#implementation JSDog
+ (void)initialize {
if ([self isSubclassOfClass:[JSDog class]] && ![self conformsToProtocol:#protocol(JSDog)]) {
NSAssert(false, #"Subclasses of JSDog must conform to <JSDog>.");
}
}
#end
Having a protocol with the same name as a class is precedented in NSObject. Because methods in a formal protocol a by default #required, you will be protected on both ends: in compile-time, if your JSDog subclass purports to conform to <JSDog>, but doesn't implement -yipe, you will receive an error; at runtime, if your subclass does not claim to conform with <JSDog>, you will receive a warning when the subclass is instantiated.
I lately like using NSAssert for this task:
- (BOOL)proceedForVersion:(int)versionInteger
{
NSAssert(false, #"This method needs to be overridden in a subclass of iMBApertureAbstractParser");
return NO;
}

Resources