Get all resource paths in bundle recursively

I’ve been looking for a way to search a subdirectory in my main bundle recursively – the following simple Swift extension does the trick.

I’ve been looking for a way to search a subdirectory in my main bundle recursively – the following simple Swift extension does the trick.

Bundle.main.paths(forResource: String?, ofType: String?) -> [String]?


let paths: [String]? = Bundle.main.paths(forResource: "my-resource", ofType: "my-extension")

Bundle.main.urls(forResource: String?, withExtension: String?) -> [URL]?

let urls: [URL]? = Bundle.main.urls(forResource: "my-resource", withExtension: "my-extension")

The source code of the extension

import Foundation

extension Bundle{
    
    func urls(forResource name: String?, withExtension ext: String?) -> [URL]?{
        guard let resourceURL = self.resourceURL else{ return nil }
        let enumerator = FileManager.default.enumerator(at: resourceURL, includingPropertiesForKeys: nil)
        
        var urls = [URL]()
        while let url = enumerator?.nextObject() as? URL{
            guard ext == nil && url.lastPathComponent == name || ext == url.pathExtension && url.deletingPathExtension().lastPathComponent == name else{
                continue
            }
            urls.append(url)
        }
        
        return urls.count > 0 ? urls : nil
    }
    
    func paths(forResource name: String?, ofType type: String?) -> [String]?{
        return self.urls(forResource: name, withExtension: type)?.map{ $0.path }
    }
}

Eureka ContactRow in Swift

A custom row for the elegant iOS form builder in Swift 2 called Eureka:

ContactRow

Select an existing contact from the iOS AddressBook using the new iOS 9 CNContact API – request for integration pending.

import Foundation
import Contacts
import ContactsUI
import Eureka


public class _ContactRow: Row<String,ContactCell> {
    required public init(tag: String?){
        super.init(tag: tag)
    }
}


public final class ContactRow: _ContactRow, RowType{

    required public init(tag: String?) {
        super.init(tag: tag)
        self.displayValueFor = nil
    }
}

public class ContactCellOf<T: Equatable>: Cell<T>, CellType, CNContactPickerDelegate {
    required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }


    public override func setup(){
        super.setup()
        self.bindContact()
    }


    public override func update() {
        super.update()
        self.bindContact()
    }


    private func bindContact(){
        switch CNContactStore.authorizationStatusForEntityType(.Contacts){
        case .Authorized: //Update our UI if the user has granted access to their Contacts
            selectionStyle = row.isDisabled ? .None : .Default

            if let id = self.row.value as? String, let contact = contactFromIdentifier(id){
                detailTextLabel?.text = CNContactFormatter.stringFromContact(contact, style: .FullName)
            }

        case .NotDetermined: //Prompt the user for access to Contacts if there is no definitive answer
            CNContactStore().requestAccessForEntityType(.Contacts) { granted, error in
                dispatch_async(dispatch_get_main_queue()){
                    self.row.disabled = Condition.init(booleanLiteral: !granted)
                    self.selectionStyle = self.row.isDisabled ? .None : .Default

                    if granted, let id = self.row.value as? String, let contact = self.contactFromIdentifier(id){
                        self.detailTextLabel?.text = CNContactFormatter.stringFromContact(contact, style: .FullName)
                    }
                }
            }

        case .Denied, .Restricted:
            self.row.disabled = true
            selectionStyle = row.isDisabled ? .None : .Default
        }
    }


    private func contactFromIdentifier(identifier: String) -> CNContact?{
        do{
            return try CNContactStore().unifiedContactWithIdentifier(identifier, keysToFetch: [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName)])

        } catch let error as NSError{
            NSLog(error.localizedDescription)
            return nil
        }
    }


    public override func didSelect() {
        super.didSelect()

        let controller = CNContactPickerViewController()
        controller.delegate = self

        self.formViewController()?.presentViewController(controller, animated: true, completion: nil)
    }


    public func contactPicker(picker: CNContactPickerViewController, didSelectContactProperty contactProperty: CNContactProperty){
        if contactProperty.contact.isKeyAvailable(CNContactIdentifierKey), let id = contactProperty.contact.valueForKey(CNContactIdentifierKey) as? T{
            self.row.value = id

        } else {
            self.row.value = nil
        }
    }
}
public typealias ContactCell = ContactCellOf<String>