Showing posts with label swift4. Show all posts
Showing posts with label swift4. Show all posts

Friday, September 14, 2018

fileprivate to private


In Swift 3, If we need to access private stuff of a class in extension, we need to change the access specifier from private to fileprivate.


     
  class User {
    
    private var name: String
    private var id: Int
    
    init(name: String, id: Int) {
        self.name = name
        self.id = id
    }
    
    private var greeting: String {
        get {
            return "Hi \(name)"
        }
        set(v) {
            name = v
        }
    }
    
 }

 extension User {
    func greetUser() {
        print(greeting)
    }
 } 



Swift 3 gives build error for below as greeting is private. 



     
  extension User {
    func greetUser() {
        print(greeting)
    }
  }



It should be marked as fileprivate which makes it accessible to others which are inside a file which may not be we wanted most of the times.

Swift 4, makes it appropriate based on their name.

private is not at all accessible outside even with in the same file.

fileprivate is accessible only with in the file, Not accessible outside of a file.

If greeting is with in the same file where User class is there, It doesn’t matter If it’s fileprivate or private to access it in a User extension with in the same file. But, careful with fileprivate cause it is accessible with in the same file. 


     
  class User {
    
    private var name: String
    private var id: Int
    
    init(name: String, id: Int) {
        self.name = name
        self.id = id
    }
    
    fileprivate var greeting: String {
        get {
            return "Hi \(name)"
        }
        set(v) {
            name = v
        }
    }
    
 }

 extension User {
    func greetUser() {
        print(greeting)
    }
 }



If you are writing extension of User in another file, You can not access it If it’s fileprivate or private.

Extension outside of file,


     
  extension User {
    func greetUser() {
        print(greeting)
    }
  }



fileprivate build error - 'greeting' is inaccessible due to 'fileprivate' protection level

private build error - 'greeting' is inaccessible due to 'private' protection level


That’s how Swift 4, make both the access specifiers clear based on their name. 

Glad, It’s not confusing now like in Swift 3.

Swift 3, fileprivate -  If you need access throughout the file even in extensions (private gives build error in extensions)

Swift 3, private - Not accessible outside the model scope even in the extension which is there in same file.

Swift 4, fileprivate - If you need access throughout the file.

Swift 4, private - Accessible in extensions If they are in the same file. Not accessible for all remaining cases.

Take Aways - 

In Swift 4, We don’t need to change fileprivate access for a property/method to private to access that in the extension in the same file.


Hope this post is useful. Feel free to comment incase of any queries.


Wednesday, November 8, 2017

Swift 4 - Method ‘initailize()’ defines Objective-C class method ‘initialize’, which is not guaranteed to be invoked by Swift and will be disallowed in future versions

In earlier swift versions (3x), We can override initialize() method of a class which gives you a compile time warning like shown below.






In latest Xcode 9 and above, We can set the Swift the version.








It is clearly saying that, The support will be disallowed in future.

So, From Swift 4, We are not suppose to override Objective-C class method initialize(), Which gives build error like shown below.

Method ‘initialize()’ defines Objective-C class method ‘initialize’, which is not permitted by Swift.















Swift 3 versions warning became error in Swift 4. 


In this post let’s see the alternate approach to get rid of this build error.

Like In my earlier Method Swizzling posts, If need something needs to be executed like Method swizzling in Swift, We can write that in method and call that in AppDelegate didFinishLaunchWithOptions


----------------------------------------------------------------------------------------------------------

    static func swizzleViewWillAppear() {
        if self != UIViewController.self {
            return
        }
        let _: () = {
            let originalSelector = #selector(UIViewController.viewWillAppear(_:))
            let swizzledSelector = #selector(UIViewController.newViewWillAppear(_:))
            let originalMethod = class_getInstanceMethod(self, originalSelector)
            let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
            method_exchangeImplementations(originalMethod!, swizzledMethod!);
        }()
    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions 
                         launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        UIViewController.swizzleViewWillAppear()
        return true
    }

----------------------------------------------------------------------------------------------------------

The only extra step is we need to call that method explicitly to get it applied, Whereas using initialize() like in earlier versions, we don’t need to as initialize() will get called automatically.

Hope this post is useful. Feel free to comment incase of any queries.



Saturday, October 21, 2017

Interface Segregation Principle in SOLID (Object-Oriented Design)

In this post, Let’s discuss ISP (Interface Segregation Principle) which is one of the SOLID principles of OOP design.

S  - Single Responsibility Principle
O - Open/Closed Principle
L  - Liskov Substitution Principle
I   - Interface Segregation Principle
D  - Dependency Inversion Principle

The Interface-segregation principle states that no client should be forced to depend on methods it does not use. ISP splits interfaces that are very large into smaller and more specific ones so that client will only have to know about the methods that are of interest to them. Such shrunken interfaces are also called as role interfaces.
  • Courtesy wikipedia.org

I am going to use Xcode9 and Swift 4 for the example ion this post.

Let’s take a Vehicle protocol, having necessary methods for vehicles.

  
    protocol VehicleProtocol {

        func numberOfGears() -> Int
        func isGearedOne() -> Bool
        func numberOfTyres() -> Int
    
        func start()
        func stop()    

    }


Let’s take a Car class which confirms to this protocol.

  
  class Car: VehicleProtocol  {

      func numberOfTyres() -> Int {
          return 4
      }
    
      func numberOfGears() -> Int {
          return 5
      }
    
      func isGearedOne() -> Bool {
          return true
      }
    
      func start() {
          print("starting off in first gear")
      }
    
      func stop() {
          print("stopping off in first gear")
      }
    
  }


For car, These all methods looks and fits good.

Whereas, Take a Horse class, 

  
   class Horse: VehicleProtocol  {

      func numberOfTyres() -> Int {
          return 4
      }
    
      func numberOfGears() -> Int {
          return 5
      }
    
      func isGearedOne() -> Bool {
          return true
      }
    
      func start() {
          print("starting off in first gear")
      }
    
      func stop() {
          print("stopping off in first gear")
      }
    
  }



For which below protocol methods looks very odd.

  1. numberOfGears
  2. isGearedOne
  3. numberOfTyres


If we ignore those protocols, You will end up with Build errors as shown below.



Here comes the ISP principle, Let me bring that again,

The Interface-segregation principle states that no client should be forced to depend on methods it does not use. ISP splits interfaces that are very large into smaller and more specific ones so that client will only have to know about the methods that are of interest to them. Such shrunken interfaces are also called as role interfaces.
  • Courtesy wikipedia.org

Let’s solve the above Horse scenario as per this principle.

I will separate VehicleProtocol into 2 different protocols based on their role as per the ISP principle.

  
   protocol VehicleData {

        func numberOfGears() -> Int
        func isGearedOne() -> Bool
        func numberOfTyres() -> Int
    
    }

   protocol VehicleActions {
    
        func start()
        func stop()
    
    }


VehicleData protocol’s role is to get the data of the vehicle
VehicleActions protocol’s role is to take the actions of the vehicle.

That’s how we have split a large interface into 2 small interfaces based on the role.

So now, Car can confirm to both VehicleData and VehicleActions,
Horse can confirm to VehicleActions.


  
  class Car: VehicleData, VehicleActions  {

    func numberOfTyres() -> Int {
        return 4
    }
    
    func numberOfGears() -> Int {
        return 5
    }
    
    func isGearedOne() -> Bool {
        return true
    }
    
    func start() {
        print("starting off in first gear")
    }
    
    func stop() {
        print("stopping off in first gear")
    }
    
  }

  class Horse: VehicleActions {
    
    func start() {
        print("started running")
    }
    
    func stop() {
        print("stopped running")
    }
    
  }


Now, You must have got an idea of why iOS is having two separate UITableView protocols, One for DataSource and one for Delegate :)

UITableViewDataSource
UITableViewDelegate

If you are not worried by the cell selections, You can ignore the UITableViewDelegate.

Hope this post is useful. Feel free to comment incase of any queries.


Sunday, October 8, 2017

Swift 4 NEW Tutorial-3 (private instead of fileprivate)

In Swift 3, To access a private property in the extension in the same file, We need to specify it as fileprivate.

------------------------------------------------------------------------------------

class Vehicle {
    fileprivate var name = "BMW"
}

extension Vehicle {
    func strat() {
        print("Stating \(name)")
    }
    
    func stop() {
        print("Stopping \(name)")
    }
}

------------------------------------------------------------------------------------

Swift 4 solved this and we can access all the private properties in all the extensions of the class with in the same file.

------------------------------------------------------------------------------------

class Vehicle {
    private var name = "BMW"
}

extension Vehicle {
    func strat() {
        print("Stating \(name)")
    }
    
    func stop() {
        print("Stopping \(name)")
    }
}

------------------------------------------------------------------------------------


Hope this post is useful. Feel free to comment incase of any queries.


Swift 4 NEW Tutorial-2 (Strings are Collections Again)

Prior to Swift 3, Strings are collection types, Now again in Swift 4 they are collections.

Swift 3 

-------------------------------------------------------------------------

var str = “Hello World!”
str.characters.count
str.characters.append(“appending….”)

-------------------------------------------------------------------------

Swift 4 

-------------------------------------------------------------------------

var str = “iOS Solves”
str.count        // 10
str.append(“ Blog”)      // iOS Solves Blog

-------------------------------------------------------------------------

Multiline strings :-

Swift 3

let name = “name1 \n name2 \n name3”

Output:

name1
name2
name3

Swift 4

Use 3 double quotes to specify it as a multiline string.

-------------------------------------------------------------------------

let name = “””
name1
name2
name3
“””

Output:

name1
name2
name3

-------------------------------------------------------------------------

Use spaces for indentation

-------------------------------------------------------------------------

let name = “””
  name1
  name2
  name3
“””

Output:

  name1
  name2
  name3

-------------------------------------------------------------------------

Hope this post is useful. Feel free to comment incase of any queries.