Search Your Question

Showing posts with label Shoppers Stop. Show all posts
Showing posts with label Shoppers Stop. Show all posts

I have 100 cells. In each cell I have 5 button. How can I check which cell button is clicked?

Ans : 

There are various approach for this problem. But following two approach are better.

Approach-1 : Delegate - Protocol 

Cell : 

protocol CellSubclassDelegate: class {
    func buttonTapped(cell: CellSubclass)
}

class CellSubclass: UITableViewCell {

@IBOutlet var someButton: UIButton!

weak var delegate: CellSubclassDelegate?

override func prepareForReuse() {
    super.prepareForReuse()
    self.delegate = nil
}

@IBAction func someButtonTapped(sender: UIButton) {
    self.delegate?.buttonTapped(self)

}

ViewController:

class MyViewController: UIViewController, CellSubclassDelegate {

    @IBOutlet var tableview: UITableView!

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CellSubclass

        cell.delegate = self


    }

    func buttonTapped(cell: CellSubclass) {
        guard let indexPath = self.tableView.indexPathForCell(cell) else {
            // Note, this shouldn't happen - how did the user tap on a button that wasn't on screen?
            return
        }

        //  Do whatever you need to do with the indexPath

        print("Button tapped on row \(indexPath.row)")
    }


Approach-2 Using Closure:

Cell :

class MyCell: UITableViewCell {
    var button: UIButton!

    var buttonAction: ((Any) -> Void)?

    @objc func buttonPressed(sender: Any) {
        self.buttonAction?(sender)
    }

}


ViewController : 

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! MyCell
    cell.buttonAction = { sender in
        // Do whatever you want from your button here.
    }
    // OR
    cell.buttonAction = buttonPressed(closure: buttonAction, indexPath: indexPath) // <- Method on the view controller to handle button presses.

}

No need to explain code. Simple as that.

If you have any comment, question, or recommendation, feel free to post them in the comment section below!


Latest version of iOS, Swift, XCode

Ans : 
As per today (18-Oct-2018),

Latest version of

XCode : 10.0
Swift : 4.2
iOS : 12.0
Mac OS : mojave 10.14
Objective C : 2.0

I am using XCode 9.3, Swift 3.0, iOS 11 and mac os as High sierra.

Swift Version History :

DateVersion
2014-09-09Swift 1.0
2014-10-22Swift 1.1
2015-04-08Swift 1.2
2015-09-21Swift 2.0
2016-09-13Swift 3.0
2017-09-19Swift 4.0
2018-03-29Swift 4.1
2018-09-17Swift 4.2



What is @escaping and @nonescaping in swfit?

Ans : 

Closure : Closure are self contained blocks of functionality that can be passed around and used in code.


In swift 1.x and 2.x, closure parameter is @escaping by default. It means closure can be escape during function body execution. If don't want to escape, we have to mention @nonescaping as parameter.

In swift 3.x and after, closure parameter is @nonescaping by default.
Life cycle of non-escaping closure
Basically, a non-escape closure can only run the contents inside of it’s body, anything outside of it’s closure cannot be used. A non-escape closure tells the complier that the closure you pass in will be executed within the body of that function and nowhere else. When the function ends, the closure will no longer exist in memory. For example, if we needed to extract any values within our closure to be used outside of it, we may not do so. During the earlier days of Swift, closure parameters were escaping by default. Due to better memory management and optimizations, Swift has changed all closures to be non-escaping by default.

var closuresArray: [() -> Void] = []
func doClosures(completion: () -> Void){
completionHandlers.append(completion)
}
//ERROR!!!
passing non-escaping parameter 'completion' to function expecting an @escaping closure

Here is an example of an non-escaping closure. Here we have an empty array of closure and a function that includes a closure. If we were to append the closure in the function to the array of closure, we cannot do so because it is defaulted to non-escape. One great thing about Xcode is that it will that you that you need an escaping closure and can implement it for you.
Escaping Closure : 
Essentially escaping closure is the opposite of non-escaping closure. An escaping closure grants the ability of the closure to outlive the function and can be stored elsewhere. By using escape closure, the closure will have existence in memory until all of it’s content have been executed. To implement escaping closure, all we have to do is put @escaping in front of our closure. If you are unsure whether your closure needs escaping, no worries, as I’ve said before the complier is smart enough to let you know.
There are several ways when we need to implement an escaping closure. One instance is when we use asynchronous execution. When we are dealing with dispatch queue, the queue will hold onto the closure for you, and when the queue is done completing its work, then it will return back to the closure and complete it. Since dispatch queue is outside of the scope, we need to use escaping closure. Another instance is when we need to store our closure to a global variable, property, or any bit of storage that lives on past the function.

Always remember to use weak self while using a closure.

Optional, Optional Binding, Unwrapping and Optional Chaining

Ans : 

Optional : Optional is swift's powerful feature which come to solve problem of  non-existing value. It is just a type . There are two types as Int (which must has a value) and Int?(which may contain a Int value or may have nil value). It is declared as T? i.e Int?, String?

Forced Unwrapping : Exclamation mark ( ! ) is used to unwrap value.
i.e let optionalInt : Int? = 5
let intVal : Int = 2
optionalInt! + intVal

So we hvae forecfully unwrap optionaInt. That means we tell compiler that optionalInt has a value and extract and use it.

But this is not good practise. If sometimes optionaInt has not value and we try to unwrap, then app will be crashed. A good practise is to check with nil before unwrapping or use optional binding. It checks it has value or not and if and only if it has value extract it and use it.

Optional Binding : You use optional binding to check if the optional contains a value or not. If it does contain a value, unwrap it and put it into a temporary constant or variable.

Example :

var stockCode:String? = findStockCode("Facebook")

let text = "Stock Code - "

if let tempStockCode = stockCode {

    let message = text + tempStockCode

    println(message)
}

The “if let” (or “if var”) are the two keywords of optional binding. In plain English, the code says “If stockCode contains a value, unwrap it, set its value to tempStockCode and execute the conditional block. Otherwise, just skip it the block”. As the tempStockCode is a new constant, you no longer need to use the ! suffix to access its value.

Implicitly Unwrapped Optional : When we are very very sure about it has value after first time it is set, then we need not unwrap every time. So for this type of scenario, we have to use it with ! mark in their type.

// forced unwrapping
let optionalInt: Int? = 123
let forcedInt: Int = optionalInt!

// implicitly unwrapped optional
let assumedInt: Int! = 123
let implicitInt: Int = assumedInt

It may has nil value.

Optional Chaining :

The feature allows us to chain multiple optionals together with the “?.” operator.


if let sharePrice = findStockCode("Apple")?.price {

    let totalCost = sharePrice * 100

    println(totalCost)

}

FindstockCode method returns optional value. We can access multiple optional together using Optional chaining feature.

Dynamically set UITableview cell height

Ans : 

For auto cell height in tableview in Swift 3.0

Write following 2 lines of code in viewDidLoad and before reload tableview :

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44

Following steps must to do otherwise label height will not be increase and so UITableiViewCell.

Label height must be auto incremented using numberOfLines = 0

LineBreak should be set according your need word-wrap, char-wrap, etc...

What is extension and How to use it?

Ans :
Swift Extension :

Add a new swift file with File > New > File... > iOS > Source > Swift File, but you can call them what you want.
The general naming convention is to call it TypeName+NewFunctionality.swift

Make extension of Double

Double+Conversions.swift

import Swift // or Foundation

extension Double {

    func celToFahren() -> Double {
        return self * 9 / 5 + 32
    }

    func fahrenToCel() -> Double {
        return (self - 32) * 5 / 9
    }
}

How to make extension:

let boilingPointCel = 100.0
let boilingPointFaren = boilingPointCel.celToFahren()
print(boilingPointFaren) // 212.0

Make extension of UIColor

UIColor+CustomColor.swift

import UIKit

extension UIColor {

    class var customGreen: UIColor {
        let darkGreen = 0x008110
        return UIColor.rgb(fromHex: darkGreen)
    }

    class func rgb(fromHex: Int) -> UIColor {

        let red =   CGFloat((fromHex & 0xFF0000) >> 16) / 0xFF
        let green = CGFloat((fromHex & 0x00FF00) >> 8) / 0xFF
        let blue =  CGFloat(fromHex & 0x0000FF) / 0xFF
        let alpha = CGFloat(1.0)

        return UIColor(red: red, green: green, blue: blue, alpha: alpha)
    }

}
See here also.

Using extension :

view.backgroundColor = UIColor.customGreen

Summary : Once you define an extension it can be used anywhere in your app just like the built in class functions. In Objective-C extensions are known as categories.

Objective C Extension : 

In objective c, when you want to make behavior of some property private you use class extension.
-> it comes with .m file only.
-> mainly for properties.
The implementation of the extension must be in the main @implementation block of the file.
Extension can only be added to the classes whose source code is available because compiler compile the source code and extension at same time.