Extraction is alway an interesting refactoring operation. The tranditional approach of extracting a single field or method generally isn’t too bad. It can sometimes take a while, but overall you’re copying a few fields, deleting the crossover, and done. Extraction of an object with multiple responsibilities is a different task entirely. Intertwined state I’ve got to say is the most difficult. If statements scattered throughout mutliple methods to achieve the desired strategy is probably the worst of it.

Refactoring can sometimes shake out defects in the software. In this case the synchronization error mysteriously appeared again. I got the application back into a deterministicly failing state by playing around with the dispatch queue. Alrighty, creating a serial queue makes that super easy, now all the tests correctly pass regardless of battery power.

Ran into a problem with mtynior/SwiftyLogger’s BaseTargetLogger not using the new open access modifier from Swift 3. The open modifier explicitly marks a class as extensible from other modules. Interesting Apple is adding additional rules around extension and modifications of classes. Anyway, I created an example project as a demonstration of behavior, and submitted a pull request.

While I would love to have the time to wait for the pull request ot be accepted, I need to use the patch now. Onto figuring out how to use git based pods. Easy enough, setting the properties :git to the repository and :branch to the target branch. For example pod 'SwiftyLogger', :git => "https://github.com/meschbach/SwiftyLogger", :branch => "BaseLoggerTarget-Swift3".

Back to integrating the TargetLogger into SwiftyPaperTrail. Thinking through the use case as it was originally designed, most of these fields don’t really make too much sense. The logger factory didn’t use the builder pattern like the docs said. Maybe I missed something. Nope, looking at the history the file hasn’t been updated to follow the documentaiton.

On to verifying reads. The interface doesn’t allow for notifying us when a write is complete, so I have to figure out how to sync without that. NSPredicate can be passed as an argument to the expectation statements, so I’ll have to try this one. So looks at the docs it seems promising but I’m not really like the idea of passing a string. I just used a delayed async loop to await operations like the following:

        let change = expectation(description: "Log line will be recorded")
        func check(){
            if buffer.writes.count > 0 {
                change.fulfill()
            } else {
                DispatchQueue.main.async(execute: check)
            }
        }
        check()

And done.