Heres my scenario. Most of my network calls now need to have an api key inserted into the header field when making a request. So what i was thinking i could do was make a category of NSMutableUrlRequest. Override one of the initalizers. Then in that one initializer i could set the api key as a header field. So everytime i create an object of NSMUTABLEURLREQUEST the header field i need is already set. If you look at the apple doc here NSMutableUrlRequest you can see that the object has 4 initializers 2 class and 2 instance methods. Ill list my questions
What initializer function should i override in order to complete my task? The class or the instance ones?
How can i override it? Either if its an instance or class initializer?
Is this even a good way to go about it? or should i just subclass it and override it like that?
My code has been written for sometime now and well i dont want to go back and insert the api key into each individual request because well theres a lot of them. In a way i think this is a better approach to it because ill just have to set the apiKey in one place and not many place, which lessens the probability of a programming errors.Thank you for your help.
P.S. Even if this isnt a good way to complete this can someone still show me how a class initializer works? Like whats the underlying code so i can generate my own static class initializers also. Each time i try to override the class method i cant figure out what type to return.
Thank you for your help
Categories are not meant to be used to override. You use categories when you want to add additional functionality to existing classes. If you really want to override the initializers then use inheritance.
The static functions are not initializers, they are just helper functions that creates the instance for you, so there's no need to handle them. The simple initWithURL: method is just a simplified version which provide default values for the designated initializer initWithURL:cachePolicy:timeoutInterval:; so in your subclass you actually only need to override this single initializer, looking something like this:
#interface MyNSMutableURLRequest : NSMutableURLRequest
#end
#implementation MyNSMutableURLRequest
- (instancetype)initWithURL:(NSURL *)URL cachePolicy:(NSURLRequestCachePolicy)cachePolicy timeoutInterval:(NSTimeInterval)timeoutInterval {
self = [super initWithURL:URL cachePolicy:cachePolicy timeoutInterval:timeoutInterval];
if (self) {
//do your stuff here
}
return self;
}
Related
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/
I try to dynamically call certain viewController/Feature depends on his Name.NSClassFromString
(that kind of idea was suggested by Facebook).
For Instance from my server I can define in IOS app which feature or viewController should be used.(or On/Off them)
I searched all over Stack but still cant find an elegant way to implement what I want
Class myclass = NSClassFromString(className);
id obj = [[myclass alloc] init];
will work.
But I would like to call my custom init.
Class myclass = NSClassFromString(className);
id obj = [[myclass alloc] initWithCostumInitializer:userInfo];
I cant find a proper way to do it. Of course every time I receive an error because initWithCostumInitializer is not recognised.So I need to make the decision in run time.I believe I missing something.
Tnx a lot.
First off, you shouldn't get a compile-time error about an unknown method if the headers for the possible classe(s) are imported into the .m file where this code is running. Because of exactly this sort of dynamism, ObjC should let you get away with calling fairly arbitrary methods on objects of type id.
But that's just a bandaid solution. Really, if you know that that custom initializer method is present, then it's not an arbitrary class, right? You have some idea what kind of object it is, or at least what kind of base class it derives from, otherwise you wouldn't know to call that method. So you could always:
id customObj = [((BaseViewController *)[myclass alloc]) initWithCustumInitializer:userInfo];
If your error is a runtime error about the receiver missing that selector, then you have a real problem, which is: why are you calling a named method on an object that might not be the kind of object that has that method? If that's what's happening, you'll need to look at the class first to figure out what kind of thing you're actually about to create, and then behave appropriately for the init.
I have a class, User, that has an NSMutableArray that stores custom NSObjects. I only want one of these to ever be instantiated throughout the entire app, and I would like to be able to call methods on it in each ViewController for getting and setting. My problem is that I don't know how to call the methods so they apply to this one instance, instead of creating a new one each time. I'm new to objective-c, so the learning curve makes me feel I'm missing something a bit obvious. I've been working on this all day and am at a wit's end. Is there a good solution to my dilemma? Should I use a singleton class?
(If it helps, the class User is basically a class that stores a to-do list for each user that uses my app. The custom NSObjects are to-do items. There's probably a better storage method that should be used here, but I'm not sure what it is.)
RandomPleb it sounds like what you're looking for is a Singleton. http://en.wikipedia.org/wiki/Singleton_pattern. I also think this question has been answered before so search around on SO.
Laymen's terms; you create a static reference to the class that you only want one of inside that class, then make a static method in the following way:
//call this from classes that want to modify it
public static getsharedinstance()
{
if(the static instance of this class does not exist){
instantiate instance;
}
return this classes static instance..
}
Hope this helps (and if this is wrong, I hope someone can correct me)
Also in regards to your storing objects, I think NSMutableArray is fine unless it is a very big persistent list where each task has many properties in which case maybe using CoreData would be better.
Fenix
I have class called ViewController. How to make this class is a sub-class of "metaiosdkViewController" and "JWslideViewController". Help me with syntax.
i have written like this
#interface ViewController : MetaioSDKViewController,JWslideViewController
but this giving me error
objective-c doesn't support multiple inheritance,but if you want to add some extra behaviour you can achieve it through delegates..
yes objective-c doesnt support multiple inheritance but you can give one parent so
#interface ViewController : MetaioSDKViewController
and
#interface MetaioSDKViewController : JWslideViewController
this is just an idea I know you can implement well as per your need
What is it that you want to achieve with multiple inheritance?
Do you want to override methods from each of these super classes?
Note that objective c provides 2 mechanisms for extensibility:
1) Implementing a Protocol and make your object the delegate:
#interface ViewController : <MetaioSDKViewController,JWslideViewController>
This enforces ViewController to implement certain methods as defined in contract by 2 delegates, and at some point in processing, they get called. If you don't implement them, they may simply not be called but you may not get desired functionality.
Example: UITableViewDataSource protocol that defines many methods that UITableViewController subclass implements. cellForRowAtindexPath is very famous example of a delegate method that your own table view subclass must implement to draw your own custom cells.
Note that this is not the type of extensibility that subclasses provide in general sense. Your class does not extend any functionality here. Rather it becomes what it says - a delegate - someone who is assigned to do some task. Like you do:
yourTableView.delegate = self; //tell self to be the delegate of yourTableview
Library code does it's stuff and in some point in processing it calls [delegate someMethod]. If your own class implements it, it calls it, otherwise delegate will be nil, and it may just be NO-OP and you don't get desired functionality. Again, this is implementation-dependent. Maybe the protocol defines that the method is compulsory, in which case your class MUST implement this method in order to compile.
2) Implement a category:
This is sort of a shortcut way to extend library classes. They act like an extra stub which, when your code runs, attaches itself to the already existing memory layout of the library objects and provides extra functionality.
You can define a category on any of the in-built classes as well. In fact that is the primary objective it is used for. For example, here is an NSString category which provides HTML conversion. There are hundreds of categories implemented as open source and they provide enormous benefits where library code falls short. Discussing their suitability in entirety is however out of scope for this discussion.
One thing to note however is: You do not override anything using a category. Rather you are supplying something in extra. For example if you want some custom drawing across all your app views, you can define a category on UIView in your project and then all your views could simply include the category header file. You don't even have to inherit from this category, you simply inherit from the base type.
e.g. in the NSString category example above, you do not have to define your NSString to be of type NSString+HTML. Instead you just include the responsible NSString+HTML.h file wherever you want those extra methods like stringByConvertingHTMLToPlainText and so on. The changes remain limited to your project - to the files where you include this category.
Categories do not provide for extra data members - and that is something that only inheritance can provide. Yet, multiple inheritance among viewcontrollers is something you should definitely reconsider hundred times - you will see that what you are looking for is not multiple inheritance.
So I'm getting myself into a confusion over where my data's going and where it's stored in my application. It's not a specific question so hopefully someone can provide a generalised answer.
I need to pass some data around between a few UIViewController instances, and I'm currently doing that with a singleton object called my dataManager. This class has one method, a class method, called + (LCDataManager *) sharedDataManager, and that method basically checks if whether the sharedDataManager already exists, if so, return it, if not, create it and set up its variables. This means that I can refer to that class anywhere I like, access and modify its variables anywhere I like, from across multiple classes.
First question: is this the correct / best / most appropriate means of passing data around like this? I'm hoping it obeys MVC, it feels like it does, and I hope I'm right.
Second question: what if I want to put an instance method in that class, and call it from within the class method? Let's say my sharedDataManager needs to call a method to grab some objects one of its variables (an array), and put them in another array, then send that back out again. I can't do that, can I? What's the way around that? If I make an instance of that class (rather than using the shared instance), I lose the ability to use that instance across multiple viewControllers.
I'm hideously confused, and it seems like it's not the problem I'm making it. Appreciate any guidance, and preferably not that "Read the Apple documentation" stuff – they write as if you already know what you're doing, and frankly I don't yet.
First question: is this the correct / best / most appropriate means of passing data around like this? I'm hoping it obeys MVC, it feels like it does, and I hope I'm right.
Your design is perfectly MVC compliant.
Second question: what if I want to put an instance method in that class, and call it from within the class method?
you can surely define an instance method and call it like this:
[[MyModelClass sharedModel] myInstanceMethod];
indeed, [MyModelClass sharedModel] will give you an instance of MyModelClass (which should be guaranted to be unique being it a singleton).
If you want to call the instance method from the sharedModel class method, you could also do that, because sharedModel owns a reference to your singleton, so it can send messages to it.
is this the correct / best / most appropriate means of passing data around like this?
There's nothing wrong with only having a single instance of LCDataManager, but using the Singleton pattern has potential problems. An alternative is to just initialize one LCDataManger and to pass it around to wherever it's needed.
what if I want to put an instance method in that class, and call it from within the class method?
The accessor + (LCDataManager *) sharedDataManager should only return the instance. I guess what you want is something like
+ (LCDataManager *)preparedDataManager {
LCDataManager *shared = [self sharedDataManager];
[shared doSomeInstanceMagic];
return shared;
}
- (void)doSomeInstanceMagic {
// magic!
// grab some objects one of its variables (an array),
// and put them in another array
}
Matthijs Hollemans has an excellent three-part tutorial on his blog about the correct way to make your view controllers talk to each other:
Part 1
Part 2
Part 3
there is no problem with this development architecture, and it is the must used (I think) in the iOS development. In the book IOS Programming: The Big Nerd Ranch Guide they call it Model View Controller Store.
Regarding your second question, yes, you can declare instance methods and call then from your sharedDataManager. What is not usual is creating other instances of a singleton class, but it is possible.