Difference between method swizzling and category in Objective c - ios

I was just understanding the method swizzling done in obj c Method Swizzling and dangers of using method swizzling and couldn't help but draw a comparison between doing method swizzling and overwriting method implementation using categories.
They both help override the functionality of the predefined framework methods.
So is there any difference between the two or they can be used interchangeably?

The main difference is that Objective C prevents you from invoking the original implementation from a category override. This is because Objective-C's super invocations start from the super-class, while categories override methods on the same class level.
Method swizzling, on the other hand, lets you keep a reference to the original implementation as well, so that you could call it from inside your implementation. For example, in the article at your first link the author writes this:
- (void) logged_viewDidAppear:(BOOL)animated {
[self logged_viewDidAppear:animated];
NSLog(#"logged view did appear for %#", [self class]);
}
The second line makes a call to logged_viewDidAppear: method, which looks like an unconditional call to itself that should cause infinite recursion. However, this is not what happens: after swizzling, this call gets transformed into a call to the original viewDidAppear: because of the way method swizzling works.
In contrast, overriding a method from a category does not give you access to the logic of the method that you are overriding. It lets you replace the logic, but it does not let you extend it.

extension UIViewController{
public func myViewDidLoad(){
self.viewDidLoad()
//but you need to call this method everywhere replacing
}
//you cant do this
public func viewDidLoad(){
self.viewDidLoad()
//my code
}
}
Categories or extension let you do these:
Add computed properties and computed type properties
Define instance methods and type methods
Provide new initializers
Define subscripts
Define and use new nested types
Make an existing type conform to a protocol
(from Apple)
They don't let you extend original method of the same class that you are extending and if you try like the above code method signature conflict pops up.
You might want to check this website to get the concept diagrammatically. I really loved it.
http://matteogobbi.github.io/blog/2014/12/15/extending-methods-in-a-category-by-method-swizzling/
Make sure to check this awesome article for good implementation detail:
http://nshipster.com/method-swizzling/

Related

Replace (swizzle) an entire class (with all instance and static methods) in Objective-C

I'm new to method swizzling and now I'd like to do a little more with that on iOS:
Is there an easy/elegant way in Objective-C to redirect all calls of an existing class (ClassA) to another class (ClassB, provided it has the exact same methods). I know it's possible to do so with a single method (method swizzling), but what about an entire class?
getting the list of all the class's methods and swizzling them one by one?
swizzling only the init method of the class?
any other way?
The class I want to replace has a lot of static methods and I don't want to touch the original code.

Why do we need to override methods — Objective-C?

I'm new to Objective-C and I did a big step from web developing (php) to ios developing.
Why should I override and implement methods from the superclass? Don't these methods already exist in their superclass?
For example, I have a table view controller. Why isn't a property like: numbers of rows, Instead of implementing a method? And why don't we implement all the methods that exist in the superclass?
I guess I have a lack of knowledge in all of the inheritance system in Objective-C.
Method overriding, in object oriented programming, is a language feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its superclasses or parent classes. The implementation in the subclass overrides (replaces) the implementation in the superclass by providing a method that has same name, same parameters or signature, and same return type as the method in the parent class. The version of a method that is executed will be determined by the object that is used to invoke it. If an object of a parent class is used to invoke the method, then the version in the parent class will be executed, but if an object of the subclass is used to invoke the method, then the version in the child class will be executed.
This is a very powerfull aspect of the object oriented programing.
Exemple:
C subclass B and B subclass A
They all have the same methode print
If you have an Arrays with one instance name arr
For i in arr {
Print (i)
}
The good methode print 'll be call for each object
You are talking about overriding methods but the example you gave with the tableView is not overriding the methods. The tableView is using the delegate pattern. In the delegate pattern, there is a protocol that is defined. Let's use UITableView as the example:
The protocol that is defined is the UITableviewDataSource. This is basically a declaration that methods like numberOfRowsInSection should exist in whichever class conforms to this protocol.
When you tell the tableView that you conform to its UITableViewDataSource protocol by saying tableview.dataSource = self, you are telling it that you implement the methods listed in the UITableviewDataSource declaration.
This pattern creates an api for the tableView to consume without having knowledge of the class providing it. Essentially, the tableview will be asking your class for information via the UITableviewDataSource api that was defined.
You can do a search on the delegate pattern to find the pros and cons of implementing it.

objective-c/ios track screen usage

Let's say, for instance, that I want to place some code in the viewDidAppear: method for all UIViewController (including subclasses) objects from my project:
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSLog(#"Did show: %#:%#", NSStringFromClass([self class]), self.title);
}
Is there a way to do this without using categories (for UIViewController), and without having to manually change the superclass of all my view controllers to a new class that defines this method?
The reason I don't want to use a category is because I might want to define methods and call their super implementation.
For instance, is it possible to automatically add an intermediary class between UIViewController and whatever other classes inherit from UIViewController at runtime (or using preprocessor macros)?
The common way to achieve this is called method swizzling. Mike Ash has an article of how to do this correctly.
The general idea is to exchange the original implementation of an Objective-C method. Usually you call through to the original implementation from the inserted function/method.
Here's a quote from Mike's article:
The Obligatory Warning
Overriding methods on classes you don't own is a dangerous business. Your override could cause problems by breaking the assumptions of the class in question. Avoid it if it's at all possible. If you must do it, code your override with extreme care.

Objective-c: How can I require override and not call super?

I guess this is solved by writing a #protocol.
But I'm hungry for knowledge. Is there some flag or other way to require subclasses to override specific methods and not call super? Like the opposite of NS_REQUIRES_SUPER / objc_requires_super?
I do that in code not using any flags.
- I add assertion in the method of the super class that needs to be overridden in case this method is get called
Here I have a class that have a method fetchUserData that should be overridden by the child class
- (void)fetchUserData
{
NSString *descrip = [NSString stringWithFormat:#"child implementation for method:%# : %#",NSStringFromSelector(_cmd), NSStringFromClass([self class])
NSAssert(NO, descrip);
}
If I understand this right you're essentially asking how to make an abstract class... forcing subclasses to implement methods.
Check out : Creating an abstract class in Objective-C
In short, have the method throw an exception.
There are some things here that should be useful.
Specifically subclassResponsibility:
EDIT: Good point in the comments - GNUStep != Foundation. In other words, the methods on the page I linked to should be used with caution. However, I've personally used subclassResponsibility: and it works.

what does do method class in objective c

This might be a silly question. I'm learning objective C (iOS) by studying the code and I came across the expression
[InstanceName class];
What does it do?
I tried to search for class method but It just pops up difference between class method and instance method etc. I guess it might give some sort of class object but I have no idea what is the purpose of the statement.
the original code is Sample Facebook App (scrumptious) using FB SDK....
If you see something like this as a standalone expression....
[InstanceName class];
... then the code is most likely forcing the execution of the +initialize method on said class. The first time any method is invoked on a class, the +initialize method will be invoked prior by the runtime. So, have a look at InstanceName and see if it has a +initialize method.
Note that forcing +initialize to execute in this fashion is a sure sign of bad design. +initialize should never need to be forced like this and should not have execution order dependencies.
There is a legitimate additional reason why this line of code might exist. By referring to InstanceName with a hard reference, it'll force the linker to link in all symbols in the library. (If you don't have a hard reference to at least one symbol in a library -- a .a -- some linkers will simply drop the library from the link unit entirely.)
It gets the class of the object.
So for instance if InstanceName is an instance of class Foo
[InstanceName class]; will return Foo, in a variable of type Class
You can use class_getClassName to get an NSString from this class to log it.
class is a method inherited from NSObject. It lets you get the instance of the class object representing the class of the instance on which the method is called.
It can be used to examine the metadata of the current object. For example, you can use class method to determine if a given object is of a particular class:
if ([sender isKindOfClass:[UIButton class]]) {
...
}
It returns the class of the object. Suppose you have an array of UIView subclasses you created and you want to perform some action only to those who belong to a certain class. You could loop through the array and check for each object's class:
for (id view in myViews) {
if ([view isKindOfClass:[MyUIViewSubclass class]]) {
// Do something
}
}

Resources