Adjust Baseline of Text Using NSAttributedString

Fix Urdu font issues in iOS

When using urdu font, we have some cases where the text is much higher and is being cut off. We can adjust the baseline of the text and bring it down using the following code.

// https://hashaam.com/2017/11/13/adjust-baseline-of-text-using-nsattributedstring/
let attributedString = NSAttributedString(string: “text", attributes: [
NSFontAttributeName: font,
NSForegroundColorAttributeName: UIColor.white,
NSBaselineOffsetAttributeName: -5.0
])

URL Encode only Unicode Characters

Make your URLs readable by the Framework SDK

When dealing with Unicode Characters in URL strings, we need to encode Unicode characters to percentages for them to be readable by URL. We do so using the following code:

// https://hashaam.com/2017/11/13/url-encode-only-unicode-characters/
let originalURLString = "https://www.exampleserver.com/articles/latest/لن-تصدق-ما-يمكن-أن-تجده-في-مطبخك-فاحذر-غسل-هذه-الأداة.html"
let allowedCharacterSet = CharacterSet.urlFragmentAllowed
let urlString = originalURLString.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet)!
let url = URL(string: urlString)!

Get device token for remote push notifications in Swift 3

When registering device to receive remote notifications, we can use device token to uniquely identify each device and even send the token to our server.

Consider the following code

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    let tokenParts = deviceToken.map { data -> String in
        return String(format: "%02.2hhx", data)
    }

    let token = tokenParts.joined()

    // process token

}

Here is gist for the example

// https://hashaam.com/2017/07/22/get-device-token-for-remote-push-notifications-in-swift-3/
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenParts = deviceToken.map { data -> String in
return String(format: "%02.2hhx", data)
}
let token = tokenParts.joined()
// process token
}

Source: RayWenderlich

Custom Sorting an Array in Swift

Let’s assume we have following Business struct

struct Business {
    let businessId: Int
    let rating: Int
}

And we have following data set for business with left value being businessId and right being rating

167 1
196 2
171 3
147 4
153 5
191 1
125 2
126 3
174 4
175 5
103 1
119 2
186 3
157 4
178 5
110 1
130 2
168 3
129 4
120 5

We should sort businesses in descending order of rating. For the businesses that have same rating, the original order of business should remain same.

To solve this, we can have following function:

func sortBusinesses(_ businesses: [Business]) -> [Business] {

    let set = NSOrderedSet(array: businesses)
    let newSet = set.sortedArray(comparator: { first, second -> ComparisonResult in
        let firstBusiness = first as! Business
        let secondBusiness = second as! Business
        if firstBusiness.rating == secondBusiness.rating {
            return .orderedSame
        }
        return .orderedDescending
    })
    return newSet as! [Business]

}

let sortedBusinesses = sortBusinesses(businesses)

The above will give us following output:

153 5
175 5
178 5
120 5
147 4
174 4
157 4
129 4
171 3
126 3
186 3
168 3
196 2
125 2
119 2
130 2
167 1
191 1
103 1
110 1

Here is gist for the example

// https://hashaam.com/2017/07/20/custom-sorting-an-array-in-swift/
struct Business {
let businessId: Int
let rating: Int
}
func sortBusinesses(_ businesses: [Business]) -> [Business] {
let set = NSOrderedSet(array: businesses)
let newSet = set.sortedArray(comparator: { first, second -> ComparisonResult in
let firstBusiness = first as! Business
let secondBusiness = second as! Business
if firstBusiness.rating == secondBusiness.rating {
return .orderedSame
}
return .orderedDescending
})
return newSet as! [Business]
}
let sortedBusinesses = sortBusinesses(businesses)

Configure Audio Session for background audio mode (iOS Project)

We use AVPlayer from AVFoundation to play audio in our applications. The moment we send the application to back ground mode, audio stops playing.

To fix this, we will need to configure AVAudioSession properly. We start by importing AVFoundation in AppDelegate or our iOS Project.

import AVFoundation

Next, add the following code in application didFinishLaunchingWithOptions:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    // enable playback category: this is required for background audio to function normally
    let audioSession = AVAudioSession.sharedInstance()
    try? audioSession.setCategory(AVAudioSessionCategoryPlayback, mode: AVAudioSessionModeDefault)
    try? audioSession.setActive(true, with: [])
    
    return true
}

Finally, enable Background Audio Mode in Project Settings.
Enable background audio mode in XCode Project Settings

Here is gist for the example

// https://hashaam.com/2017/06/15/configure-audio-session-for-background-audio-mode-ios-project/
import UIKit
import AVFoundation
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// enable playback category: this is required for background audio to function normally
let audioSession = AVAudioSession.sharedInstance()
try? audioSession.setCategory(AVAudioSessionCategoryPlayback, mode: AVAudioSessionModeDefault)
try? audioSession.setActive(true, with: [])
return true
}
}

Working with live views in Swift Playground

Prototype faster in Swift Playground without Projects

When working on prototypes it is easy to create a new Playground to experiment on views. This makes the development really fast and easy. This method is much faster than creating a new XCode Project for prototyping.

Below is the code I use in Swift Playground


import UIKit
import PlaygroundSupport

let f = CGRect(x: 0.0, y: 0.0, width: 50.0, height: 50.0)
let v = UIView(frame: f)
v.backgroundColor = UIColor.yellow

PlaygroundPage.current.liveView = v

 

Then, to see the live view, select ViewAssistant EditorShow Assistant Editor

Show Assistant Editor in XCode

 

And then select Timeline option to see the live view.

Show Playground Timeline in Assistant Editor (XCode)

 

Later, we will add UIView with red background color as sub-view to test live updates.


// will be adding red view as sub view
let redView = UIView(frame: CGRect.zero)
redView.translatesAutoresizingMaskIntoConstraints = false
redView.backgroundColor = UIColor.red

v.addSubview(redView)

redView.centerXAnchor.constraint(equalTo: v.centerXAnchor, constant: 0.0).isActive = true
redView.centerYAnchor.constraint(equalTo: v.centerYAnchor, constant: 0.0).isActive = true
redView.widthAnchor.constraint(equalToConstant: 15.0).isActive = true
redView.heightAnchor.constraint(equalToConstant: 15.0).isActive = true

 

And finally, see the updates.

See live updates in Playground (XCode)

Generate Random Colors in Swift

Randomize UIColor

We have all come across scenarios where we need to use random colors. For example, showing UIViewControllers with random background color in a UIPageViewController, or just show UITableViewCells with random background colors in a UITableView.

I have created an extension on UIColor to help me in the applications.

Here is the code in Swift 3:

extension UIColor {
    static var random: UIColor {
        // Seed (only once)
        srand48(Int(arc4random()))
        return UIColor(red: CGFloat(drand48()), green: CGFloat(drand48()), blue: CGFloat(drand48()), alpha: 1.0)
    }
}

 

Usage:

view.backgroundColor = UIColor.random

 

Here is the github repo for the sample project:

https://github.com/hashaam/Sample-RandomColor