I'm finally making the switch from Objective-C to Swift. I'm creating a view layout system for my client to make their apps more flexible in layout, without using auto layout as they want to design their screens remotely and auto-layout would be too complex for them. I tried to do this using structs and protocols but I found it to be quite clumsy, so I'm suspecting I'm not thinking about it the right way.
With classes, the structure would be as follows:
class ViewModel {
var frame: CGRect = .zero
}
class ViewGroupModel: ViewModel {
var weight: Int = 1
var children:[ViewModel] = [ViewModel]()
}
class HorizontalViewGroupModel: ViewGroupModel {
}
class VerticalViewGroupModel: ViewGroupModel {
}
I tried to approach it with protocols by defining a ViewModel protocol, and a ViewGroupModel protocol, but I found it created a lot of duplication (properties). Is there a better approach? Would it be considered a good practice to use classes in this case?
EDIT: In case it would be better to not uses classes, I am looking for an answer that gives me a concrete solution in terms of structs and protocols.
If the concern was merely how to implement the protocol's properties, I wouldn't necessarily let that sway my choice between struct vs class. If you had a variety of properties that your struct types must implement, you have two basic options:
If you're talking about a few properties, just implement those few properties in your struct types that conform to that protocol. We do this all the time. E.g. when defining custom types that conform to MKAnnotation, we simply implement the three required properties.
Sure, if we're talking about a much larger set of properties, this gets tedious, but the compiler holds our hand through this process, ensuring that we don't miss anything. So the challenge is fairly modest.
While I'm not a fan of this approach, https://stackoverflow.com/a/38885813/1271826 shows that you could implement the shared properties as a component, where you have struct to wrap all of these properties, and then implement default computed properties for your protocol in an extension:
enum SubviewArrangement {
case none
case horizontal
case vertical
case flow
}
struct ViewComponent {
var frame = CGRect.zero
var weight = 1
var subviews = [ViewModel]()
var subviewArrangement = SubviewArrangement.none
}
protocol HasViewComponent {
var viewComponent: ViewComponent { get set }
}
protocol ViewModel: HasViewComponent { }
extension ViewModel {
var frame: CGRect {
get { return viewComponent.frame }
set { viewComponent.frame = newValue }
}
var weight: Int {
get { return viewComponent.weight }
set { viewComponent.weight = newValue }
}
var subviews: [ViewModel] {
get { return viewComponent.subviews }
set { viewComponent.subviews = newValue }
}
var subviewArrangement: SubviewArrangement {
get { return viewComponent.subviewArrangement }
set { viewComponent.subviewArrangement = newValue }
}
}
Where, you can then create an instance that conforms to ViewModel, like so:
struct LabelModel: ViewModel {
var viewComponent = ViewComponent()
}
var label = LabelModel()
label.weight = 2
print(label.weight)
I have to confess, this isn't the most elegant approach. (I hesitate to even present it.) But it avoids having to implement all of those properties individually in your types that conform to ViewModel.
So, let's set the property question aside. The real question is whether you should be using value type (struct) or reference type (class). I think it's illuminating to consider Apple's discussion of value vs reference semantics near the end (#42:15) the Protocol-Oriented Programming in Swift video. They touch upon those cases where you actually may still want to use classes. For example, they suggest you might want to use reference types when, "Copying or comparing instances doesn't make sense". They suggest this rule might apply when dealing with "Window" instances. The same applies here.
On top of that, it doesn't seem to me that there is much benefit to use value types to represent a view hierarchy, which is a collection of reference type objects. It only makes it more confusing. I would just stick with class types, as it will accurately mirror the view hierarchy it represents.
Don't get me wrong: We're so used to using reference types that I think it's always good to challenge our preconceived notions and take a long hard look at whether a value type could better address the situation. In this case, though, I simply wouldn't worry about it and just stick with a class hierarchy that mirrors the hierarchy of those objects you're modeling.
That having been said, the class hierarchy proposed in your question doesn't quite feel right, either. It feels strange that you can actually instantiate a ViewModel to which you can't later add subviews (whereas all UIView objects have subview property). Also, your horizontal and vertical group types don't feel correct either. For example, should it be a single type with some "axis" property, like UIStackView or some other "arrangement" property, to broaden the notion to capture UICollectionView layouts, too?. As you'll see in my ViewComponent example, above, I've flattened this a bit, with these two caveats in mind, but do whatever you see fit.
In general, use a class only if you need the special features of classes, which are:
A class can have a superclass and/or a subclass; a struct can't.
A class is a reference type, while a struct is a value type.
Objective-C can introspect a class (esp. if it derives from NSObject), whereas it cannot even see a struct declared in Swift.
Its always good to code to interface/protocol than to classes/structs. This your model wisely.
You can make use of generics as well beautifully for this purpose. I hope it would save a lot of variables and duplications for you.
For layout purpose in my opinion structs coupled with protocols and generics would make a great design. I don't see for you any need to use classes in your case.
Its always good to know in and out of a feature to better use it. The main difference between structs and classes in Swift are
Class objects are stored/passed as references where as struct instances are stored/passed as values
Reference counting allows more than one reference to a class instance.
For Class we have identity operators === and !== which are used to check whether two variables or constants refer to the same instance of Class. The question for identity operators does not arise for Struct because two different Struct variables or constants can not point to same instance. You can try applying identity operator to Struct types. You will get compile time error.
Inheritance enables one class to inherit the characteristics of another.
Type casting enables you to check and interpret the type of a class instance at runtime.
Deinitializers enable an instance of a class to free up any resources it has assigned.
For detailed disscussion you can through my post Struct Vs Classes in Swift.
Related
I'm trying to simplify a huge file in Swift and I'm not sure what would be the best approach. It might be a very naive question as I'm still fairly new to Swift :)
For the sake of simplicity, let's say I have one User struct and in it I can call a ton of different setupModeA, setupModeB and so on, called depending on various conditions:
struct User {
var currentMode: String
mutating func setupModeA() {
currentMode = "A"
}
mutating func setupModeB() {
currentMode = "B"
}
// and so on for each mode
}
I'd like to be able to take the setupMode*() functions and their associated helper functions into a separate file to make it easier to read through, since most of the time I'd be focusing on only one mode.
I was thinking:
struct ModeA {
mutating func setup() {
// change the mode from there
}
}
However I can't figure out how to simply pass and mutate the User info to this new struct.
I thought about:
initializing a bunch of ModeX objects with a user variable in the User struct and passing the User on init, but it creates weird behaviours.
using static methods on the ModeX structs, but then I'm not quite sure how to mutate the User
taking a more functional approach & not mutating the User but instead cloning it and re-assigning it each time... this would probably work but since my code is very sequencial it feels like added complexity / memory usage for nothing.
switching from struct to classes and hoping it gives me other options... but I'm afraid everything would break
really complex things that feel too weird and unintuitive to be mentioned here :)
Any pointers would be much appreciated.
Overview
I was trying to get my head around Swift's Protocol Oriented Programming paradigm. As per Apple's WWDC 2015 video https://developer.apple.com/videos/play/wwdc2015/408/ Protocols can achieve everything that inheritance can and also solves the fundamental issue with inheritance.
Though Protocols solves the problem of multiple inheritance by capturing each capability (functionality) as protocol and allowing a class/struct to confirm multiple protocols, I believe Protocols can never replace inheritance for the following reason.
Lets assume I am implementing College/School automation software and there are two Entities, Staff and Principal and lets assume they both take class but principal along with taking class controls the staff.
So I create a protocol which will model the common capability which is taking class. So let's create a protocol.
protocol staffProtocol {
var classHour : Int { get set}
var numberOfClass : Int? { get set }
mutating func doesWork()
}
extension staffProtocol {
mutating func doesWork(){
classHour = 9
numberOfClass = 4
print("Takes calss")
}
}
As Taking class is a common task for both staff and principal so I provided a default extension which provides a implementation for doesWork() and says takes class.
Now let's write a Staff struct which will confirm to staffProtocol,
struct Staff : staffProtocol {
var classHour: Int = 0
var numberOfClass: Int? = 0
}
Now if I create a staff object as
var staff = Staff()
staff.doesWork()
Everything works absolutely fine, now lets create a Principal struct which will also extend staffProtocol,
struct Principal : staffProtocol {
var classHour: Int = 0
var numberOfClass: Int? = 0
mutating func doesWork() {
print("Also controls other staff")
}
}
Now along with teaching he also controls other staff, so if I override doesWork() and write "Also controls other staff". Now the code in default extension will never be called.
Now in order to provide both teaching capability and controlling capability, I have two methods,
I can create another protocol which will model controlling capability and make principal struct to extend it
Copy the whole code in default extension of staffProtocol to the principal struct's doesWork implementation and add a line which says Also controls other staff.
Issues:
Issue with Solution 1. We faced the similar issue in Inheritance, when there was need to implement the capabilities which belonged to two different parent classes and as multiple inheritance was not allowed we used to create the capability as a component and add the component as a property to parent class so that we can achieve multiple capability without having to implement multiple inheritance (which is anyway not allowed). But apple says its too much of code and absolutely not essential.
Even with protocol oriented programming if I have to implement each capability as a protocol isn't am running into same nook of the problem? Rather than creating a capability as a component am I not creating it as a protocol? How is that protocol adding benefit here?
Issues with solution 2. Because I can't call the default extension of the protocol and end up writing the whole code in struct specific implementation again, Haven't I ended up in code duplication issue which is the common problem which inheritance tried solving in a very first place?
Question
Question am trying to find solution is not how can I solve it? There are 100 ways to solve each problem, all I am trying to ask is,
Is protocol programming really an alternative to Object oriented programming?
Is protocol really a replacement to inheritance ? If yes at what cost? Writing simply super.doesWork() was clear or writing a separate protocol for each capability?
I might have completely misunderstood the concept of Protocol Oriented Programming, please help me understand the same.
(Very late to the party though. I came across this thread after having some beginning level knowledge about the POP)
Suppose, you are going to write some bird classes. Like:
Flappy Bird
Swift Bird
Stork Bird
Penguin Bird
Ostrich Bird
Eagle Bird
Some of them can fly and some can't. In OOP, you have various options to design. Most commons are:
You design a base class Fly, then by subclassing it you design Bird and then you use this Bird as the base class for all the bird classes in the question. Override the flying/not flying behavior for each bird type.
Or, you can have a base class Fly, you subclass it for FlyingBird. And then you have another base class NotFlyingBird. After that you subclass these two classes according to your need.
The above approaches work. But you see for the case 1:
Every time you create a new bird, you are also inheriting some capabilities that you don't need maybe.
And in the case 2:
You create two separate base class of your need! What if you need to write something common for FlyingBird and NotFlyingBird? You will probably end up changing your mind to use the approach 1 here.
And lastly, every time you change your mind in later time you end up inheriting from different base class. Or just adding all of the behaviors in a god-like class
Now see, how you can design this with POP approach.
protocol Flyable { ... }
protocol Bird { ... }
struct Flappy: Bird, Flyable { ... } //it's a bird & can fly
struct SwiftBird: Bird, Flyable { ... } //it's a bird & can fly
struct Stork: Bird, Flyable { ... } //it's a bird & can fly
struct Penguin: Bird { ... } //it's a bird but can't fly
struct Ostrich: Bird { ... } //it's a bird but can't fly
struct Eagle: Bird, Flyable { ... } //it's a bird & can fly
See! how POP really shine? So, it’s a good thing you didn’t take the inheritance approach, and make all birds flyable after all!
With protocol oriented programming you just don't magically inherit everything from the Super class. You are enforcing to provide their own. With this approach, you are adding behaviors. So you can keep out the burden off your shoulder.
If you need anything very new, you just add to them and not enforcing every other one to have that very new thing without their actual consent.
This Introducing Protocol-Oriented Programming in Swift 3 article from RayWenderlich may even lighten up you a bit more.
You might even have a look at this answer from a different thread.
Let's answer your trailing questions in short:
Is protocol programming really an alternative to OOP? -> Not always. But it has it's shine.
Is protocol really a replacement to inheritance? -> Again, No. But!! If you are designing from the scratch it's worth it to give this idea a shot.
I'm new in Swift and even in object oriented programming languages itself. So my question is, how to use this very extensive language Swift the right way? I give an example to verify my problem:
Let's say I have got two classes:
Class ScanForBluetoth{} //Handles all parts to scan for BT devices
class ScanForDevices: UIViewController, CBCentralManagerDelegate , CBPeripheralDelegate, UITableViewDelegate,UITableViewDataSource{}
Class Bluetooth{} //Handles only the Bluetooth parts with it's delegates
class Bluetooth: ScanForDevices{}
Now, I would like to implement all my used delegates and other Bluetooth specific functions into the Bluetooth class. BUT I need some objects (for example of the CBCentralManagerDelegate) in my ScanForDevices class, too. So, I have to implement all my delegates in my "mother" class ScanForDevices although I only need some properties. SO if I implement the delegates, I have to be conform with the protocol and must implement ALL my needed delegate functions... At the end I have implemented all my delegate functions in ScanForDevices and then override them in Bluetooth. But I don't think that my way is the best way to realize this problem...
Thanks for reading!
Firstly, I would like to point out that your naming conventions are really off. In object oriented programming, you want your class names to be objects (nouns). You named your classes by what they were doing, rather than what they are. A better name choice for your classes would be something like BluetoothDeviceScanner, rather than scan for devices, and BluetoothManager rather than the non-explicit "bluetooth".
Secondly, what you have done is subclassed the bluetooth class to scan for devices class, which causes it to inherit all the functionality of its class. This really doesn't make any sense. Subclassing is used to create an object based on a parent object, while these two objects handle two totally different things, and then you're planning on overriding the functions anyway. Instead of that, you should just include the protocols that you need in the bluetooth class separately. Keep the functionality of the two classes separated as much as possible.
Thirdly, you should separate your view controller functionality from the scanning functionality. What I mean is the "ScanForDevices" object's job is to scan for devices, so it shouldn't also have the job of controlling a view... I would remove the UIViewController protocol and introduce a new view controller class, and within that class you can have a property that is assigned the "ScanForDevices" object, at which point the devices can be scanned for within the viewcontroller, but the scanning functionality is contained within a single object (which is best practice).
EDIT
All you need to do to "connect" the data is have your BluetoothManager and BluetoothScanner objects is have them available as a property within whatever view controller you need them. So, in the viewcontroller declare some properties, I usually do it with optionals so that I don't have to worry about initializing the properties (This means you need to unwrap the variables before using them).
In your ViewController...
var bluetoothScanner: BluetoothScanner?
var bluetoothManager: BluetoothManager?
override func viewDidLoad() {
super.viewDidLoad()
bluetoothScanner = BluetoothScanner(init parameters)
bluetoothManager = BluetoothManager(init parameters)
}
You're objects are now "connected" in the sense that you have access to them and all their properties/methods in the viewcontroller. Now that I think about it, you don't even need to have both objects on this level. You can store the BluetoothScanner as a property of the Bluetooth manager, at which point you would only need to use a BluetoothManager object to handle all your bluetooth needs on the view controller level.
Init Methods
//init method that takes 2 parameters, a string and a uiviewcontroller.
init(param1: String, param2: UIViewController) {
//Struct init code using parameters
self.name = param1
self.viewController = param2
}
//init method that takes no parameters, but still initializes the same properties.
init() {
self.name = "YungGun"
self.viewController = UIViewController()
}
Keep in mind these initialization methods are made up and have nothing to do with your problem at hand, I was attempting to illustrate that this is where you define the parameters needed to initialize the struct. The same parameters in the parenthesis must be passed when creating an instance of the struct.
I want to create a Helper.swift file to add some functions/methods that are useful in different parts of my app.
I was wondering what is the best practice (if there is one): create a class and only create type methods or just create functions?
I would generally lean towards using a type methods on an appropriately named type, in order to give your helper methods context and avoid polluting the global namespace.
In Swift, structs are an ideal candidate for this sort of construct:
struct Helper {
static func helpfulMethod() { ... }
}
I also use embedded structs with static constants quite liberally in my top level types in order to group related constants within my code.
In writing custom Swift types, you should generally consider using structs first, and only resort to classes when inheritance, reference semantics (as opposed to the implicit copying with value semantics) or ownership semantics (unowned/weak) are required. In this case, your utility functions will be stateless, and there is no inheritance to speak of, so a struct should really be preferred over a class.
I would argue that in general, the Swift language is moving away from global functions in favour of the implicit namespacing provided by types (and protocols/generics). But it's still largely a matter of style/personal preference, and for something as simple as a utility function it's of little consequence.
It is not necessary to create a class or a struct. You can simply put the functions directly in Helper.swift file. And you dont even need to import this file by writing import statements.
To test it out create a file called helper.swift and just add the following lines of code to the file. No class or struct is required.
import Foundation
func addTwo(x: Int) {
return x+2
}
To use this function in any other file just call the function with the required arguments.
let a = addTwo(9)
I prefer this method because when you call the function then you dont have to call it on an instance of a class/struct. Secondly, it leads to cleaner code as you don't have to make each function a class function or a static function.
I will prefer type method because by this way you can easily differentiate your methods.
Suppose you have 50 to 60 methods in which some methods are for designing purpose, some methods are for calculation purpose and some methods are for getting and posting data on server.
Now in this scenario, if you create all these methods as globally it will become hard to recognise and remember.
Now if you differentiate this methods in some class/struct like below:
Methods which are use for Designing purpose make a DesignHelper class/struct and put all these methods into it as class/static method
Methods which are use for calculation purpose make a MathHelper class/struct and put all these method into it as class/static method
Methods which are use for process data with server make a ConnectionHelper class/struct and put all these method into it as class/static method
By using this way you can easily find out any of the method and it will also help in auto completion.
Thank you.
Class functions through a single class work but generally those functions that are being used throughout your app will reuccur on the same objects. A cleaner way is to define your functions in extensions of the object that will use the function. You could put all your extensions in Helper.swift
e.g.
extension UIColor
{
class func randomColor() -> UIColor
{
var randomRed:CGFloat = CGFloat(drand48())
var randomGreen:CGFloat = CGFloat(drand48())
var randomBlue:CGFloat = CGFloat(drand48())
return UIColor(red: randomRed, green: randomGreen, blue: randomBlue, alpha: 1.0)
}
}
with usage like this page.backgroundColor = UIColor.randomColor()
So you can still define your functions as class functions or object functions depending on the usage, but within the extension of the object.
This keeps your code clear so you dont route your calls through the helper throughout your code base. Its clearly defined for the object that will be needing the function. If you find code that does not make sense in an extended function then the function probably needs refactoring into more focused functionaly.
I don't know if it is the best practice but here is how I do it.
First I declare a protocol:
protocol UtilityType { }
Then I extend it (For example a utility function for UIViewController)
extension UtilityType where Self: UIViewController {
func setDefaultTitleAttributes() {
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
}
}
And I use it like this
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setDefaultTitleAttributes()
}
}
extension MyViewController: UtilityType {}
Solution #1:
class Helper {
class func classMethod() {
// TODO: play something
}
}
And call it:
Helper.classMethod()
In Apple doc:
Structures are always copied when they are passed around in your code, and do not use reference counting.
Solution #2:
struct Helper {
static func classMethod() {
// TODO: do something
}
}
And use it:
Helper.classMethod()
I think solution#2 better than solution#1 because it's not increase reference counting.
UPDATED: I tested with playground. See the result below:
Hope this helps!
I'm trying to build my first spritekit game in swift. I don't understand where to store constants so I can make them available to the whole project. I have some experience with C++ and I used to create a Constants.h file. Is there such thing in Swift? What's the recommended practice to do this?
Right now I'm using a struct with static constants but I'm not sure if it's the right way to do it:
struct Constants {
static let gravity : Int = 20
}
struct Constants {
static let buildName = "Orange-Pie"
struct FacebookConstants {
static let clientId ="asdasdsa"
}
struct TwitterConstants {
static let clientId ="asdasdsa"
}
}
Use :
Constants.FacebookConstants.clientId
If you have highly generic constants needed by every part of your program, this is indicating a design problem (whenever you are at a loss of where something should go, you probably have a design problem). Things like a gravitational constant shouldn't be necessary for the vast majority of the program, so they generally don't need to be global constants (that's true in C++, too).
Put your constants with the thing that needs that constant, or pass them into the thing that needs that constant. SpriteKit should do most gravity calculations for you, but if you're doing additional physics work, then there should be some object that represents the physics engine or "the world." That's where the gravity constant belongs. Alternately, put the gravity constant into a struct that you pass into the physics engine at launch.
Even if you do have very broad need of the gravitational constant, then you should put it into a struct like PhysicalConstants, not a generic Constants (which makes code reuse hard because it mixes unrelated things). A common case of this in my code are "style" constants like "the systemwide highlight color" (which are likely to be changed by the client, so I want a single place to modify them). These go into a header called Style.h in my apps, and now would go into a Style struct. But they're kept separate from non-style constants.
When I was at WWDC 2014, I asked an engineer the exact same thing. Their recommendation was to use your method to replace #define that we had in Objective-C. I agree that it's a suboptimal procedure and actual defining should be implemented in some way.
Also note that I don't think you need to explicitly state the type of your variable, as Swift has rather advanced type inference. So this should work:
struct Constants {
static let gravity = 20
}
struct Constants {
static let varName = "AnyValue"
}
Accessing to varName:
Constants.varName