Regular Expressions on iOS

I’ve decided to take on the masochistic task of getting my hands dirty with NSRegularExpression. Here are some of my thoughts and findings:

– Regex is voodoo. What’s worse, it’s not even standardized. So all the tutorials on the web are not platform agnostic. I could use a recipe to match the things I’m interested in, but when creating an instance of NSRegularExpression on iOS, it fails as “invalid pattern”.
– Because of this, you WILL become a test driven developer. ūüôā
– Start with a simple regex pattern that detects PARTS of what you’re looking to match, then add complexity. This way you can see what part of your pattern is failing.
– Don’t use the Number Sign # as a matchable character. It is protected but not documented! Use \u0023 instead. e.g. “\\b
– When you map/inspect your NSTextCheckingResult objects, it should have the same number of ranges as you have capture groups. You use these to get more specific about which capture groups were involved in the match. (Provides more granularity/control). The NSTextCheckingResult.range represents the range in the text associated with that one result!
– NSRegularExpression really doesn’t deal well with the hash symbol (sharps).

I ultimately reached a solution, but it never felt entirely ‘correct’ despite finding a way to produce the correct results.

Useful “Finder” methods on NSManagedObject in Swift

I don’t know about you, but CoreData seemed insane to me before I discovered MagicalRecord, back in the days of Mogenerator and Objective-C.

But since Swift 3 has come out, and the tools have improved to support Swift development (remember poor compiler warnings, if not just a “segmentation fault 11” error), I’m finding that I like to work with the Xcode tools again, and forego these old approaches.

My old way of doing things worked very well, and in some ways I miss some aspects of that, but ultimately I quickly (swiftly… cough cough) became a lover of Swift and simply prefer developing in that language.

What I miss most were the “MagicalFinders” categories present in MagicalRecord. ¬†I found quite a concise way to do that however in Swift, and the code looks like this:

import Foundation
import CoreData

@objc public protocol CoreDataFinders {

    /// Because we are doing fetch requests on a data model,
    /// Fetch requests require sort descriptors.
    static func defaultSortDescriptors() -> [NSSortDescriptor]
}

extension CoreDataFinders where Self: NSManagedObject {
    
    public static func findAll(with predicate: NSPredicate?, context: NSManagedObjectContext) -> [Self] {
        
        let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: Self.entity().name!)
        
        let predicate = predicate
        
        fetchRequest.predicate = predicate
        fetchRequest.sortDescriptors = self.defaultSortDescriptors()
        
        do {
            let results = try context.fetch(fetchRequest)
            return results
        } catch {
            if predicate != nil {
                print("Failed to fetch objects with predicate:\(predicate!.description) error:\(error)")
            } else {
                print("Failed to fetch objects with no predicate.  error:\(error)")
            }
        }
        return []
    }
    
    public static func findFirst(with predicate: NSPredicate?, context: NSManagedObjectContext) -> Self? {
        
        let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: Self.entity().name!)
        
        let predicate = predicate
        
        fetchRequest.predicate = predicate
        fetchRequest.sortDescriptors = self.defaultSortDescriptors()
        fetchRequest.fetchLimit = 1
        
        do {
            let results = try context.fetch(fetchRequest)
            return results.first
        } catch {
            if predicate != nil {
                print("Failed to fetch objects with predicate:\(predicate!.description) error:\(error)")
            } else {
                print("Failed to fetch objects with no predicate.  error:\(error)")
            }
            
        }
        return nil
    }
}

And then you can add these to any object by either making a new baseclass in your app that subclasses NSManagedObject, or you just declare protocol support in your class definition and then these methods are added:

import Foundation
import CoreData

@objc(RecentItem)
class RecentItem: NSManagedObject, CoreDataFinders {
  static func defaultSortDescriptors() -> [NSSortDescriptor] {
    return [NSSortDescriptor(key: #keyPath(RecentItem.lastViewed), ascending: false)]
  }
  // ...
}

You can see here that you can extend this approach to pass in your own sort descriptors or limit fetch sizes, etc. This should be enough to get you started! The idea is that you can write the code once and have it apply to all instances of NSManagedObject on an opt-in basis.

Alamofire and nostalgic feelings for AFNetworking

So, in the Swift world, I presume a lot of people prefer to remain “Swifty”. ¬†That is, why would you opt for old Objective-C libraries? ¬†Out with the old, in with the new!

So, we adopt Alamofire.  Is it just me, or is this library a bit unwieldy?   I think it has a lot to do with Swift shorthand and often not knowing just what types are actually being passed around, especially given autocomplete.

On top of that, just when you get your head around a specific release, they make a new major release, breaking old APIs. ¬†And if I’m going to have to keep updating my code to stay current because “out with the old, in with the new”, why don’t I just stay with AFNetworking? ¬†I mean come on. ¬†It’s networking. ¬†For the mostpart it’s just “give me that data at that URL. ¬†Here’s my auth info.” ¬†Done. ¬†Or “here’s some data for you. ¬†Here’s my auth info.” ¬†Done.

Anyway, it’s a rant. ¬†I just don’t find Alamofire all that sexy. ¬†It reminds me of dealing with civil servants. ¬†The creators imagined this bureaucratic utopia that functions perfectly as long as everyone understands it. ¬†Furthermore, we must¬†not only understand it, but are fully on board with its vision. ¬†Meanwhile, we the people are busy trying to write our¬†own apps, and couldn’t really care less. ¬†We¬†just want to get data and post data and not have to deal with too much crap in the middle.

(Go ahead, snarky programmer. ¬†Now tell me off, tell me to just use this, that, or the other. ¬†Reject my feedback. ¬†It’s fine. ¬†All I’m saying is that AFNetworking seemed a lot easier to use.)

DataSource object for UITableView / UICollectionView in Swift with Core Data

It’s amazing how quickly I now have become a part of the Swift Fan Club. ¬†I recently worked on some old Objective-C code of mine and was amazed how quickly one learns to stop typing semi-colons. ¬†ūüôā

Today’s post is all about a pattern I use more often in my projects, and it’s one that prefers composition over inheritance. ¬†All that really means in this case is that on any UITableViewController (or similarly, UICollectionViewController), I prefer to create separate Data Source objects that keep all that code separate from the View Controller itself. ¬†(I personally don’t find that MVC stands for Massive View Controller if you don’t let it.)

The issue here is that I pretty much don’t do projects any more without using Core Data. ¬†It is the best solution in my opinion because of the code you oftentimes *don’t* have to write. ¬†Also, with NSFetchedResultsController, I like how¬†you can further separate your data layer (think Networking and importing) from you View Controllers. ¬†View Controllers concern themselves with *what* they want to display, and not with how it is acquired.

Anyway, the strictly typed language of Swift sometimes makes old approaches not straightforward, and I would like to share what I determined today.  It will become a staple in my future Swift projects.

I create a DataSource class that takes a generic type, so that this generic type can be used for Core Data related activities.  By default, a NSFetchedResultsController also takes a generic type of NSFetchRequestResult. But sometimes that is simply not enough. More on this later. To even make a Generic Data source, we have:

class BasicFetchedResultsDataSource: NSObject, NSFetchedResultsControllerDelegate where T:NSManagedObject {
    
    let managedObjectContext: NSManagedObjectContext!
    let tableView: UITableView!
    
    init(context: NSManagedObjectContext!, tableView: UITableView!) {
        
        self.managedObjectContext = context
        self.tableView = tableView
    }
    
    private var _fetchedResultsController: NSFetchedResultsController? = nil
    var fetchedResultsController: NSFetchedResultsController {
        
        if _fetchedResultsController != nil {
            return _fetchedResultsController!
        }
        
        let request = T.fetchRequest()
        request.predicate = self.searchPredicateForFetchRequest
        request.sortDescriptors = self.sortDescriptorsForFetchRequest
        let controller = NSFetchedResultsController(fetchRequest: request as! NSFetchRequest,
                                                    managedObjectContext: self.managedObjectContext,
                                                    sectionNameKeyPath: self.sectionNameKeyPath,
                                                    cacheName: self.resultsControllerCacheName)
        
        controller.delegate = self
        _fetchedResultsController = controller
        return _fetchedResultsController!
    }
    
    
    func updateRequestAndFetch() throws {
        
        self.fetchedResultsController.fetchRequest.predicate = self.searchPredicateForFetchRequest
        self.fetchedResultsController.fetchRequest.sortDescriptors = self.sortDescriptorsForFetchRequest
        
        do {
            try self.fetchedResultsController.performFetch()
            
            self.tableView.reloadData()
        }
        catch {
            throw error
        }
    }
    
    // allows your subclass to override and change this
    var sectionNameKeyPath: String? {
        return nil
    }
    
    // allows your subclass to override and change this
    var resultsControllerCacheName: String? {
        return nil
    }
    
    // allows your subclass to override and change this according to state
    var sortDescriptorsForFetchRequest: [NSSortDescriptor]! {
        return []
    }
    
    // allows your subclass to override and change this according to state
    var searchPredicateForFetchRequest: NSPredicate? {
        return nil
    }
    
    // ... Typical NSFetchedResultsController and UITableViewDataSource code here.
}

That’s it for the basics, but what if my data model is a bit more interesting? In my current project I want my data to be sortable, filterable, searchable, and possibly groupable.

So I define the following:

import CoreData
@objc protocol Sortable: NSFetchRequestResult {
    static func defaultSortDescriptors() -> [NSSortDescriptor]!
}

@objc protocol Groupable: NSFetchRequestResult {
    var groupIndex: String! { get }
}

@objc protocol RelationshipFilterable: NSFetchRequestResult {
    static func relationshipFilterPredicate(for constraintObject:NSManagedObject?) -> NSPredicate?
}

@objc protocol TextSearchable: NSFetchRequestResult {
    static func searchPredicate(for searchTerm:String?) -> NSPredicate?
}

@objc protocol MyGenericDataObject: Sortable, Groupable, RelationshipFilterable, TextSearchable {
    // combines them
}

Then the cool stuff. Subclass the Basic view controller above:

class GenericFetchedResultsDataSource: BasicFetchedResultsDataSource where T:NSManagedObject {
    
    let allowsGrouping: Bool
    let allowsTextSearching: Bool
    
    override init(context: NSManagedObjectContext!, tableView: UITableView!) {
        self.allowsGrouping = true
        self.allowsTextSearching = true
        super.init(context: context, tableView: tableView)
    }
    
    var currentSearchTerm: String? {
        didSet {
            if self.allowsTextSearching {
                do {
                    try self.updateRequestAndFetch()
                }
                catch {
                    print("Fetch Error: \(error)")
                }
            }
        }
    }
    
    override var sectionNameKeyPath: String? {
        return self.allowsGrouping ? #keyPath(MyGenericDataObject.groupIndex) : nil
    }
    
    override var resultsControllerCacheName: String? {
        return nil
    }
    
    override var sortDescriptorsForFetchRequest: [NSSortDescriptor]! {
        return T.defaultSortDescriptors()
    }
    
    override var searchPredicateForFetchRequest: NSPredicate? {
        return self.allowsTextSearching ? T.searchPredicate(for: self.currentSearchTerm) : nil
    }
}

And that’s how you can work with generics and their subclasses. It’s why protocol oriented programming and swift go together nicely!

HSHTMLImageRenderer !

So with permission of my current client (for whom I wrote the original code), I’m able to open source this component for all to use. I’m delighted I can do that because I think this component can be of good use to people.

HSHTMLImageRenderer is a way to be able to render HTML offscreen to images that can be stored in a cache. ¬†It’s useful when you have many layout elements whose content is a small bit HTML¬†that could be complicated and unsuitable for a UILabel, and it’s not feasible to have numerous instances of UIWebView everywhere.

Have a look. It’s over on my github page.

Multi-Threaded Core Data Solution

I’ve been wanting to revamp some old code that wasn’t performing as I like. ¬†I had come up with something a bit too complicated involving NSOperationQueue, fetching remote data, parsing it all in the background, then saving that to my Core Data’s¬†persistent store.

I always thought my solution a bit too complicated, and not sure it was entirely correct / robust.

I don’t know about you, but I regularly have 6-7 Google Chrome windows open with tons of tabs. ¬†I have some articles that sit there for months that I don’t want to forget about. ¬†One of which was written by Marcus Zarra, a prominent source of Core Data info. ¬†He made it look so easy.

I’ve come to enjoy Core Data as a framework. ¬†I think there is no other way at this point. ¬†And I’m sure I’ve only scratched the surface of what it can do. ¬†Along with mogenerator¬†in your build pipeline,¬†and especially the associated controller (NSFetchedResultsController) this framework is indispensable.

I basically took Marcus Zarra’s post and extended it to allow for doing data model work in the background, and also for making “scratch pad” contexts. ¬†That is, consider editing forms but then the user hits “cancel”. ¬†No rollbacks needed. ¬†Just discard the “editor” context. ¬†Or, consider data imports that run in the background, and you are on a view controller using an editor context. ¬†You can even tell that editor context to update itself with those changes that occurred in the meantime.

Anyway, all a bit vague, so I’d like to just refer you to my repository that demonstrates what I’m talking about at http://github.com/horseshoe7

Please clone it and run it.  So a search for scenarioToExamine and change that value.

UPDATE: ¬†I just found and read this article by Florian Kugler. ¬†This solution above is an implementation of his so called “Stack #2”. ¬†I really want to have a solution that’s going to be versatile and fast, so expect my repository’s implementation to change to be “Stack #3”. ¬†Will update again after this happens.

UPDATE 2: ¬†So I found my solution. ¬†It’s in the Repo. ¬†It’s called HSHybridThreeStack. ¬†It has Marcus Zarra’s asynchronous background saving context, it has Florian Kugler’s separate context for speedy importing, it has main thread editing contexts that can optionally keep themselves updated to changes resulting from these import contexts, and an API that should be pretty straightforward. ¬†You could refactor the HSCoreDataStack protocol and just incorporate it into one baseclass, but I kept it as such so that my various implementations were completely separate from one another. ¬†So there is a lot of code repeated across implementations. ¬†It is a Sandbox project after all and doesn’t represent an incredible approach to architecture.

“Invisible Container” – HSPassthroughView

I’d like to revisit an older post which deals with allowing subviews in a view hierarchy to be touchable, but making the parent view completely “non-interactive”.

Sometimes you need a ‘container view’ that can simplify¬†Autolayout Constraint animations. ¬†You want the view to be ‘invisible’ whilst allowing its subviews to behave normally. Being invisible, you may also want to tell it to inherit it’s superview’s color, so to reduce the need for layer blending (better performance)

I present the updated HSPassthroughView:

#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface HSPassthroughView : UIView

@property (nonatomic, assign) IBInspectable BOOL inheritsBackgroundColor;  // defaults to NO

@end

@implementation HSPassthroughView

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *view = [super hitTest:point withEvent:event];
    if (view == self)
    {
        NSLog(@"A view was asked for a view, but this is a QLPassthroughView.  If you see this message but expect a touch to be found, look here.");
        return nil;
    }   
    return view;  //ensure this view will never register a touch!
}
- (void)awakeFromNib
{   
    if (self.inheritsBackgroundColor && self.superview) {
        self.backgroundColor = self.superview.backgroundColor;
    }
}
- (void)willMoveToSuperview:(UIView *)newSuperview
{
    if (self.inheritsBackgroundColor) {
        self.backgroundColor = newSuperview.backgroundColor;
    }
    [super willMoveToSuperview:newSuperview];
}
@end

This helped solve a problem I had that was on StackOverflow.