iOS | Bounds vs Frame ?

Everyone talk about bounds and frame during the interview for sure. lets make it little easy.

The Bounds of a view is recentagle, expressed as location coordinates (x,y) and also the size (height, width) relative to the own coordinate system.

The Frame of a view is recentagle, expressed as location coordinates (x,y) and also the size (height, width) relative to the its superview.

So for example lets say if you have UILabel on top of your UIView that has size of (100×100) with thelocation coordinates (10,10). so here is the Swift code.

override func viewDidLoad() {
        super.viewDidLoad()

        //Bounds
        print("label.bounds.origin.x    = \(label.bounds.origin.x)")
        print("label.bounds.origin.y    = \(label.bounds.origin.y)")
        print("label.bounds.size.height = \(label.bounds.size.height)")
        print("label.bounds.size.width  = \(label.bounds.size.width)")

        //Frame
        print("label.frame.origin.x    = \(label.frame.origin.x)")
        print("label.frame.origin.y    = \(label.frame.origin.y)")
        print("label.frame.size.height = \(label.frame.size.height)")
        print("label.frame.size.width  = \(label.frame.size.width)")
    }

So for the both cases size(height, width) will be same only the position (x,y) will be different as in case of bounds its relative to its own view and for frame its relative to superview. for more please see the below image(source: slideshare, CS 193P lecture).

Screen Shot 2017-05-17 at 11.12.59 AM

Properties | Swift | iOS | Stored

Properties associate value with a paticular class, structure or enumeration. Stored Properties (provided by class, struct and enum) store constant and variable values as part of instance, whereas Computed Properties (provided by class and struct only) calculate a value. Properties can also be associated with type itself its called Type Properties. Apart from that we can add observers to monitor the changes in a property’s value there you can response to your custom actions, we can add it to Stored Properties and also property that a subclass.

Stored Properties

Simplest form, its a constant or variable that is stored as a part of an instance of a particuler class, struct or enum.

struct Box  {
    var height  : Int
    let width   : Int
}

var box1 = Box(height: 101, width: 10)

It can be either Variable stored property (introduced by var) or Constant stored property(introduced by let). if its Variable stored property than we can set initial value during initialization and if Constant stored property without default value than yes as well.

Lazy Stored Properties

Whose initial values is not calculated until the first time it is used. they are useful when the initial value for a property is dependent on other factors or sometime if the initial value for a property requires complex or computationally expensive setup that should not be performed unless it is needed.

class DataImporter  {
    /*
     This class is responsible for fetching and holding the file data.
    */
    var fileName = "data.json"
}

class DataManager   {
    var data = [String]()
    lazy var importer = DataImporter()
}

let dManager = DataManager()
dManager.data.append("One")
dManager.data.append("two")

Now here the interseting part is till now importer property is not created. because is marked as lazy so the property is only created when the importer property is first accessed.

 

Subscripts in Swift ?

Shortest way to access the member elements of collection, list or sequence, means there is no need to create saparate function. lets say you have an array so you can write subscripts for setting and retrieving the value by index. Sounds good ???

Another good thing is we can define number of subscripts based on the type of index value we pass, even we can define subscripts with multiple input parameters, so its all to our need.

The syntax is very much similar to stored property and functions. Just we need to write subscript keyword and specify one or more input paramters and reture type. like the methods subscripts are also read-write or readonly. This behaviour is communicated by the same way we do in computed properties. 

subscript(index: Int) -> Int    {
    get {
        //return value here
    } set(newValue) {
        //set the new value here
    }
}

the usage is to access the member elements in a collection, list or sequence. For example, Swift’s Dictionary instance. You can set and get the value using Key. if they key does’t exist it will add into the Dictionary.

var priorities = ["Work" : 3, "Family" : 1, "Other" : 4]
priorities["Work"] = 2

Swift’s Dictionary type implements its key-value subscripting, its takes and returns an optional value. if you set the value as nil it’ll remove from Dictionary.

priorities["Work"] = nil

the interseting part what i like is subscripts can take any types of values, n number of value and can return any type of value, but they can’t use in-out parameters and can’t provide default parameters value.

struct Matrix {
    let rows: Int, columns : Int
    var grid : [Double]

    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        grid = Array(repeating: 0.0, count: rows * columns)
    }

    private func isValidIndex(row: Int, column: Int) -> Bool    {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }  

    subscript (row: Int, column: Int) -> Double  {
        get {
            assert(isValidIndex(row: row, column: column))
            return grid[(row * column) + column]
        } set {
            assert(isValidIndex(row: row, column: column))
            grid[(row * column) + column] = newValue
        }
    }
}

var matrix = Matrix(rows: 2, columns: 2)
matrix[1, 1] = 10.0

print(matrix[1, 1])

Any VS AnyObject ? Swift

Swift provides two typealiases for working with non specific types. In simple words we can say.

AnyObject

it can represent an instance of any class type.

Any

it can represent an instance of any type at all, including function types.

But here i want to mention that Apple warns to use Any and AnyObject only when you explicity need the behaviour because it always good to be more specific about the types what you are expecting in your code.

class MyClass   {   }

var things = [Any]()
things.append("String")
things.append(9)
things.append(2.0)
things.append(MyClass())

This things arrays contains IntString, Double and Class as well. Complier convert the Objective C id type into AnyObject since they are class type. Now to discover the specific type of constant and variable, we can use is or as pattern in switch statement cases.

for thing in things {
    switch thing {
        case let someInt as Int:
        print("Some Int Value is there \(someInt)")

    case let someString as String:
        print("Some String Value is there \(someString)")

    case let someFloat as Double:
        print("Some Double Value is there \(someFloat)")
      
    case let someClass as MyClass:
        print("MyClass Class is there")

    default:
        print("Unknown")
    }
}

So summary is Any type represents value of any type including optional types but complier will give you the warning if you really want to use than use as optional value as an Any value.

things.append(optionalNumber as Any)

Failable Numeric Conversion Initializers | Swift 3.1

Swift 3.1 implements failable initializers for all numeric types like Int, Int8, Int16, Int32, UInt, UInt8, UInt16, UInt32, Float, Float80, Double. So which either completely successful without loss of information or simply returns nil.

This feature is very useful let’s see an example.

typealias JSONDictionary = [String: AnyObject]
class Employee  {
    let name: String
    let level: Double
    init?(json: JSONDictionary) {
       guard   let name = json["name"] as? String,
           let levelString = json["level"] as? String,
            let levelDouble = Double(levelString),
            let level = Int(exactly: levelDouble)  // 3.1 feature here
            else {
                return nil
        }
        self.name = name
        self.level = level
    }
}

func getEmployees(from data: Data) -> [Employee]?   {
    guard let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments),
        let jsonArray = json as? [JSONDictionary]   else {
            return nil
    }

    return jsonArray.flatMap(Employee.init)
}

let jsonString = "[{\"name\":\"John\", \"level\":\"7.2\"}]"
if let data = jsonString.data(using: .utf8) {
    let employees = getEmployees(from: data)
    print(employees ?? "its Nil")
} else {
    print("Data Nil")
}