Extract Single Image from Video

Get that favorite frame from video

Extract single image from video using the following code:

ffmpeg -i video.mp4 -ss 00:00:00.000 -vframes 1 image.jpg

-ss will ask ffmpeg to seek these many seconds and start processing
-vframes with this parameter we are extracting 1 frame

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)!

Adjust Scroll View Content Inset Based on Keyboard Frame

Reveal text fields in form when keyboard is shown/hidden

In cases where we have form containing UITextFields embedded in UIScrollView, when keyboard is shown and hidden, we want UIScrollView to be adjusted accordlingly.

We start in the viewWillAppear method by adding the following code:

// https://hashaam.com/2017/09/02/adjust-scroll-view-content-inset-based-on-keyboard-frame
override func viewWillAppear(_ animated: Bool) {
NotificationCenter.default.addObserver(self, selector: #selector(adjustForKeyboardHandler(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(adjustForKeyboardHandler(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

Then we define the method to handle keyboard notifications:

// https://hashaam.com/2017/09/02/adjust-scroll-view-content-inset-based-on-keyboard-frame
func adjustForKeyboardHandler(notification: Notification) {
// this method assumes scrollView is defined
guard let userInfo = notification.userInfo else { return }
guard let value = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
let keyboardFrame = value.cgRectValue
var contentInset: UIEdgeInsets!
switch notification.name {
case Notification.Name.UIKeyboardWillHide:
contentInset = UIEdgeInsets(top: 64.0, left: 0.0, bottom: 0.0, right: 0.0)
case Notification.Name.UIKeyboardWillChangeFrame:
contentInset = UIEdgeInsets(top: 64.0, left: 0.0, bottom: keyboardFrame.size.height, right: 0.0)
default:
break
}
scrollView.contentInset = contentInset
scrollView.scrollIndicatorInsets = contentInset
}

This single method handles both cases, with keyboard shown or hidden states.

Notice the top: 64.0 is because of status bar height 20.0 and navigation bar height 44.0. If you do not have UIViewController in embedded in UINavigationController or the navigation bar is hidden, you can set the top value to 20.0

Get Specific URLQueryItem from URLComponents

Consider the following URL:

http://www.example.com/?utm_source=adsite&utm_campaign=adcampaign&utm_term=adkeyword

We are interested in the query parameter value of utm_term. We can parse the URL using the following code:

// https://hashaam.com/2017/09/02/get-specific-urlqueryitem-from-urlcomponents
func queryParam(urlString: String?, param: String) -> String? {
guard let urlString = urlString else { return nil }
guard let urlComponents = URLComponents(string: urlString) else { return nil }
guard let queryItems = urlComponents.queryItems else { return nil }
return queryItems.filter { queryItem in
return queryItem.name == param
}.first?.value
}

And call the function using:

Get filename without extension

Consider the following filename:

hls_a128_v4.m3u8

We are interested in getting filename only (without extension). We can do so with the help of following code:

// https://hashaam.com/2017/09/02/get-filename-without-extension
let path = "hls_a128_v4.m3u8"
let url = URL(string: path)
let filename = url?.deletingPathExtension().lastPathComponent
print(filename) // hls_a128_v4
let fileExtension = url?.pathExtension
print(fileExtension) // m3u8

UIWindow Presentation Context

Get top most presented UIViewController of UIWindow

There are times when we need to get top most presented UIViewController. We can do so with help of an extension of UIWindow. Consider the following code:

// https://hashaam.com/2017/08/31/uiwindow-presentation-context/
extension UIWindow {
func presentationContext(context: UIViewController? = nil) -> UIViewController? {
var presentationContextViewController = rootViewController
if let context = context {
presentationContextViewController = context
}
if presentationContextViewController?.presentedViewController == nil {
if let navigationController = presentationContextViewController as? UINavigationController {
return navigationController.topViewController
}
return presentationContextViewController
}
return presentationContext(context: presentationContextViewController?.presentedViewController)
}
}

Then we can call using:

// https://hashaam.com/2017/08/31/uiwindow-presentation-context/
if let delegate = UIApplication.shared.delegate, let window = delegate.window, let viewController = window?.presentationContext() {
// perform action on viewController
}

Sample: Working Example of Background Audio Mode with Displaying Information in Command Center and Handling Remote Control Commands

I have previously written separate articles:

Here is the sample project: MediaPlayerExample

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)