Sunday, September 11, 2016

Create a view from a .xib file easily

I always forget the underlying details of creating a view from a .xib file.

Bundle.instantiateNibWithName("MyNibName") as! MyNib // uhhh, what??

😩 That is what I normally end up writing on the first stab... Clearly that is completely wrong. I wish there was a way to get the .xib to a UIView subclass in a much less complicated way. And THERE IS! 😁

Just have your UIView subclass conform to NibInstantiating and you just have to remember the very intuitive words viewFromNib rather than Bundle(for: TheClass.self).loadNibNamed("UghAString", owner: nil, options: nil).

class TextInputBar: UIView, NibInstantiating {
to instantiate, just call viewFromNib

let inputBar = TextInputBar.viewFromNib()

Isn't that so much nicer on the brain!?

Here's the protocol and extension:


protocol NibInstantiating: class {
    static var nibName: String { get }
}

extension NibInstantiating {
    
    static func viewFromNib() -> Self! {
        var view: Self!
        let objects = Bundle(for: self).loadNibNamed(nibName, owner: nil, options: nil)
        for object in objects! {
            guard let foundView = object as? Self else { continue }
            view = foundView
            break
        }
        assert(view != nil, "Could not find object of type: \(Self.self) \(#function)")
        return view
    }
    
    static var nibName: String { return String(describing: Self.self) }

}


To download the code, click here: NibInstantiating.

Wednesday, September 7, 2016

Adjust UITableView for Keyboard in Swift

You've got a table full of cells. Now you add a text input of some kind. I used to avoid this whenever possible because it was so aggravating trying to show the last few cells above the keyboard. I used to do something similar every time, but it always changed a little and there were always annoying bugs that never seemed to die.

`TableViewInsetsAdjusting` to the rescue!

final class ExampleTableViewController: UITableViewController, TableViewInsetsAdjusting {
    
    private var inputBar: TextInputBar = TextInputBar.viewFromNib()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupInsetAdjust()
    }
    
    override func canBecomeFirstResponder() -> Bool {
        return true
    }
    
    override var inputAccessoryView: UIView? {
        return inputBar
    }
    
    deinit {
        takeDownInsetAdjust()
    }
    
}

Just conform to TableViewInsetsAdjusting, call `setupInsetAdjust` and you'll have your insets adjusting automatically for you whenever the keyboard comes up.

Don't forget to call `takeDownInsetAdjust` on your way out.

That's it!!! All your problems are now solved!

Here's the repo: TableViewInsetsAdjusting Repo

Tuesday, December 22, 2015

Core Data Deletion Rules Simplified

Person
- shoes (to many to 'Shoe')
         deletion rule is set to cascade


Shoe
- person (to one to 'Person')
        deletion rule is set to nullify

When I delete a 'Person' record all of person.shoes will be deleted as well.

When I delete a 'Shoe' record, shoe.person will not be deleted, rather the person.shoes relationship that used to be there will now be broken and the shoe reference nulled out and it will not have a reference to that shoe.

Wednesday, February 18, 2015

How to get a raise

I made an app called Schotzy.  It helps people get backing to ask your boss for a raise.  You can also anonymously see exactly how much others get paid.

When you first open the app you'll see a profile.  Estimate how much that person makes and you'll see  how much they make.  Make sure you make a good estimate because your score will depend on it.  Sign up with the app to let others estimate how much you make so you can see what others think you should be getting paid.  Show this to your boss when you ask for a raise.

Check it out here: Schotzy



Saturday, September 20, 2014

NSFetchedResultsController in Swift


NSFetchedResultsController in Swift


    lazy var fetchedResultsController: NSFetchedResultsController = {
        let moc = CoreDataTools.sharedInstance.managedObjectContext!
        let entity = NSEntityDescription.entityForName("Certificate", inManagedObjectContext: moc)
        
        let fetchRequest = NSFetchRequest(entityName: NSStringFromClass(Certificate))
        fetchRequest.entity = entity
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: true)]
        
        var frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
        var error: NSError? = nil
        frc.performFetch(&error)
        if let e = error {
            println("Error was \(e)")
        }
        return frc

    }()

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        var count = 0
        if let s = self.fetchedResultsController.sections as? [NSFetchedResultsSectionInfo] {
            count = s[section].numberOfObjects
        }
        return count

    }


    lazy var collectionView: UICollectionView = {
        var layoutView = UICollectionViewFlowLayout()
        layoutView.sectionInset = UIEdgeInsetsMake(0, 10, 0, 10)
        layoutView.scrollDirection = UICollectionViewScrollDirection.Horizontal
        layoutView.itemSize = CGSizeMake(100, 100)
        layoutView.minimumLineSpacing = 10
        layoutView.minimumInteritemSpacing = 5
        var colView = UICollectionView(frame: CGRectZero, collectionViewLayout: layoutView)
        colView.setTranslatesAutoresizingMaskIntoConstraints(false)
        colView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "CertificationCellReuse")
        colView.delegate = self
        colView.dataSource = self
        colView.backgroundColor = ThemeFactory.sharedInstance.appSecondaryColor()
        colView.bounces = true
        colView.alwaysBounceHorizontal = true
        colView.scrollIndicatorInsets = UIEdgeInsetsMake(0,0,3,0)
        colView.indicatorStyle = UIScrollViewIndicatorStyle.Black
        return colView

    }()

Monday, September 15, 2014

ABAddressBookRef Filter through ABRecordRefs

Here's a way to filter some phone contacts:

        ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
        CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
        CFMutableArrayRef peopleMutable = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
        if (people) {
            NSInteger numberOfPersonsInAB=CFArrayGetCount(people);
            for (int i =0; i< numberOfPersonsInAB; i++) {
                ABRecordRef record = CFArrayGetValueAtIndex(people, i);
                NSString *note = (__bridge NSString *)(ABRecordCopyValue(record, kABPersonNoteProperty));
                if ( note != nil &&  ([note rangeOfString:@"hi"].location != NSNotFound)) {
                    CFArrayAppendValue(peopleMutable, record);
                }
            }
            CFRelease(people);

        }

Friday, September 12, 2014

Check out Riffle Raffle

This is a simple Raffle app designed to allow you to make and save your own raffles.  This is on the iOS App Store, for iPhone and iPad.

Riffle Raffle