In this post I will to demonstrate how you can contribute to an Open Source project hosted on GitHub. I previously blogged about how you can make and apply patches, which is certainly one way. But on GitHub there is an even cooler method, one that is also less work on the project maintainer.
The parsing of HTML necessary for my DTCoreText open source project is done entirely with the sophisticated use of NSScanner. But it has been long on my list to rewrite all of this parsing with a the industry standard libxml2 which comes preinstalled on all iOS devices. Not only is this potentially much faster in dealing with large chunks of HTML. It probably is also more intelligent in correcting structural errors of the HTML code you throw at it.
In part 1 of this series I showed you how to add the libxml2 library to your project and explained the basic concepts of using libxml2 for parsing any odd HTML snippet into a DOM. In this here part 2 we will create an Objective-C based wrapper around libml2 so that we can use it just like NSXMLParser, only for HTML.
In my previous article about Sub-Projects in Xcode I showed you how you can have an Xcode project as a dependency. The advantage of this is that you can update your library from within the same project and debug into the sub-project’s code.
One thing that was not immediately obvious was how you deal with the problem that Xcode cannot find your sub-project’s library headers. Hence this writeup.
Sometimes you want to tell somebody how you fixed a problem in their code, but for some reason the code is not on github so you cannot send them a pull request. If you felt really smart then you might put the changes you made into an e-mail, like “in file1.m:102 you change it to x, in file2.m:54 you make change y”. Thought this doesn’t really help the developer you are trying to help. Even when following your change instructions to the letter it is a tedious and error-prone method of applying your changes. Thanks to M. Douglas McIlroy, Adjunct Professor at Dartmouth Colleague – one of the early Unix pioneers – there is a better way. He invented the form of diff that we are using today to get the Difference between two versions of a file. And Larry Wall who invented the patch command which can take a diff file and effectively apply it to files. Read more
Honestly I was very much excited when I found that I can use my current knowledge of Objective-C and Foundation classes like NSString to also build nifty little tools. Previously I had to resort to bash script to perform one-off operations on files that where too tedious to do manually. But knowing what I am going to show you in this article will enable you to also write these littler helpers.
I believe that beginners should rather start with writing a couple of command line tools before diving into building user interface driven apps. Commend line tools are linear and thus their function is easier to grasp. They are more akin to “functional programming” then “object oriented programming” if you will.
I am going to show you what goes into building a simple command line tool and you be the judge whether you agree with my assessment.
A very interesting yet very undocumented functionality of Xcode is that you can have sub-projects in your project tree. You can add an xcodeproj to your project and link to this project’s output.
This is exceptionally useful if you are developing some functionality in a contained project and now want to access this polished functionality from another project. Like for example you want to add to your app the capability of accepting HTML code copied from Safari and use my DTWebArchive classes for that. You could either copy all classes to your project, build two libraries (one for Simulator and one for Device, or lipo these two together), or build a static universal framework.
Or there is an option number 4 which I want to tell you about in this post. This option does neither copy source code nor does it involve building something upfront.
I would say I have the process of submitting iOS apps down, I could probably do it blindfolded. Actually I HAVE done it blindfolded on several occasions guiding people over the phone on their very first submission.
But today I am doing it for the first time on an app for the Mac App Store (aka MAS). Let’s see if I can see this through to a successful conclusion, or at least until the ball is out of my court and with the app review team.
When starting to work on our iCatalog.framework I stumbled upon an annoying problem, the same that you will face if you ever need to work with large images. “Large” meaning of a resolution sufficient to cover the entire screen of an iPad or potentially double that (horizontally and vertically) when dealing with Retina Resolution on a future iPad.
Imagine you have a UIScrollView that displays UIImageViews for the individual pages of a catalog or magazine style app. As soon as even one pixel of the following page comes on screen you instantiate (or reuse) a UIImageView and pop it into the scroll view’s content area. That works quite well in Simulator, but when you test this on the device you find that every time you try to page to the next page, there is a noticeable delay. This delay results from the fact that images need to be decompressed from their file incarnation to be rendered on screen. Unfortunately UIImage does this decompression at the very latest possible moment, i.e. when it is to be displayed.
Since adding a new view to the view hierarchy has to occur on the main thread, so does the decompression and subsequent rendering of the image on screen. This is where this annoying stutter or pause is stemming from. You can see the same on app store apps where scrolling through something stutters whenever a new image appears on screen.
For the NSAttributedString+HTML Open Source project I chose to implement parsing of HTML with a set of NSScanner category methods. The resulting code is relatively easy to understand but has a couple of annoying drawbacks. You have to duplicate the NSData and convert it into an NSString effectively doubling the amount of memory needed. Then while parsing I am building an adhoc tree of DTHTMLElement instances adding yet another copy of the document in RAM.
When parsing HTML – and by extension XML – you have two kinds of operating mode available: you can have the Sequential Access Method (SAX) where walking through the document triggers events on the individual pieces of it. The second method is to build a tree of nodes, a Document Object Model (DOM). NSScanner lends itself to SAX, but in this case it is less than ideal because for CSS inheritance some sort of hierarchy is necessary to walk up on.
In this post we will begin to explore the industry-standard libxml library and see how we can thinly wrap it in Objective-C that it plays nicely with our code.
If you show something that contains scrollable content, i.e. UITableView, UIScrollView etc. then you want to make an adjustment when the keyboard shows so that the user can still scroll to the entire content. He wouldn’t be able to do so if you didn’t do anything.
I’ve seen several approaches to this so far, but they often hard code a certain position of the view or sizes. Like assuming that the covered view always reaches towards the bottom of the screen or always has a certain amount of space taken away from it by the status bar, navigation bar and possibly toolbar.
The whole thing gets even more complicated by the fact the the coordinate system of the app’s window is always in portrait even though your app rotates. So is the frame of the keyboard which you can get from an info dictionary in several notifications. I’ll show you the most universally working method I was able to come up with.