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