Install uninstall cocoapods in your iOS Swift app

Cocoapods are third-party libraries that help you do some of the work in your app for you saving your time. These Cocoapods are built with Ruby and is installable with the built-in Ruby on your Mac OS. Search for your required Cocoapod here.

First install on your macOS using the below command in your Mac terminal:

$ sudo gem install cocoapods

Your installed gems list may be a lot longer than shown above as I’ve already installed before.

Next, setup pods with:

$ pods setup --verbose

–verbose is optional, it’ll just show you the progress of the setup.

Once, the setup is completed, let’s install the individual cocoapods. Navigate to the folder of your Project and create the pod file. And then open it for editing with the following commands:

$ cd myapp

$ pod init

$ open -a Xcode podfile

Make changes to your podfile similar to shown above after uncommenting/removing a few lines. The first line tells the minimum supported iOS platform. The general rule of the thumb is to support the last 2 iOS releases. The target is the name of your project.

use_frameworks is required for Swift Projects. The provide the list of pods inside the do block which are required for your app. Make sure the name is correct as selected from the Cocoapods.org site. Please do check if the pods you’re using is well maintained and when was the last time it was updated. Should not be like last updated 4-5 years ago is not a good sign.

Once your changes are done, save the file and run the below command while within the app folder:

$ pod install

From now on, you would want to open your project in Xcode using .xcworkspace in your Project folder instead of .xcodeproj.

To use the pod in your project, just import the pod using the import statement in your class and you can use it as per the documentation e.g.

import VENTokenField
import SVProgressHUD

To uninstall and clean your Project completely from CocoaPods, run the following commands:

$ sudo gem install cocoapods-deintegrate cocoapods-clean
$ pod deintegrate && pod clean
$ rm Podfile
Advertisement

Add placeholder to UITextView Swift

There are instances where we need to use UITextView as a multi-line text field in our app. The UITextView does not provide a placeholder property like the UITextField. So, in order to achieve this we need to implement the following methods in our UIViewController:

class DemoVC: UIViewController, UITextViewDelegate {

//hook this to the storyboard UITextView
@IBOutlet weak var descriptionTxtView: UITextView!

func textViewDidBeginEditing(_ textView: UITextView) {
        if descriptionTxtView.text == "Add description..." {
            descriptionTxtView.text = ""
            descriptionTxtView.textColor = UIColor.black
        }
    }
    
    func textViewDidEndEditing(_ textView: UITextView) {
        if descriptionTxtView.text == "" {
            descriptionTxtView.text = "Add description..."
            descriptionTxtView.textColor = #colorLiteral(red: 0.4922404289, green: 0.7722371817, blue: 0.4631441236, alpha: 1)
        }
    }

}

Please note in the above code that the View Controller class also conforms to the UITextViewDelegate. All of the methods in the protocol are optional, however use them to adjust the text as needed.

The above code is implemented using Swift 4.

Add and delete rows in UITableView Swift

In this post, we’ll discuss the scenario where we need to add or remove rows from a UITableView in Swift. Below are the parts of code required in the ViewController to achieve this.

First, we need to create the Outlet for the UITableView:

class NewRecipeVC: UIViewController, UITableViewDelegate, UITableViewDataSource {

// don't forget to hook this up from the storyboard
@IBOutlet weak var newRecipeTableView: UITableView!

//hook this to the textbox to add the ingredient
@IBOutlet weak var ingredientTxt: UITextField!

//This array holds the ingredients
var ingredients = ["1 slice lemon","1 table spoon Sugar","1 glass Water","1 spoon Rock Salt"]

//hook this to a button
@IBAction func addIngredient(_ sender: Any) {
        if ingredientTxt.text != "" {
            ingredients.append(ingredientTxt.text!)
        
            let indexPath = IndexPath(row: ingredients.count - 1, section: 0)
            newRecipeTableView.beginUpdates()
            newRecipeTableView.insertRows(at: [indexPath], with: .automatic)
            newRecipeTableView.endUpdates()
        
            ingredientTxt.text = ""
            view.endEditing(true)

        }
        else {
            let alert = UIAlertController(title: "Missing!", message: "Missing ingredient...", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
    }

}

Deleting a row requires the commit editing style method as shown below. This method allows you to right to left swipe on the row and get the delete button option.

extension NewRecipeVC {    

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        
        if editingStyle == .delete {
            ingredients.remove(at: indexPath.row)
            newRecipeTableView.beginUpdates()
            newRecipeTableView.deleteRows(at: [indexPath], with: .automatic)
            newRecipeTableView.endUpdates()
        }
    }

}

Below are some methods that are used and are defined as per Apple documentation:

beginUpdates(): Begins a series of method calls that insert, delete, or select rows and sections of the table view.

insertRows(): Inserts rows in the table view at the locations identified by an array of index paths, with an option to animate the insertion.

deleteRows(): Deletes the rows specified by an array of index paths, with an option to animate the deletion.

endUpdates(): Concludes a series of method calls that insert, delete, select, or reload rows and sections of the table view.

Implement follow unfollow button with mutating function Swift

To modify the properties of a value type, you have to use the mutating keyword in the instance method. This keyword gives your method can then have the ability to mutate the values of the properties and write it back to the original structure when the method implementation ends.

Add follow button as shown in the UIViewController below inside the UITableView Prototype cell.

Add Protocol Togglable.swift:

protocol Togglable {
    mutating func toggle()
}

Add FollowStatus.swift class with the below code that implements Togglable Protocol:

enum FollowStatus: Togglable {
    case follow, unfollow
    
    mutating func toggle() {
        switch self {
            case .follow:
                self = .unfollow
            case .unfollow:
                self = .follow
        }
    }
}

Inside the UITableViewCell class, add the follow Action method:

class TableViewCellClass: UITableViewCell {
    @IBOutlet weak var followBtn: UIButton!
    var followStatus: FollowStatus = .follow

    @IBAction func followBtnTapped(_ sender: Any) {        
        followStatus.toggle()
        if followStatus == .unfollow{
            followBtn?.setTitle("unfollow",for: .normal)
        }
        else {
            followBtn?.setTitle("follow",for: .normal)
        }
    }
}

Run the App and test clicking the button to see the status of the button changing between follow/unfollow.

Using Xcode version 10.1.

Implement Safe area guidelines for iPhone X and above

I recently faced a very common problem of supporting the App interface to the new iPhones X and above. The top label in the App was hiding behind the status bar not adapting properly to the interface of the iPhone X.

Safe area layout guide provided by Apple is a no coding solution to this problem. Select the Storyboard and on the File Inspector, check the “Use Safe Area Layout Guides” checkbox.

Next, select the label from the Storyboard and edit the top alignment constraint by changing the second item to Safe Area instead of Super View.

Running the App, will make the Top label appear below the status bar on the iPhone X and above as shown below.

Using Xcode version 10.1.

Add UIPickerView to ViewController in Swift

  1. Drag-drop UIPickerView component on to the View Controller.

    2. Create a Swift class and add it to the ViewController.

     3. Add the below code to the class:

 Control-drag the reference for the UIPickerView in the PickerVC class.
class PickerVC: UIViewController {
    @IBOutlet weak var categoryPicker: UIPickerView!
    var categories = ["Indian", "Mexican", "American", "Chinese"]

    override func viewDidLoad() {
        super.viewDidLoad()
        //Set the ViewController as the DataSource and Delegate    for the Category Picker.
        categoryPicker.dataSource = self
        categoryPicker.delegate = self
    }
}

Implement the below functions for UIPickerViewDataSource and UIPickerViewDelegate
extension PickerVC: UIPickerViewDataSource, UIPickerViewDelegate {
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return categories.count
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return categories[row]
    }
}

Using Xcode Version 10.1

Add UIScrollView to ViewController

  1. Create a Swift Project using Single view template.
  2. Add a ViewController to the Storyboard.
  3. Add ScrollView to the ViewController with Constraints set 0 for top, left, bottom and right. Leave space for the status bar at the top.scrollview
  4. Add a View on top of the Scroll View. Set height of the say to 1000 and the constraints as shown.                        viewuponscroller
  5. Control drag from inner View to the main View as shown below and select equal widths.                                                                          equal widths
  6. Select the ViewController and set the simulated size to freeform.freeform
  7. Set the height of the ViewController to 1000 same as set for the inner view.freeform height

You can then adjust your components over the UIScrollView normally using auto-layout.

When to present a ViewController programatically

While working on my app, I came across this scenario where I have a ViewController containing a UITableView. The UITableViewCell has a UIImage, tapping which opens another ViewController that presents a list of images to be selected. Phew…!!

To segue or not to segue!

Firstly, I tried adding a segue from the First VC to the Second VC. Calling a method when tapping UITapGestureRecognizer and then calling performSegue method:

performSegue(withIdentifier: "chooseicon", sender: sender)

and then:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) { ...}

But that opens the Second VC even if I tap anywhere on the UITableViewCell.

I wanted the Second VC to be opened only when tapping the image in the cell, so in this scenario, I did not use segue and instead use Present for the new VC inside the Tap gesture method as shown in the Safe Present method:

if let iconVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "IconPickerVC") as? IconPickerVC
{
present(iconVC, animated: true, completion: {
iconVC.delegate = self
})
}

IconPickerVC is the second VC with the identity added in the Main.Storyboard as shown below:

IconPickerVC identity

You need to use Push when you’re using NavigationController. If you do not use NavigationController, simply use the Present way.

If you need to know how I set the image from the Second VC to the UITableViewCell of the First VC, check my post here.

Return selected image to Previous ViewController

A very common scenario in an iOS App is to open another ViewController from one ViewController and return the value of the selected row to the previous ViewController and set the image e.g. setting an icon on the First ViewController.

You can perform the following steps to achieve this scenario:

1. Add a delegate variable on your second view controller. Please name it delegateand not Delegate as per naming convention.

weak var delegate: FirstVC?

2. Add functions to the First ViewController or create a protocol that the FirstVC will adhere to and that you want your second view controller delegate variable to perform.

extension FirstVC {
func selectedImage(_ imageName : UIImage) {
iconName = imgName
//Implement the logic to set image.
}
}

3. While pushing second view from first view controller, set your first view controller as delegate of second view controller. Something like this:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "chooseicon" {
if let iconVC = segue.destination as? SecondVC {
iconVC.delegate = self
}
}
}

4. In your second view controller once image is selected call delegate of second view controller. e.g. use didSelectRowAt of UITableViewController as shown below:

let icons = [ "img1",  "img2",  "img3"]

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.delegate?.setSelectedImage(icons[indexPath.row])
self.dismiss(animated: true, completion: nil)
}

5. Implement logic for selectedImage in your first view controller and use the passed image as per Step 2.