Some of my UITextFields are inherited from KaedeTextField from TextFieldEffects
I want to make these textfields to have masks from another framework, the AKMaskField
How could that be done? How can I make a textfield have the style of the KaedeTextField but at the same time also have the masks from AKMaskField?
is it possible to do that in Swift using protocols and extensions?
Swift does not support multiple inheritance for classes. Additionally you could conform to a protocol, but since they are both subclasses of the UITextField, there is no reasonable way and frankly - it doesn't make any sense, since they both handle it their own way.
You would (most likely) end up with a subclass of the first library and then you could recreate a missing feature from the second one.
Related
I have a class that defines all styles on a UIVIew.
They are all predefined but I'm not sure when to fire this.
When I try to create an extension for this:
extension UIView
{
func willMoveToSuperview(newSuperview: UIView?)
{
self.stylize() // Another extension somewhere (not here my problem)
}
}
And I'm getting this error:
Method 'willMoveToSuperview' with Objective-C selector conflicts with
previews declaration with the same Objective-c selector
I have tried to override it, but didn't worked either.
Any ideas on how to be able to apply a same behaviour when all of my UIViews will become visible?
You can use Swizzling technic to customize UIView's function. Take a look at:
http://nshipster.com/method-swizzling/ (objective-c)
or
http://nshipster.com/swift-objc-runtime/ (swift)
Hope that helps.
Even though Swift's Extensions are similar to Categories from Objective-C, what you are trying to do is not allowed in Swift.
You cannot override existing functionality:
Extensions can add new functionality to a type, but they cannot override existing functionality.
Source: Swift Extensions - Apple Documentation
Depending on what it is that you are trying to style, you might want to take a look at UIAppearance, it will allow you to style default colors for the UINavigationBar, amongst other things. NSHipster has a good post about it: NSHipster - UIAppearance
You can create a subclass of UIView with the method .stylize().
Then each view you create, you inherit of you UIView subclass.
You'll be able to cal .stylize() on each UIViewSubclass. Simply write the style code inside the subclass and inherite.
Or
Use a category to add the method to the existing UIView class.
See : https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html
Outside of swizzling (not generally recommended), or subclassing as noted by David in his answer, there isn't really a way to override existing methods on a class and its subclasses.
One thing you might try is creating a base class for your view controller instead of all your views. In your view controller base class, you could override viewWillLayoutSubviews to recurse through the view hierarchy and call stylize on each view. This means you would be using the subclass approach in fewer places (just view controllers as opposed to all views).
Another thing you might consider if taking the subclassing approach with UIView is that if you are subclassing anyway, you can take advantage of things like #IBDesignable and #IBInspectable to better integrate those UIView subclasses with storyboards and live preview.
I wrote a Swift library which does exactly this, and it works well for the type of styling it seems you want to do: https://github.com/daniel-hall/Stylish
I have a "GrandParentViewController" that has all methods of my application. I have a subview "ParentViewController" that contains a few subviews "ChildVC" for which I want the methods to be delegated to the "GrandParentViewController". I currently have a delegate chain from the childVC >> parentVC >> GrandparentVC but it feels wrong. What is the IOS way of doing this?
It seems that single responsibility principle is violated in your code. Maybe it is a good idea to split GrandParentViewController to several classes?
Also make sure you know what is protocol in Objective-C and how it should be used.
I do not recommend to use NSNotifications since it is good and was designed for other cases then direct delegation.
I wouldn't say that there's a set iOS way. I do something similar to what you described because it's the natural way that my VCs should be related. Go with whatever paradigm helps you keep your code clean for future changes, modularized for reusability, and of course, functional.
I will say that if any communications between VCs don't fit with your paradigm, don't force it. Use NSNotifications instead.
Recently I've been looking into RESideMenu. What really piqued my interest was his 'UIViewController+RESideMenu.h/m'. It appears to me that this is a way to subclass a UIViewController. It includes IBActions and methods in it that are accessible from anything that inherits from UIViewController.
All of my attempts to replicate this have failed. Is there a special way to go about it?
Usually that sort of classname is used to denote a category. Instead of subclassing it adds additional methods and properties to a class. For more information see here: CustomizingExistingClasses
I think of myself as an experienced Objective-C programmer. I do apps for a living, and use the language features to it's fullest. That includes using the runtime for varies just-in-time changes to existing frameworks. Stuff like method swizzling and dynamic subclassing really shows how this language is so much more versatile than it's other object oriented C counterpart.
But lately I've been having some thoughts about an old feature, that I still find myself in need of using from time to time, but has been deprecated for some time now. It's a replacement for the old class_setSuperClass.
I often find myself subclassing UIKit classes in order to extend them or just change their behaviour slightly. One example I came across recently was an UIScrollView subclass, that made some conditions to the panGestureRecognizer. I did that by subclassing UIScrollView and then implementing the gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:.
This had to be done this way, because you're not allowed to change the delegate of a scroll view's pan gesture recogniser (it will throw a runtime exception), and you cannot create your own custom UIScrollView panGestureRecognizer.
Now this all worked out great. I changed all usages of UIScrollView in my app to my newly created subclass, and everything worked as expected. But what about UITableView and UICollectionView which I also used throughout the app. What to do with those? As you know, both of these classes is inherited from UIScrollView, but not my custom subclass of UIScrollView. So I found myself ending up writing the same code multiple times for every class that existed (and was used in the app) that inherited from UIScrollView. Writing the same code multiple times is a programmers 1-2-3 no-go. But I did end up writing a custom subclass not only for UIScrollView but also for UITableView and UICollectionView.
Now in the old days with the class_setSuperClass you were able to "swizzle" the superclass of an already prepackaged class like UITableView. You basically just said class_setSuperClass([UITableView class], [MyScrollView class]), and everything worked out (well almost) fine. Now you had injected your own class in between UITableView and UIScrollView. So every time you did [[UITableView alloc] init] it would have the features of MyScrollView because it inherited directly from it.
Now class_setSuperClass was deprecated in iOS 2.0! Since that we could do some swizzling and hacking with the object's isa pointer. Now that has been deprecated too.
So my question is really simple. How would you approach this?
If you want to globally change a class's behavior, rather than play with class identities, the direct approach would just be to replace the method you want replaced. The runtime still allows this, with class_replaceMethod(). That seems like the simplest way to accomplish what you want here.
i asked me whether it is possible if i can create a uislider who has 2 handles to select a range. Just like here:
The problem i am facing is that i dont want to use a custom UIControl Subclass. I need a UISlider subclass or a other solution for this problem, because a lot of the code is based on UISlider specific propertys etc. So is there any possibility to achieve this ?
Look at the following example:
http://www.cocoacontrols.com/platforms/ios/controls/rangeslider
You can subclass UISlider, but it will be very difficult. Your class should offer quite some new properties, and the old ones won't make much sense at all.
Not sure how your code can be based much on UISlider specific things - as everything would change the meaning (i.e. ranges instead of one value).
If you really need a common base class, you could encapsulate ("has-a" relationship) the control in a custom class and let this handle the different types.
I implemented a similar control using a custom view, and it happened to be quite straight forward.
UISlider doesn't provide the functionality you're after, and subclassing UISlider probably won't work out. What would the value of such a control be? The value of a slider is a number, but you want it to be a range. Consider a custom control that duplicates the UISlider properties you need.