Saturday, May 7, 2016

Overriding methods in swift is neat

Swift is really very powerful language, but for developers coming from other OO languages it might be a bit tricky sometimes (for example: absence of abstract classes) and sometimes has neat features for which developers usually don't know util they come to the problem. One of such things is method overriding - it works the same way for procedures (void)  and functions (return value). For easier demonstration purposes in playgrounds functions will be used.
Methods can be distinguished as follows:
instance methods: can be called on instance. Unless the method has final keyword in the declaration it can be overridden in the child class (subclass).
static methods: can be called on class. This methods are internally marked as final, so they cannot be overridden by the child class (subclass).
class methods: can be called on class. Unless the method has final keyword in the declaration it can be overridden in the child class (subclass).
class Parent {

 // Multiplies input parameter by 100
 func instanceFunction(parameter: Int) -> Int {
  return parameter * 100
 }

 // Subscracts from input parameter 10 (class function)
 static func staticFunction(parameter: Int) -> Int {
  return parameter - 10
 }

 // Multiplies parameters with itself
 class func classFunction(parameter: Int) -> Int {
  return parameter * parameter
 }
}

class Child : Parent {

 // Multiplies input parameter by 100 (call to parent) and substracts 100
 override func instanceFunction(parameter: Int) -> Int {
  let result = super.instanceFunction(parameter)
  return result - 100
 }

 // Static functions are final so this is not possible - solution?
 /*override static func staticFunction(parameter: Int) -> Int {
  return result - 9
 }*/

 // Multiplies parameter with itself and substracts 1
 override class func classFunction(parameter: Int) -> Int {
  let result = super.classFunction(10)
  return result - 1
 }
}

// Instance functions override
let parent = Parent()
let child = Child()

print(parent.instanceFunction(10))
print(child.instanceFunction(10))

// Static functions override
print(Parent.staticFunction(10))
print(Child.staticFunction(10)) // Call the same implementation ...

// Class functions override
print(Parent.classFunction(10))
print(Child.classFunction(10))


There are interesting consequences of the example code from above:
  • to prevent overriding of instance or class (marked with class) methods use final keyword
  • class method marked as final behaves the same way as static method
  • when using OO principles it happens many times that we override method of parent class. In the overridden method (in child) so often also call method of parent (super-class). The interesting thing is, that this can be done for instance and class methods by using the same reserved word - super. The only thing I am asking myself is, why having static and class methods, if the same behaviour can be achieved by using class methods...
The possibility of overriding class methods is Swift's very neat feature - it is not supported in all popular languages, for example in Java. In Java we have only static methods and static method with the same name can be defined in both parent and subclass, but this is not real overriding. It is also not possible to invoke method of the parent class via super (for static methods only) without hardcoding the class name. Please note: Java has tremendously powerful reflection API and via it - it is possible to solve this problem, but this is not something what you would like to use on daily basis :) 
public class Parent {
  
  public static int staticFunction(int parameter) {
    
    return parameter * parameter;
  }
}

public class Child extends Parent {
    
  public static int staticFunction(int parameter) {
    
    int result = Parent.staticFunction(parameter);
    return result - 1;
  }
}

Monday, March 28, 2016

Embed UITableViewController into another UIViewController using Storyboard

I have been recently asked to implement side menu with static cells using TableView* + adding some elements on the screen. My initial implementation idea was using to add TableView with other UI components in UIViewController. It turned out that using TableView (not the TableViewController) does not support static cells (the xCode complains - the project does not even compile). So the UITableViewController must be used. 
Actually the solution is very simple, but you must be aware of it:
  1. implement your screen where the TableViewController should be - add any other UI elements to the screen. For the place where you want to have the UITableViewController search for ContainerView and add it to the screen (feel free to add any auto-layout, constraints there)
  2. add UITableViewController to the storyboard - next to you ViewController. Configure it as you wish
  3. select ContainerView, hold CTRL + click and create segue to the TableViewController. From the dropdown menu choose the embed segue. Run the app and voila - TableViewController is inside the first screen :)
  4. feel free to check the demo here: https://github.com/leondobnik/EmbeedTVCDemo.git
Storyboard solution of embedding
The result - UITableViewController inside UIViewController