How to clean uninstall Xcode on Mac

Many times it happens that you update your MacOS and then some new update comes up for the Xcode version and there is a backwards compatibility issue. Then you go to the App Store on your Mac to update the Xcode and Bam! You end up wasting hours because the installation gets stuck. It keeps showing installing for hours. If you force shutdown your MacOS and restart, then again the same story.

This time it happened with me again after I updated MacOS Catalina and installation of Xcode 11.3 just doesn’t end. Stopping in App Store doesn’t work.

Another way is, going to the Launchpad and holding down the alt/option key till all the icons start to jiggle. Then click on the x icon and you’ll be prompted to confirm to delete the Xcode App. Well, this also didn’t work for me. Then restart your Mac to move to the next steps.

Go to the Applications folder and find the Xcode App, right-click on it and move it to Trash/Bin. Empty the Trash/Bin.

For newer versions of Xcode, this step should be sufficient. You can go ahead and re-install Xcode from the App Store.

Removing from the Terminal

You need to run the following command in order to completely remove Xcode:

sudo /Developer/Library/uninstall-devtools --mode=all

The above command requires the admin password for sudo. If you get the error that the above command not found, then it probably doesn’t work for the newer versions of Xcode.

You might need to consider backing up the data in case you have Projects in the Developer folder and certain preferences to preserve in case you’re reinstalling. Back-up some of these files/folders before deleting anything:

~/Library/Developer/Xcode/UserData/CodeSnippets
~/Library/Developer/Xcode/UserData/FontAndColorThemes
~/Library/Developer/Xcode/UserData/KeyBindings
~/Library/Developer/Xcode/Templates
~/Library/Preferences/com.apple.dt.Xcode.plist
~/Library/MobileDevice/Provisioning Profiles

The following folders are cleared with complete uninstallation of Xcode:

  • /Applications/Xcode.app
  • /Library/Preferences/com.apple.dt.Xcode.plist
  • ~/Library/Preferences/com.apple.dt.Xcode.plist
  • ~/Library/Caches/com.apple.dt.Xcode
  • ~/Library/Application Support/Xcode
  • ~/Library/Developer/Xcode
  • ~/Library/Developer/CoreSimulator
  • /System/Library/Receipts/com.apple.pkg.XcodeExtensionSupport.bom
  • /System/Library/Receipts/com.apple.pkg.XcodeExtensionSupport.plist
  • /System/Library/Receipts/com.apple.pkg.XcodeSystemResources.bom
  • /System/Library/Receipts/com.apple.pkg.XcodeSystemResources.plist
  • /private/var/db/receipts/com.apple.pkg.Xcode.bom

Remove the files at ~/Library/Caches/com.apple.dt.Xcode is basically clearing the cache. You can delete anything under /Library/Developer/ directory, such as CommandLineTools and CoreSimulator, except PrivateFrameworks subfolder. This might cause your newly installed Xcode to crash until you put it back.

Share your experience on what worked for you to make this post better.

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

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