Swift Protocol conform to two specific classes only - ios

I want to make a protocol which can only be conformed by UIlabels and UIButton, is there a way ?
Example :
protocol MyProtocol {
func setTextValue()
}
I want MyProtocol to only be acessed by UILabel and UIButton and no other class

I want to make a protocol which can only be conformed by UIlabels and UIButton, is there a way ?
Which can only be? Not directly, no. You cannot impose upon another programmer a contract such that programmer cannot make some other class adopt your protocol (e.g. forcing the compiler to complain if that happens).
But perhaps you mean which is only “conformed” (i.e. adopted). In that case, certainly. Nothing prevents you from declaring a protocol and then declaring, yourself, that UILabel and UIButton do adopt it (and not declaring that any other classes adopt it). Just do it.

An extension may be a better suite for this, especially in swift, depending on what you want you want to do.
extension UILabel {
func greenBackground() {
self.backgroundColor = .green
}
}
Then you can use it anywhere in your project on any UILabel like this:
let label = UILabel()
label.greenBackground()

Related

How to implement protocols and delegates in SwiftUI

I was converting one of my swift project into SwiftUI. I need to convert delegtes and protocols to SwiftUI, is it allowed in SwiftUI? or any alternative methods are there? Please help me i'm so confused in SwiftUI.
I'm calling a delegate method from one of my class, then delegate method will be present in another ViewController.
//PresenterClass
protocol SplashPresenterDelegate {
func didFetchedSystemInfo(info: String)
}
class SplashPresenter: NSObject {
var delegate: SplashPresenterDelegate?
func getSystemInfo(){
self.delegate?.didFetchedSystemInfo(info: "ResponseString")
}
}
// Viewcontroller class
class myViewController: UIViewController {
.
.
.
}
extension myViewController: SplashPresenterDelegate{
func didFetchedSystemInfo(info: String){
print("delegate called")
}
}
Please help me to convert this code to SwiftUI
Typically, SwiftUI prefers the pattern of taking callbacks rather than protocol/delegates. For instance, each button in an ActionSheet has a closure that is executed when the button is tapped.
You shouldn't just convert your code over directly, though. SwiftUI, being declarative, uses different paradigms for a lot of things. For instance, you wouldn't have a didFetchInfo method, you would just assign it to a #Published variable.
Think about having "single sources of truth", where a single variable is always correct. For example, List simply takes an array and updates when the array changes, unlike UITableView where you provide the data through numberOfRows and cellForRowAt. I don't know enough about your specific project to give more detail, but those are things to think about.

Subclass/Extend UIView so all other Views (UIImageView, UITextField ...) inherit upon creation

what is the suggested approach when I want to add a functionality to UIView so all views inside my app get those? As a matter of fact I need to add some stored properties too so an Extension is not possible. Since I need to deal with Textfields, ImageViews, Views (and who knows what else will come) I dont want to subclass every each of the too add that functionality, so the goal would be to make a subclass of UIView and all my controls (if its possible) get that functionality out of the box.
With an extension it would be easy, but as I said, I need to store some stuff too, so is this goal achievable with a subclass? Or what would be the right approach (maybe there is a third option)
Thanks
Why don't you define a protocol and provide default implementations in the protocol extension, then have UIView conform to that protocol? Here is an example:
protocol MyProto {
var someVar: Bool { get set }
func someFunc() -> Void
}
extension MyProto {
var someVar: Bool {
get {
// provide default implementation
return true
}
set {
}
}
func someFunc() -> Void {
// provide common implementation
}
}
extension UIView: MyProto {}
You can also use the where clause to constrain the default behaviour for a type.
extension MyProto where Self: UIControl {
var someVar: Bool {
get {
return isUserInteractionEnabled
}
set {
isUserInteractionEnabled = newValue
}
}
}
extension MyProto where Self: UITextField {
var someVar: Bool {
get {
return isFirstResponder
}
set {
newValue ? becomeFirstResponder() : resignFirstResponder()
}
}
}
TLDR; You can't do this and you will need to subclass each UI element that you want to introduce new properties to.
You can't do this (without access to the source code) as you would effectively be changing the class inheritance tree by injecting your own class between UIView and its subclasses.
Consider the implications if a language allowed this:
Class A defines a property, a
Class Binherits from Class A and defines a property b, which is fine because Class A does not have this property.
Class C inherits from Class B and has both a and b properties.
Now, what could happen if you could 'inject' Class A1 somehow 'below' Class A?
Class A1 could define a property, b, which is fine because Class A does not have this property
Class B now has a problem though, because its b clashes with the superclass b
Class C has a multiple-inheritance diamond-problem with property b
Of course, you only intend to add properties that don't clash (although you can't know this because you don't know of all possible subclass implementations) and don't need the subclasses to access your property, so the multiple inheritance
isn't an issue, but if such a feature were in a language, these potential issues would need to be addressed because you can't rely on everyone having the same intentions as you.

Swift property conforming with multiple protocols

I have custom UIView (CustomView) conforming to two different protocols
protocol ResizableDelegate: class {
func view(view:UIView, didChangeHeight difference:CGFloat)
}
protocol Resizable: class {
var delegate:ResizableDelegate? { set get }
}
protocol TappableDelegate: class {
func viewDidTap(view:UIView)
}
protocol Tappable {
var delegate:TappableDelegate? { set get }
}
And I need to have a property in my CustomView class named delegate and conforming to these two protocols at the same time. I read Types conforming to multiple protocols in swift but that is not solving my problem.
I created this protocol
protocol CustomViewDelegate: ResizableDelegate, TappableDelegate {}
And then make my CustomView
class CustomView : UIView, Resizable, Tappable {
var delegate:CustomViewDelegate?
}
But that is causing me to get a message
Type 'CustomView' does not conform to protocol 'Resizable'
I don't want to have:
class CustomView : UIView, Resizable, Tappable {
var resizableDelegate:ResizableDelegate?
var TappableDelegate:TappableDelegate?
}
Is there any way two have only one delegate property that conforms to these two protocols at the same time? Im using swift 2.0, Xcode 7.
I guess you don't really need to declare Resizable and Tappable protocols. All you need is to delegate from your custom view to some other object, which confirms to both ResizableDelegate and TappableDelegate, right? If so, this should work for you:
protocol ResizableDelegate: class {
func view(view:UIView, didChangeHeight difference:CGFloat)
}
protocol TappableDelegate: class {
func viewDidTap(view:UIView)
}
class CustomView : UIView {
var delegate: (ResizableDelegate, TappableDelegate)?
}
Although you can leave things as is, I would strongly recommend changing the required properties to "tappableDelegate" and "resizableDelegate" thus having two separate properties in your View subclass.
Your specific use case may require adherence to both, but having the same naming means you would not be able to have different delegates.

Protocol extension vs class extension in Swift

Assume there is a protocol Draggable, usually will be conformed by an UIView object
protocol Draggable {
drag()
}
We can either implement drag() in a protocol extension as option 1
// option 1
extension Draggable where Self: UIView {
func drag() {
// implementation
}
}
extension UIView: Draggable {} // added after #Rich Tolley's answer
Or we can implement drag() in a UIView extension as option 2
// option 2
extension UIView: Draggable {
func drag() {
// implementation
}
}
Here is my question:
Is there a difference between these two approaches (option 1 & option 2) ?
If yes, what's the difference and how to choose when we design a our project or library ?
And idea would be helpful.
Yes, there is a difference: (EDIT: or at least there was in the original version of this q, which didn't add extension UIView : Draggable {} to the end of option 1).
Option 1 creates a default implementation for instances of UIView that conform to Draggable. You still need to mark UIViews you wish to conform to Draggable as such in the declaration: class MyView : Draggable. Anything that conforms to Draggable but is not a UIView subclass will need to supply its own implementation.
Option 2 extends all UIViews to make them conform to Draggable. Nothing else can be a Draggable unless separate extensions are also written for those classes, or they are manually conformed to the protocol. There is no need to add Draggable in the class declaration.
The protocol extension is usually the better option. In this case this is obviously true since not all UIViews can be Draggable. Also, going down the protocol extension route means that you can create a Draggable object that is not a UIView subclass, if necessary (admittedly fairly unlikely, since most Cocoa controls are UIView subclasses - although not all -UIBarButtonItem isn't, strangely)
If you follow option 2, you will be adding unnecessary methods to UIView in a lot of cases, which is a violation of good object oriented design - specifically the Interface Segregation Principle (clients should not be forced to rely on methods they don't use
) - which is the 'I' in the SOLID principles
A protocol extension should be used when you want to implement functionality for more than just one class.
In this case you should use the extension UIView: Draggable as the Implementation is specific to the UIView class.
Assuming you have a protocol which provides location:
protocol Location {
var location: CGPoint { get set }
}
and you want every class which implements Location to conform to Draggable, then a protocol extension could be used:
extension Draggable where Self: Location {
func drag() {
}
}
For further reference, you should have a look at Protocol-Oriented Programming in Swift from the 2015 WWDC.

Swift - Same protocol for two different classes

I want to use the same protocol for two different classes. It is for two UIStoryboardSegue classes, the normal one and the unwind segue. In my first class GameSegue.swift, I've declared this protocol
#objc protocol ViewControllerWithBackgroundImage {
var backgroundImage: UIImageView { set get }
}
I use this protocol to have access to the ViewControllers property backgroundImage. In the first class GameSegue.swift, the normal segue, the backgroundImage animates 10 px up. So in the second class GameSegueUnwind.swift, I want to do the same thing backwards, move the background 10 pxdown. But to get access to the backgroundImage property I need this protocol. Therefore it would be useful, to not declare another protocol, but instead use the same.
Any idea how this is possible?
In the second class just declare a new delegate variable
class GameSegueUnwind {
var secondDelegate: ViewControllerWithBackgroundImage?
}
and you will be able to access the function in any other class that conforms to the protocol. Of course, in the conforming class remember to declare it has the delegate handler in the prepare for segue method
destinatonViewController.secondDelegate = self

Resources