iOS Swift Snippet Codes – XSTutorials

iOS Swift Snippet Codes

This page showcases a few common snippet codes that can be useful for your projects.

Dismiss a Controller

// Dismiss with animation
dismiss(animated: true, completion: nil)

// Dismiss without animation
dismiss(animated: false, completion: nil)

Pop a Controller

// Go back to previous controller (current one has been Pushed)
    _ = navigationController?.popViewController(animated: true)

Create UILabel programmatically

let aLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 44))
aLabel.font = UIFont(name: "HelveticaNeue-Thin", size: 20)
aLabel.textColor = .white // .black | .orange | etc.
aLabel.textAlignment = .center // .left | .right
aLabel.adjustsFontSizeToFitWidth = true // false
aLabel.isEnabled = true // false
aLabel.isHidden = false // true
aLabel.text = "text String here..."
view.addSubview(aLabel)

Create UIButton programmatically

// Into viewDidLoad() or any function:
let myButton = UIButton(type: .custom)
myButton.frame = CGRect(x:0, y:0, width:200, height:44)
myButton.center = CGPoint(x: view.center.x, y:view.center.y)
myButton.backgroundColor = .black
myButton.showsTouchWhenHighlighted = true
myButton.setBackgroundImage(UIImage(named: "my_button"), for: .normal)
myButton.setTitle("Title here", for: .normal)
myButton.setTitleColor(.white, for: .normal)
myButton.addTarget(self, action: #selector(myButtAction), for: .touchUpInside)
myButton.tag = 1
view.addSubview(myButton)

// Into the Class:
@objc func myButtAction(_ sender:UIButton) {
    // code here...
}

ActionSheet controller

let alert = UIAlertController(title: "My Alert",
            message: "Message here...",
            preferredStyle: .actionSheet)
        
let ok = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
    // code for this action...

})
alert.addAction(ok)
        
        
// Cancel button
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in })
alert.addAction(cancel)
        
alert.view.tintColor = .black
if UIDevice.current.userInterfaceIdiom == .pad {
    // iPad
    alert.modalPresentationStyle = .popover
    alert.popoverPresentationController?.sourceView = self.view
    alert.popoverPresentationController!.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
            alert.popoverPresentationController?.permittedArrowDirections = []
    self.present(alert, animated: true, completion: nil)
} else {
    // iPhone
    self.present(alert, animated: true, completion: nil)
}

AlertController with textField

let alert = UIAlertController(title: "My Alert Title",
            message: "Message here...",
            preferredStyle: .alert)
        
let ok = UIAlertAction(title: "Ok", style: .default, handler: { (action) -> Void in
    // TextField
    let textField = alert.textFields!.first!
    let txtStr = textField.text!
            
    // code for this action...
})
alert.addAction(ok)
        
// Cancel button
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in })
alert.addAction(cancel)
        
// Add a textField
alert.addTextField { (textField: UITextField) in
    textField.keyboardAppearance = .default
    textField.keyboardType = .default
}
present(alert, animated: true, completion: nil)

App Transport Security (for Into.plist)

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key><true/>
</dict>

Set Font in UISearchBar

// Into viewDidLoad():
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).font = UIFont(name: "Font-Name", size: 14)

Common Privacy rows in Info.plist

// Location
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>This app needs your current location in order to...</string>
<key>NSLocationWhenInUseUsageDescription</key>
    <string>This app needs your current location in order to...</string>
<key>NSLocationAlwaysUsageDescription</key>
    <string>This app needs your current location in order to...</string>
<key>NSLocationUsageDescription</key>
    <string>This app needs your current location in order to...</string>

// Camera
<key>NSCameraUsageDescription</key>
	<string>This app needs to open the Camera to take pictures</string>

// Photo Library
<key>NSPhotoLibraryUsageDescription</key>
	<string>This app needs to access your Photo Library to pick up pictures</string>

// Contacts
<key>NSContactsUsageDescription</key>
	<string>This app needs to access your Contacts to do something</string>

// Microphone
<key>NSMicrophoneUsageDescription</key>
	<string>This app needs to access the Microphone to do record audio/video</string>

Present a ViewController – Modal

let vc = storyboard?.instantiateViewController(withIdentifier: "VIEW_CONTROLLER_ID") as! ViewControllerName
// pass some data (optional)
vc.aVariable = myVariable
present(vc, animated: true, completion: nil)

Push a ViewController

let vc = storyboard?.instantiateViewController(withIdentifier: "Controller_ID") as! ControllerName
// pass some data (optional)
vc.aVariable = myVariable
navigationController?.pushViewController(vc, animated: true)

Detect Device Orientation

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        coordinator.animate(alongsideTransition: nil) { (UIViewControllerTransitionCoordinatorContext) in
            // Landscape orientation
            if size.height < size.width { print("Landscape")
                
            // Portrait orientation
            } else { print("Portrait") }
        }
}

Check Internet Connection

// Import framework:
import SystemConfiguration


// Into the Class:
public class Reachability {
        class func isInternetConnectionAvailable() -> Bool {
            var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
            zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
            zeroAddress.sin_family = sa_family_t(AF_INET)
            let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
                $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
                    SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
                }
            }
            var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
            if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
                return false
            }
            // Working for Cellular and WIFI
            let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
            let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
            let ret = (isReachable && !needsConnection)
            return ret
        }
}


// Into viewDidLoad() or a function:
if !Reachability.isInternetConnectionAvailable(){
    print("Internet Connection is not available, please enable WiFi or Mobile data!")
} else {
    print("Internet Connectiom is available!")
}// ./ If

CollectionView delegate methods

// Add to the Class declaration: 
UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout


// Into the Class:
func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}
    
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return myArray.count
}
    
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCustomCellID", for: indexPath) as! MyCustomCellName
        
    // Configure cell...

return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: 100, height: 100)
}
    
// Cell selected
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    print("Selected row #(indexPath.row)")        
}
    

TableView delegate functions

// Add to the Class declaration:
UITableViewDataSource, UITableViewDelegate


// Into the Class:
func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return myArray.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "MyCustomCellID", for: indexPath) as! MyCustomCellName

    // configure cell...
        
    return cell
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 120
}

// select a cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print("Selected cell #(indexPath.row)")    
}

// delete a cell
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
            
        myArray.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath], with: .fade)
    }
}

Extension to compare 2 Arrays

// Outside the Class:
extension Array where Element: Hashable {
    func difference(from other: [Element]) -> [Element] {
        let thisSet = Set(self)
        let otherSet = Set(other)
        return Array(thisSet.symmetricDifference(otherSet))
    }
}


// Inside a function:
let arr1 = ["hello", "world"]
let arr2 = ["hello", "dear"]

let difference = arr1.difference(from: arr2)
print("(difference)")
// Prints: ["dear", "world"]

Convert a video into MP4

// Into the Class:

var exportSession:AVAssetExportSession!
func convertVideoToMP4()  {
    let avAsset = AVURLAsset(url: videoURL as URL)
    exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough)
    let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    let myDocumentPath = URL(fileURLWithPath: documentsDirectory).appendingPathComponent("temp.mp4").absoluteString
    _ = NSURL(fileURLWithPath: myDocumentPath)
    let documentsDirectory2 = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
    let filePath = documentsDirectory2.appendingPathComponent("video.mp4")
    deleteFile(filePath: filePath as NSURL)
        
    //Check if the file already exists then remove the previous file
    if FileManager.default.fileExists(atPath: myDocumentPath) {
        do { try FileManager.default.removeItem(atPath: myDocumentPath)
        } catch let error { print(error) }
    }

    exportSession!.outputURL = filePath
    exportSession!.outputFileType = AVFileType.mp4
    exportSession!.shouldOptimizeForNetworkUse = true
    let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 0)
    let range = CMTimeRangeMake(start, avAsset.duration)
    exportSession?.timeRange = range
        
    exportSession!.exportAsynchronously(completionHandler: {() -> Void in
        switch self.exportSession!.status {
            case .failed:
                print("ERROR ON CONVERSION TO MP4: (self.exportSession!.error!.localizedDescription)")
            case .cancelled:
                print("Export canceled")
            case .completed:
                // Video conversion finished
                let videoToShareURL = self.exportSession!.outputURL!
                print("MP4 VIDEO URL: (videoToShareURL)")
                
            default: break
            }
        })
    }
func deleteFile(filePath:NSURL) {
    guard FileManager.default.fileExists(atPath: filePath.path!) else { return }
    do { try FileManager.default.removeItem(atPath: filePath.path!)
    } catch { fatalError("Unable to delete file: (error)") }
}

Copy String into Clipboard

UIPasteboard.general.string = "Hello world"

Extension to create a custom Album and save media in it

// Outside the Class:
extension UIViewController {
    // Save an image
    func savePhoto(image:UIImage, albumName:String, completion:((PHAsset?)->())? = nil) {
        func save() {
            if let album = findAlbum(albumName: albumName) {
                saveImage(image: image, album: album, completion: completion)
            } else {
                createAlbum(albumName: albumName, completion: { (collection) in
                    if let collection = collection {
                        self.saveImage(image: image, album: collection, completion: completion)
                    } else {
                        completion?(nil)
                    }})
            }
        }
        
        if PHPhotoLibrary.authorizationStatus() == .authorized {
            save()
        } else {
            PHPhotoLibrary.requestAuthorization({ (status) in
                if status == .authorized {
                    save()
                }})
        }
    }
    
    // Save a video
    func saveVideo(videoURL:URL, albumName:String, completion:((PHAsset?)->())? = nil) {
        func save() {
            if let album = findAlbum(albumName: albumName) {
                saveTheVideo(videoURL: videoURL, album: album, completion: completion)
            } else {
                createAlbum(albumName: albumName, completion: { (collection) in
                    if let collection = collection {
                        self.saveTheVideo(videoURL: videoURL, album: collection, completion: completion)
                    } else {
                        completion?(nil)
                    }
                })
            }
        }
        
        if PHPhotoLibrary.authorizationStatus() == .authorized {
            save()
        } else {
            PHPhotoLibrary.requestAuthorization({ (status) in
                if status == .authorized {
                    save()
                }})
        }
    }
    
    func findAlbum(albumName: String) -> PHAssetCollection? {
        let fetchOptions = PHFetchOptions()
        fetchOptions.predicate = NSPredicate(format: "title = %@", albumName)
        let fetchResult : PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
        guard let photoAlbum = fetchResult.firstObject else {
            return nil
        }
        return photoAlbum
    }
    
    func createAlbum(albumName: String, completion: @escaping (PHAssetCollection?)->()) {
        var albumPlaceholder: PHObjectPlaceholder?
        PHPhotoLibrary.shared().performChanges({
            let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumName)
            albumPlaceholder = createAlbumRequest.placeholderForCreatedAssetCollection }, completionHandler: { success, error in
                if success {
                    guard let placeholder = albumPlaceholder else {
                        completion(nil)
                        return
                    }
                    let fetchResult = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
                    guard let album = fetchResult.firstObject else {
                        completion(nil)
                        return
                    }
                    completion(album)
                } else {
                    completion(nil)
                }})
    }
    
    func saveImage(image: UIImage, album: PHAssetCollection, completion:((PHAsset?)->())? = nil) {
        var placeholder: PHObjectPlaceholder?
        PHPhotoLibrary.shared().performChanges({
            let createAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
            guard let albumChangeRequest = PHAssetCollectionChangeRequest(for: album),
                let photoPlaceholder = createAssetRequest.placeholderForCreatedAsset else { return }
            placeholder = photoPlaceholder
            let fastEnumeration = NSArray(array: [photoPlaceholder] as [PHObjectPlaceholder])
            albumChangeRequest.addAssets(fastEnumeration)
        }, completionHandler: { success, error in
            guard let placeholder = placeholder else {
                completion?(nil)
                return
            }
            if success {
                let assets:PHFetchResult<PHAsset> =  PHAsset.fetchAssets(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
                let asset:PHAsset? = assets.firstObject
                completion?(asset)
            } else {
                completion?(nil)
            }
        })
    }
    
    
    func saveTheVideo(videoURL: URL, album: PHAssetCollection, completion:((PHAsset?)->())? = nil) {
        var placeholder: PHObjectPlaceholder?
        PHPhotoLibrary.shared().performChanges({
            let createAssetRequest = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoURL)
            guard let albumChangeRequest = PHAssetCollectionChangeRequest(for: album),
                let photoPlaceholder = createAssetRequest?.placeholderForCreatedAsset else { return }
            placeholder = photoPlaceholder
            let fastEnumeration = NSArray(array: [photoPlaceholder] as [PHObjectPlaceholder])
            albumChangeRequest.addAssets(fastEnumeration)
        }, completionHandler: { success, error in
            guard let placeholder = placeholder else {
                completion?(nil)
                return
            }
            if success {
                let assets:PHFetchResult<PHAsset> =  PHAsset.fetchAssets(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
                let asset:PHAsset? = assets.firstObject
                completion?(asset)
            } else {
                completion?(nil)
            }
        })
    }
    
}


// Inside a function:

// save a photo
savePhoto(image: MY_UIIMAGE, albumName: "ALBUM_NAME", completion: nil)

// save a video
saveVideo(videoURL: videoURL!, albumName: "ALBUM_NAME", completion: nil)

Create a Video’s thumbnail image

// Inside the Class:
func createVideoThumbnail(_ url:URL) -> UIImage? {
    let asset = AVAsset(url: url)
    let imageGenerator = AVAssetImageGenerator(asset: asset)
    imageGenerator.appliesPreferredTrackTransform = true
    var time = asset.duration
    time.value = min(time.value, 2)
    do {
        let imageRef = try imageGenerator.copyCGImage(at: time, actualTime: nil)
        return UIImage(cgImage: imageRef)
    } catch let error as NSError {
        print("Image generation failed with error (error)")
        return nil
    }
}

// Inside a function:
let videoThumbnailUIImage = createVideoThumbnail(videoURL!)

Crop an UIIMage into a UIView

UIGraphicsBeginImageContext(myView.frame.size)
myView.layer.render(in: UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

myImageView.image = img

Date formatter

let date = Date()
let df = DateFormatter()
df.dateFormat = "MMM dd yyy | hh:mm a"
let dateSTring = df.string(from: date)

Detect hashtags and @mentions in TextView

// Outside the Class:
extension UITextView {
            func resolveHashTags() {
                // Turn string in to NSString
                let nsText = NSString(string: self.text)
                let words = nsText.components(separatedBy: CharacterSet(charactersIn: "@#ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_").inverted)
                let attrString = NSMutableAttributedString()
                attrString.setAttributedString(self.attributedText)
                
                // Tag each word if it has a hashtag
                for word in words {
                    if word.count < 3 { continue }
                    
                    // #hashtag
                    if word.hasPrefix("#") {
                        let matchRange:NSRange = nsText.range(of: word as String)
                        let stringifiedWord = word.dropFirst()
                        if let firstChar = stringifiedWord.unicodeScalars.first, NSCharacterSet.decimalDigits.contains(firstChar) {
                        } else {
                            attrString.addAttribute(NSAttributedStringKey.link, value: "#(stringifiedWord)", range: matchRange)
                        }
                        
                    // @mention
                    } else if word.hasPrefix("@") {
                        let matchRange:NSRange = nsText.range(of: word as String)
                        let stringifiedWord = word.dropFirst()
                        if let firstChar = stringifiedWord.unicodeScalars.first, NSCharacterSet.decimalDigits.contains(firstChar) {
                        } else {
                            attrString.addAttribute(NSAttributedStringKey.link, value: "@(stringifiedWord)", range: matchRange)
                        }
                        
                    }// ./ If #
                    
                }// ./ For
                self.attributedText = attrString
            }
}

// Inside a function:
 myTextView.resolveHashtags()

Detect Web URLs in a String

let types: NSTextCheckingResult.CheckingType = .link
let detector = try? NSDataDetector(types: types.rawValue)
guard let detect = detector else { return }
let matches = detect.matches(in: myString, options: .reportCompletion, range: NSMakeRange(0, myString.count))
for match in matches {
    print("WEB URL DETECTED: (match.url!)")
    let task = URLSession.shared.dataTask(with: match.url!, completionHandler: { (data, response, error) in
        if error == nil {
            let urlContent = String(data: data!, encoding: String.Encoding.ascii)
             print("URL CONTENT: " + urlContent!)
        }
})
task.resume()

Detect iPhone and iPad device

if UIDevice.current.userInterfaceIdiom == .phone {
    // iPhone
} else  {
    // iPad  
}

Check Device model by size

if UIScreen.main.bounds.size.width == 320 {
    // iPhone 4/5/SE

} else if UIScreen.main.bounds.size.width == 375 {
    // iPhone 6/7/8

} else if UIScreen.main.bounds.size.width == 414 {
    // iPhone 6+/7+/8+

} else if UIScreen.main.bounds.size.width >= 768 {
    // iPad - iPad Pro

} else if UIScreen.main.bounds.size.height == 812 {
    // iPhone X/XS

} else if UIScreen.main.bounds.size.height == 896 {
    // iPhone XR / XS Max
    
}

Dismiss keyboard on scroll down

var lastContentOffset: CGFloat = 0
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
    self.lastContentOffset = scrollView.contentOffset.y
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if (self.lastContentOffset > scrollView.contentOffset.y) {
        myTextField.resignFirstResponder()
    }
}

DispatchQueue after 1 second

DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {

    // action here...

})

DispatchQueue (main thread)

DispatchQueue.main.async {
    // code here...
}

Calculate distance between 2 locations

if currentLocation != nil {
    let otherLocation = CLLocation(latitude: 10.123456798, longitude: -74.123456789)
    let distanceInKM: CLLocationDistance = otherLocation.distance(from: currentLocation!) / 1000
    let distanceString = String(format: "%.2f Km", distanceInKM)
}

Save data with FileManager

// save an image
let fileManager = FileManager.default
let imagePath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("myImage" + ".jpg")
let data = myUIImage.jpegData(compressionQuality: 1.0)
fileManager.createFile(atPath: imagePath, contents: data, attributes: nil)
print("SAVED IMAGE PATH: (imagePath)")
            
            
// save a video
let aURL = URL(string: "my_video_path")
do {
    let videoData = try Data(contentsOf: aURL!)
    let videoPath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("myVideo" + ".mp4")
    let fileManager = FileManager.default
    fileManager.createFile(atPath: videoPath, contents: videoData, attributes: nil)
    print("-- SAVED VIDEO PATH: (videoPath)")
} catch let error as NSError { print(error) }
        
// save a string
let documentsPath = NSSearchPathForDirectoriesInDomains( .documentDirectory, .userDomainMask, true)[0]
let localURL = URL(fileURLWithPath: documentsPath).appendingPathComponent("myText.txt")
do {
    try myString.write(to: localURL, atomically: false, encoding: String.Encoding.utf8)
    print("TEXT LOCAL: URL: (localURL)")
} catch {}

Apply a CoreImage filter to an image

let ciContext = CIContext(options: nil)
let coreImage = CIImage(image: myImageView.image!)
let filter = CIFilter(name: "CIGaussianBlur")!
filter.setDefaults()
print("FILTER ATTRIBUTES: (filter.attributes)")
        
// Filter values (if any)
filter.setValue(sender.value, forKey: kCIInputRadiusKey)
        
// Finalize filter
filter.setValue(coreImage, forKey: kCIInputImageKey)
let filteredImageData = filter.value(forKey: kCIOutputImageKey) as! CIImage
let filteredImageRef = ciContext.createCGImage(filteredImageData, from: filteredImageData.extent)
myFilteredImageView.image = UIImage(cgImage: filteredImageRef!)

Extension to find duplicates in 2 Arrays

// Outside the Class:
extension Array where Element: Hashable {
    func duplicates() -> Array {
        let groups = Dictionary(grouping: self, by: {$0})
        let duplicateGroups = groups.filter {$1.count > 1}
        let duplicates = Array(duplicateGroups.keys)
        return duplicates
    }
}


// Inside a function:
let arr1 = ["hello","world"]
let arr2 = ["hello", "dear", "friend"]
let arrays = arr1 + arr2
let duplicates = arrays.duplicates()
print(duplicates)
// prints: ["hello"]

Get Address from Location coordinates

let geoCoder = CLGeocoder()
geoCoder.reverseGeocodeLocation(myLocation!, completionHandler: { (placemarks, error) -> Void in
    let placeArray:[CLPlacemark] = placemarks!
    var placemark: CLPlacemark!
    placemark = placeArray[0]
            
    // Street
    let street = placemark.addressDictionary?["Name"] as? String ?? ""
    // City
    let city = placemark.addressDictionary?["City"] as? String ?? ""
    // Zip code
    let zip = placemark.addressDictionary?["ZIP"] as? String ?? ""
    // Country
    let country = placemark.addressDictionary?["Country"] as? String ?? ""
    // State
    let state = placemark.addressDictionary?["State"] as? String ?? ""
    
    print("ADDRESS: (street) - (zip), (city) - (country) - (state)")
})

Get center coordinates while moving a MapView

var center:CLLocationCoordinate2D!
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    center = mapView.centerCoordinate
    let loc = CLLocation(latitude: center.latitude, longitude: center.longitude)
    print("CHANGED LOCATION: (loc)")
}

Get Current Location

// Inside the Class, above viewDidLoad():
var locationManager: CLLocationManager!

// Into the Class:
func getCurrentLocation() {
    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
    if locationManager.responds(to: #selector(CLLocationManager.requestWhenInUseAuthorization)) {
    locationManager.requestAlwaysAuthorization()
    }
    locationManager.startUpdatingLocation()
}

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("Failed to Get Your Location")
    }
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    locationManager.stopUpdatingLocation()
    let location = locations.last
    print(location)
}

Get Location coordinates from an Address string

let geoCoder = CLGeocoder()
geoCoder.geocodeAddressString("W 101 Street, London, UK", completionHandler: { (placemarks, error) in
    if error != nil { print(error as! String)
    } else {
        if let placemark = placemarks?.first {
            let coordinates = placemark.location!.coordinate
            let myLocation = CLLocation(latitude: coordinates.latitude, longitude: coordinates.longitude)
            print(myLocation)
            
            // Invalid adddress
            } else { print("Invalid adddress, please type a new one.") }
}})

Get iOS Keyboard visibility status

// Inside viewDidAppear():
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)


// Inside the Class:
@objc func keyboardWillShow(_ notification: Notification) {
    if let kFrame: NSValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
        let kRect = kFrame.cgRectValue
        let kHeight = kRect.height
        print("KEYBOARD's HEIGHT: (kHeight)")
            // do something...
    }
}
@objc func keyboardWillHide(_ notification: Notification) {
    // so something...
}

Get Array from a .plist file

let dictRoot = NSDictionary(contentsOfFile: Bundle.main.path(forResource: "MyPListFileName", ofType: "plist")!)
let plistArray: NSArray = dictRoot?.object(forKey: "ArrayInThePlistFile") as! NSArray
print(plistArray)

Set HTML string into a UILabel

let HTML_HEADER_STYLE =
    "<style>" +
    "@import url('https://fonts.googleapis.com/css?family=Poppins');" +
    "body{ font-family: 'Poppins', sans-serif; font-size:13px;color:#000; }" +
    "span{ color:#687683; font.size: 13px; }" +
    "</style>"
        
// HTML string
let htmlStr = HTML_HEADER_STYLE + "<strong>Strong text</strong> <span>Hello world</span>"
let attributedString = try! NSAttributedString(data: htmlStr.data(using: .unicode, allowLossyConversion: true)!, options:[.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
        
myLabel.attributedText = attributedString

Get TabBar height

let tabBarHeight = tabBarController?.tabBar.frame.height

Get the device language

// Get the device Language (by its 2-letter string)
let language = Locale.preferredLanguages[0]
let langArr = language.components(separatedBy: "-")
var deviceLanguageCode = langArr[0]
print("DEVICE LANGUAGE: (deviceLanguageCode)")
        
// If the device has a language you have not set into the .plist file, it'll return English as default
if deviceLanguageCode != "en"
&& deviceLanguageCode != "it"
&& deviceLanguageCode != "de" {
    deviceLanguageCode = "en"
}

Grayscale an image

UIGraphicsBeginImageContextWithOptions(MyUIImage.size, true, 1.0)
var imageRect = CGRectMake(0, 0, MyUIImage.size.width, myUIImage.size.height)
MyUIImage.drawInRect(imageRect, blendMode: kCGBlendModeLuminosity, alpha: 1.0)
var filteredImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
    
// Set the grayscaled image
myUIImage = filteredImage
myImageView.image = myUIImage

Hide status bar

override var prefersStatusBarHidden : Bool {
    return true
}

In-App Purchase code

// Import Framework:
import StoreKit

// Add class delegates
SKProductsRequestDelegate, SKPaymentTransactionObserver

// Declare IAP variables
var productsRequest = SKProductsRequest()
var validProducts = [SKProduct]()

// Inside viewDidLoad():
purchaseButton.isHidden = true
fetchAvailableProducts()

// Inside the Class, below viewDidLoad():
func purchaseProduct() {
    purchaseMyProduct(validProducts[0])
    purchaseButton.isEnabled = false
}

func fetchAvailableProducts()  {
    let productIdentifiers = NSSet(objects:
        "Your IAP product ID"
    )
    productsRequest = SKProductsRequest(productIdentifiers: 
    productIdentifiers as! Set<String>)
        productsRequest.delegate = self
            productsRequest.start()
}

func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) {
    if (response.products.count > 0) {
        validProducts = response.products
                
        // 1st IAP Product
        let firstProduct = response.products[0] as SKProduct
                
        // Get its price from App Store Connect
        let numberFormatter = NumberFormatter()
        numberFormatter.formatterBehavior = .behavior10_4
        numberFormatter.numberStyle = .currency
        numberFormatter.locale = firstProduct.priceLocale
        let price1Str = numberFormatter.string(from: firstProduct.price)
            
        let productDescription = firstProduct.localizedDescription + "nfor just (price1Str!)"
    }
}

func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool {
    return true
}

func canMakePurchases() -> Bool {  return SKPaymentQueue.canMakePayments()  }
    func purchaseMyProduct(_ product: SKProduct) {
        if self.canMakePurchases() {
            let payment = SKPayment(product: product)
            SKPaymentQueue.default().add(self)
            SKPaymentQueue.default().add(payment)
        } else { print("Purchases are disabled in your device!") }
}

func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for transaction:AnyObject in transactions {
            if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction {
                switch trans.transactionState {
                        
                case .purchased:
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    print("You've successfully removed ads!")
                break
                        
                case .failed:
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    break
                case .restored:
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    break
                        
                default: break
        }}}
    }
        
func restorePurchase() {
    SKPaymentQueue.default().add(self as SKPaymentTransactionObserver)
    SKPaymentQueue.default().restoreCompletedTransactions()
}

func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
    print("You've successfully made your purchase!")
}

ImagePicker Delegate

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
    myImageView.image = image
    }
    dismiss(animated: true, completion: nil)
}

Animate a set of images in a loop (like a Gif)

let imagesArr = ["image1", "image2", "image3"]
var images : [UIImage] = []
for i in 0..<imagesArr.count {
    images.append(UIImage(named: imagesArr[i])!)
}
animImage.animationImages = images
animImage.animationDuration = 0.7
view.addSubview(animImage)
animImage.startAnimating()

Add Keyboard toolbar to a TextView

let toolbar = UIView(frame: CGRect(x: 0, y: view.frame.size.height+44, width: view.frame.size.width, height: 44))
toolbar.backgroundColor = .white
        
let doneButt = UIButton(frame: CGRect(x: toolbar.frame.size.width - 60, y: 0, width: 44, height: 44))
doneButt.setTitle("Done", for: .normal)
doneButt.setTitleColor(.black, for: .normal)
doneButt.titleLabel?.font = UIFont(name: "Titillium-Black", size: 13)
doneButt.addTarget(self, action: #selector(dismissKeyboard), for: .touchUpInside)
toolbar.addSubview(doneButt)

myTextView.inputAccessoryView = toolbar
myTextView.delegate = self

Limit characters in a TextView

// Add the delegate to the Class declaration:
UITextViewDelegate

// Inside the Class:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    let maxCharacters = 100
    let newText = (textView.text as NSString).replacingCharacters(in: range, with: text)
    let numberOfChars = newText.count
    if numberOfChars >= maxCharacters { simpleAlert("You've reached the maximum characters allowed for review!") }
    return numberOfChars < maxCharacters
}

Set line-height for TextView

let paragraphStyle = NSMutableParagraphStyle()
let lineHeight: CGFloat = 20.0
paragraphStyle.lineHeightMultiple = lineHeight
paragraphStyle.maximumLineHeight = lineHeight
paragraphStyle.minimumLineHeight = lineHeight
let ats = [NSAttributedString.Key.font: UIFont(name: "HelveticaNeue", size: 14)!, NSAttributedString.Key.paragraphStyle: paragraphStyle]
myTextView.attributedText = NSAttributedString(string: "Hello world, I'm here to amaze you!", attributes: ats)

Load local HTML file in WebView

let url = Bundle.main.url(forResource: "MyFileName", withExtension: "html")
webView.loadRequest(URLRequest(url: url!))

Load and Save an Array with UserDefaults

// Declare an Array as a global varibale outside the Class
var myArray = [String]()
let defaults = UserDefaults.standard()


// Inside viewDidLoad():

// load...
if let tempArr = defaults.object(forKey: "tempArr") as? [String] {
    myArray = tempArr
}
print("myArray: (myArray)")
    
// save...
myArray += anotherArray
// or other append operations for myArray...

let tempArr = myArray
defaults.setObject(tempArr, forKey: "tempArr")
print("myArray: (myArray)")

Make a phone call

let aURL = URL(string: "telprompt://1234567890")!
if UIApplication.shared.canOpenURL(aURL) { UIApplication.shared.openURL(aURL) }

Create Buttons inside a ScrollView

var X:CGFloat = 0
let Y:CGFloat = 0
let W:CGFloat = 80
let H:CGFloat = 44
let G:CGFloat = 2
var counter = 0

for i in 0..<MY_ARRAY.count {
    counter = i
    
    let aButt = UIButton(type: .custom)
    aButt.frame = CGRect(x: X, y: Y, width: W, height: H)
    aButt.tag = i
    aButt.setTitle("(MY_ARRAY[i])", for: .normal)
    aButt.titleLabel?.font = UIFont(name: "Titillium-Semibold", size: 13)
    aButt.setTitleColor(.white, for: .normal)
    aButt.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
    
    X += W + G
    myScrollView.addSubview(aButt)
}   

myScrollView.contentSize = CGSize(width: W * CGFloat(counter+2), height: H)

Open iMessage to send an SMS

// Import framework
import MessageUI


// Add delegate
MFMessageComposeViewControllerDelegate 

// Inside a function
let messageComposer = MFMessageComposeViewController()
messageComposer.messageComposeDelegate = self
messageComposer.body = "Hello world!"
present(messageComposer, animated: true, completion: nil)

// Inside the Class:
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
    dismiss(animated: true, completion: nil)
}

Open a URL in WebView

let url = URL(string: "https://google.com")
webView.loadRequest(URLRequest(url: url!))

Open TabBar element

let tbc = storyboard?.instantiateViewController(withIdentifier: "MainTabBar") as! UITabBarController
tbc.selectedIndex = 0
present(tbc, animated: false, completion: nil)

Open native Camera

if UIImagePickerController.isSourceTypeAvailable(.camera) {
    let imagePicker = UIImagePickerController()
    imagePicker.delegate = self
    imagePicker.sourceType = .camera
    imagePicker.allowsEditing = false
    present(imagePicker, animated: true, completion: nil)
}

Open native Photo Library

if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
    let imagePicker = UIImagePickerController()
    imagePicker.delegate = self
    imagePicker.sourceType = .photoLibrary
    imagePicker.allowsEditing = false
    present(imagePicker, animated: true, completion: nil)
}

Open Location Service in Settings

UIApplication.shared.openURL(URL(string:UIApplicationOpenSettingsURLString)!)

Open Map with address string

let baseUrl: String = "http://maps.apple.com/?q="
let addressStr = addressOutlet.titleLabel!.text!
let encodeName = addressStr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlFragmentAllowed)!
let finalUrl = baseUrl + encodeName
if let url = URL(string: finalUrl) { UIApplication.shared.openURL(url) }

Open Maps with GPS coordinates

// Import frameworks
import CoreLocation
import MapKit


// Inside a function
let regionDistance:CLLocationDistance = 5000
let coordinates = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let regionSpan = MKCoordinateRegion(center: coordinates, latitudinalMeters: regionDistance, longitudinalMeters: regionDistance)
let options = [
            MKLaunchOptionsMapCenterKey: NSValue(mkCoordinate: regionSpan.center),
            MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan: regionSpan.span)
]
let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)
let mapItem = MKMapItem(placemark: placemark)
mapItem.name = "Location name"
mapItem.openInMaps(launchOptions: options)

Open native VideoCamera

if UIImagePickerController.isSourceTypeAvailable(.camera) {
    let imagePicker = UIImagePickerController()
    imagePicker.delegate = self
    imagePicker.sourceType = .camera
    imagePicker.mediaTypes = [kUTTypeMovie as String]
    imagePicker.videoMaximumDuration = 10
    imagePicker.videoQuality = .typeMedium
    imagePicker.allowsEditing = false
    present(imagePicker, animated: true, completion: nil)
}

Open a XIB modally

let vc = myXIBname(nibName: "myXIBname", bundle: nil)
vc.modalTransitionStyle = .crossDissolve
present(vc, animated: true, completion:nil)

Set right and left margins in TextField

myTxt.rightView = UIView(frame: CGRect(x: 0, y: 0, width: 88, height: myTxt.frame.height))
myTxt.rightViewMode = .always

myTxt.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: myTxt.frame.height))
myTxt.leftViewMode = .always

ScrollView pagination

// Add delegate
UIScrollViewDelegate


//Inside the Class:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let pageWidth = imagesScrollView.frame.size.width
    let page = Int(floor((imagesScrollView.contentOffset.x * 2 + pageWidth) / (pageWidth * 2)))
    pageControl.currentPage = page
}

Pan Gesture

let translation: CGPoint =  sender.translation(in: view)
sender.view?.center = CGPoint(x:sender.view!.center.x + translation.x, y:sender.view!.center.y + translation.y)
sender.setTranslation(CGPoint(x: 0, y: 0), in: view)

UIPickerView

// Add delegates to the Class declaration:
UIPickerViewDataSource, UIPickerViewDelegate


// Inside the Class:
func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 1
}

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return myArray.count
}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return myArray[row]
}
    
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    myLabel.text = "(myArray[row])"
}

// CUSTOMIZE FONT AND COLOR OF PICKERVIEW (*optional*)
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
    var label = view as! UILabel
    if view == nil { label = UILabel() }
        
    label.textAlignment = .center
    let rowText = myArray[row]
        
    let attributedRowText = NSMutableAttributedString(string: rowText)
    let attributedRowTextLength = attributedRowText.length
    attributedRowText.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.black, range: NSRange(location: 0, length: attributedRowTextLength))
        attributedRowText.addAttribute(NSAttributedString.Key.font, value: UIFont(name: "HelveticaNeue", size: 16)!, range: NSRange(location: 0 ,length:attributedRowTextLength))
        
    label.attributedText = attributedRowText
        
 return label
}

Placeholder color in UITextField

myTextField.attributedPlaceholder = NSAttributedString(string: "Search for something...", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white])

Play a sound with AVAudioPlayer

// Import framework
import AVFoundation

// Inside a function
let path = Bundle.main.path(forResource: "SoundFileName", ofType: "wav")
let url = URL.init(fileURLWithPath: path!)
do { try audioPlayer = AVAudioPlayer(contentsOf: url)
} catch { print("NO AUDIO PLAYER") }
audioPlayer.delegate = self
audioPlayer.numberOfLoops = 0
audioPlayer.volume = 1.0
audioPlayer.prepareToPlay()
audioPlayer.play()

Play a sound clip with AutioToolbox

var soundID:SystemSoundID = 0
func playSound() {
    let filePath = Bundle.main.path(forResource: "mySoundFileName", ofType: "wav")
    let soundURL = URL(fileURLWithPath: filePath!)
    AudioServicesCreateSystemSoundID(soundURL! as CFURL, &soundID)
    AudioServicesPlaySystemSound(soundID)
}

Get an online JSON file data

let jsonUrl = "http://example.com/myJson.json"
let session = URLSession.shared
let url = URL(string: jsonUrl)!
let task = session.dataTask(with: url, completionHandler: { (data, response, error) in
    do {
        let jsonData = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)
        let myArray:NSArray = jsonData
        print("My Array: (myArray)")
    } catch _ { }
})
task.resume()

Get a random number

let myRandomInt = Int(arc4random() % 100)

RefreshControl for TableView and CollectionView

// Declare variable
let refreshControl = UIRefreshControl()


// Into viewDidLoad():
refreshControl.tintColor = .black
refreshControl.addTarget(self, action: #selector(refreshData), for: .valueChanged)
myTableView.addSubview(refreshControl)


// Inside the Class:
@objc func refreshData () {
    myTableView.reloadData()
    if refreshControl.isRefreshing { refreshControl.endRefreshing() }
}

Remove an item from an Array of strings

myArray = myArray.filter{$0 != "String To Remove"}

Remove ScrollView’s subviews

let subViews = myScrollView.subviews
for subview in subViews { subview.removeFromSuperview() }

Resize an UIImage

func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage {
    let size = image.size
    
    let widthRatio  = targetSize.width  / image.size.width
    let heightRatio = targetSize.height / image.size.height
        
    var newSize: CGSize
    if(widthRatio > heightRatio) {
        newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
    } else {
        newSize = CGSize(width: size.width * widthRatio,  height: size.height * widthRatio)
    }

    let rect = CGRect(x:0, y:0, width: newSize.width, height: newSize.height)
        
    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
    image.draw(in: rect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
        
    return newImage!
}

Rotate Gesture Recognizer function

if sender.state == .began ||
    sender.state == .changed {
    sender.view!.transform = CGAffineTransformRotate(sender.view!.transform, sender.rotation)
    sender.rotation = 0
}

Rotate a View 90° clockwise

myView.transform = CGAffineTransform( rotationAngle:.pi/2)

Round Views corners

myView.layer.cornerRadius = myView.bounds.size.width/2 // or 10, or any other number

Extension to round large numbers

extension Int {
    var rounded: String {
        let abbrev = "KMBTPE"
        return abbrev.enumerated().reversed().reduce(nil as String?) { accum, tuple in
            let factor = Double(self) / pow(10, Double(tuple.0 + 1) * 3)
            let format = (factor.truncatingRemainder(dividingBy: 1)  == 0 ? "%.0f%@" : "%.1f%@")
            return accum ?? (factor > 1 ? String(format: format, factor, String(tuple.1)) : nil)
            } ?? String(self)
    }
}

Save an Event in the Calendar app

let eventStore = EKEventStore()
        eventStore.requestAccess(to: .event) { (granted, error) in
            if granted && error == nil {
                print("ACCESS GRANTED (granted)")
                
                let event = EKEvent(eventStore: eventStore)
                event.title = "Event title"
                event.startDate = startDate!
                event.endDate = endDate!
                event.notes = "Event notes"
                
                // Save Event...
                event.calendar = eventStore.defaultCalendarForNewEvents
                do { try eventStore.save(event, span: .thisEvent)
                } catch let error as NSError { print("Failed to save Event: (error)") }
                print("This Event has been savede in your Calendar app")
                
            // error
            } else { print("Failed to save Event: (error!.localizedDescription)") }
}
        

Scale an UIImage proportionally

func scaleImage(image: UIImage, maxDimension: CGFloat) -> UIImage {
    var scaledSize = CGSize(width: maxDimension, height: maxDimension)
    var scaleFactor: CGFloat
        
    if image.size.width > image.size.height {
        scaleFactor = image.size.height / image.size.width
        scaledSize.width = maxDimension
        scaledSize.height = scaledSize.width * scaleFactor
    } else {
        scaleFactor = image.size.width / image.size.height
        scaledSize.height = maxDimension
        scaledSize.width = scaledSize.height * scaleFactor
    }

        UIGraphicsBeginImageContext(scaledSize)
        image.draw(in: CGRect(x:0, y:0, width: scaledSize.width, height: scaledSize.height))
        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
    return scaledImage!
}

Zoom an ImageView into a ScrollView

// Add delegate:
UIScrollViewDelegate


// Inside the Class:
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return myImageView
}

Set HEX value for colors

func hexValue(hex:String) -> UIColor {
    var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
    
    if (cString.hasPrefix("#")) {
        cString.remove(at: cString.startIndex)
    }
    
    if ((cString.count) != 6) {
        return UIColor.gray
    }
    
    var rgbValue:UInt32 = 0
    Scanner(string: cString).scanHexInt32(&rgbValue)
    
    return UIColor(
        red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
        green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
        blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
        alpha: CGFloat(1.0)
    )
}

Share text and image with UIActivityController

let messageStr  = "MY_MESSAGE_HERE"
let img = myUIImage!
let shareItems = [messageStr, img] as [Any]

let vc = UIActivityViewController(activityItems: shareItems, applicationActivities: nil)
vc.excludedActivityTypes = [.print, .postToWeibo, .copyToPasteboard, .addToReadingList, .postToVimeo]

if UIDevice.current.userInterfaceIdiom == .pad {
    // iPad
    vc.modalPresentationStyle = .popover
    vc.popoverPresentationController?.sourceView = view
    vc.popoverPresentationController!.sourceRect = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0)
    vc.popoverPresentationController?.permittedArrowDirections = []
        present(vc, animated: true, completion: nil)
} else {
    // iPhone
    present(vc, animated: true, completion: nil)
}

Shuffle Array’s items

extension Array {
    mutating func shuffle() {
        for _ in 0..<self.count {
            sortInPlace { (_,_) in arc4random() < arc4random() }
        }
    }
}

Extension to show time ago to a Date

extension UIViewController {
    func timeAgoSinceDate(_ date:Date,currentDate:Date, numericDates:Bool) -> String {
        let calendar = Calendar.current
        let now = currentDate
        let earliest = (now as NSDate).earlierDate(date)
        let latest = (earliest == now) ? date : now
        let components:DateComponents = (calendar as NSCalendar).components([NSCalendar.Unit.minute , NSCalendar.Unit.hour , NSCalendar.Unit.day , NSCalendar.Unit.weekOfYear , NSCalendar.Unit.month , NSCalendar.Unit.year , NSCalendar.Unit.second], from: earliest, to: latest, options: NSCalendar.Options())
        
        if (components.year! >= 2) {
            return "(components.year!) years ago"
        } else if (components.year! >= 1){
            if (numericDates){
                return "1 year ago"
            } else {
                return "Last year"
            }
        } else if (components.month! >= 2) {
            return "(components.month!) months ago"
        } else if (components.month! >= 1){
            if (numericDates){
                return "1 month ago"
            } else {
                return "Last month"
            }
        } else if (components.weekOfYear! >= 2) {
            return "(components.weekOfYear!) weeks ago"
        } else if (components.weekOfYear! >= 1){
            if (numericDates){
                return "1 week ago"
            } else {
                return "Last week"
            }
        } else if (components.day! >= 2) {
            return "(components.day!) days ago"
        } else if (components.day! >= 1){
            if (numericDates){
                return "1 day ago"
            } else {
                return "Yesterday"
            }
        } else if (components.hour! >= 2) {
            return "(components.hour!) hours ago"
        } else if (components.hour! >= 1){
            if (numericDates){
                return "1 hour ago"
            } else {
                return "An hour ago"
            }
        } else if (components.minute! >= 2) {
            return "(components.minute!) minutes ago"
        } else if (components.minute! >= 1){
            if (numericDates){
                return "1 minute ago"
            } else {
                return "A minute ago"
            }
        } else if (components.second! >= 3) {
            return "(components.second!) seconds ago"
        } else {
            return "Just now"
        }
        
    }
    
}

Touches detection

// MARK: - Touches Began
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // Get the location of the finger touch on the screen
        let touch = touches.first
        let touchLocation = touch!.location(in: self.view)
        
        // code here...
}
    
   
    
// MARK: -  Touches Moved
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        // Get the location of the finger touch on the screen
        let touch = touches.first
        let touchLocation = touch!.location(in: self.view)
        
        // code here...
}
    
    
// MARK: - Touches Ended
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        // code here...
}

Animate a View

UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveLinear, animations: {
    self.myView.frame.origin.y = 84
}, completion: { (finished: Bool) in
    // completion code (optional)
})
Buy me a coffee - XScoder - thanks for your support
Your support will be highly appreciated 😉