Play Music in iOS

Here’s a utility to play background music for iOS in Swift:

First, import AVFoundation. Then add:

var backgroundMusicPlayer: AVAudioPlayer!

func playBackgroundMusic(filename: String) {
    let resourceUrl = Bundle.main.url(forResource: filename, withExtension: nil)
    guard let url = resourceUrl else {
        print("Could not find file: \(filename)")
    do {
        try backgroundMusicPlayer = AVAudioPlayer(contentsOf: url)
        backgroundMusicPlayer.numberOfLoops = -1 // endless loop
    } catch {
        print("Could not create audio player")

Use it like this:

playBackgroundMusic(filename: "backgroundMusic.mp3")


Generic Alert Method

Here is a generic alert method that you can place in a global functions/variables file that checks for an existing alert first.

func showAlert(withTitle title: String, message: String, viewController: UIViewController) {
    if viewController.presentedViewController == nil { // Prevent multiple alerts at the same time
        let localizedTitle = NSLocalizedString(title, comment: "")
        let localizedMessage = NSLocalizedString(message, comment: "")
        let alert = UIAlertController(title: localizedTitle, message: localizedMessage, preferredStyle: .Alert)
        let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
        viewController.presentViewController(alert, animated: true, completion: nil)


Get Timestamps

This is just a random method I’m no longer using and wanted to get rid of but didn’t really want to throw it away in case I want to reference it someday.

static func getTimestamps(forEntry entry: Entry?) -> [String: Int] {
    let calendar = NSCalendar.currentCalendar()
    let formatter = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    var since = NSDate()
    var until = NSDate()
    if let entry = entry {
        if let createdAt = entry.created_at {
            // get date portion only of createdAt
            let entryDateComponents = calendar.components([.Day, .Month, .Year], fromDate: createdAt)
            // set the time to midnight and the last second
            let entryDateBegin = "\(entryDateComponents.year)-\(entryDateComponents.month)-\( 00:00:00"
            let entryDateEnd = "\(entryDateComponents.year)-\(entryDateComponents.month)-\( 23:59:59"
            since = formatter.dateFromString(entryDateBegin)!
            until = formatter.dateFromString(entryDateEnd)!
    } else {
        let currentDateComponents = calendar.components([.Day, .Month, .Year], fromDate: NSDate())
        let currentDateBegin = "\(currentDateComponents.year)-\(currentDateComponents.month)-\( 00:00:00"
        let currentDateEnd = "\(currentDateComponents.year)-\(currentDateComponents.month)-\( 23:59:59"
        since = formatter.dateFromString(currentDateBegin)!
        until = formatter.dateFromString(currentDateEnd)!
    let sinceTimestamp = Int(since.timeIntervalSince1970)
    let untilTimestamp = Int(until.timeIntervalSince1970)
    return ["since": sinceTimestamp, "until": untilTimestamp]


Add Share Button to iOS 9 App

@IBAction func export(sender: UIBarButtonItem) {        
    if let data = prepareCSVData() {
        let filename = getDocumentsDirectory().stringByAppendingPathComponent("data.csv")
        data.writeToFile(filename, atomically: true)
        let url = NSURL(fileURLWithPath: filename)
        let activityViewController = UIActivityViewController(activityItems: [url], applicationActivities: nil)
        if let popoverController = activityViewController.popoverPresentationController {
            popoverController.barButtonItem = sender

        presentViewController(activityViewController, animated: true, completion: nil)

    } else {
        NSLog("Unable to prepare data")

The important line is where you set up the popoverController. Without that, it will crash on iPad.

Send Mail with Attachment in iOS

if MFMailComposeViewController.canSendMail() {
    let data = prepareCSVData()
    let mailController = MFMailComposeViewController()
    mailController.mailComposeDelegate = self
    mailController.setSubject("Data Export")
    mailController.setMessageBody("Attached is a CSV file containing your data.", isHTML: false)
    // Add attachment
    if let data = data {
        mailController.addAttachmentData(data, mimeType: "text/comma-separated-values", fileName: "headaches.csv")
        presentViewController(mailController, animated: true, completion: nil)
    } else {
        NSLog("No data")


Prevent “Array index out of range” Error in Swift

If you don’t know if the array index you are calling exists, here is a nice way to just return nil instead of an error. I grabbed this from StackOverflow but unfortunately lost the link. I am putting it here because I use it once in a while and get tired of searching for it.

extension Array {
    subscript (safe index: Int) -> Element? {
        return indices ~= index ? self[index] : nil

Use it like this:

array.item[safe: 1]


Scroll to the Bottom of a Collection View

private func scrollToBottom() {
    let lastSectionIndex = (collectionView?.numberOfSections())! - 1
    let lastItemIndex = (collectionView?.numberOfItemsInSection(lastSectionIndex))! - 1
    let indexPath = NSIndexPath(forItem: lastItemIndex, inSection: lastSectionIndex)
    collectionView!.scrollToItemAtIndexPath(indexPath, atScrollPosition: UICollectionViewScrollPosition.Bottom, animated: false)