Core Graphics, Part 3: Lines
Consider the humble line—just a straight sequence of pixels connecting two points. There are well-known algorithms you can use to do your own drawing, but these days, we have toolkits to do the hard work.
Advanced Mac OS X Instructor Mark Dalrymple, author of Advanced Mac OS X Programming, has been a Macintosh programmer since 1985 and a professional unix programmer since 1990. Mark has experience on the client side and server side, being a veteran of several startups, and larger technology operations like AOL and Google. On the back-end, he has been the technical lead for AOLserver, a high-performance web server handling tends of thousands of hits per second on many different unix platforms (Linux, HP, SGI, Digital Alpha, Solaris). On the client-side, he has worked with native Mac toolkits, helped in the construction of cross-platform toolkits, and currently has code running on millions of Macintosh desktops world-wide.
In addition to being the principal author of both “Advanced Mac OS X Programming”, Mark is principal author of “Learn Objective-C on the Macintosh”, and has been the technical reviewer for many Cocoa and iPhone titles with Apress. He is also the co-founder of CocoaHeads, the international Mac programmer’s group, with chapters in 26 countries on five continents.
Consider the humble line—just a straight sequence of pixels connecting two points. There are well-known algorithms you can use to do your own drawing, but these days, we have toolkits to do the hard work.
You need to interact with the current Core Graphics context in some manner to actually draw stuff, so it’s good to get comfortable with it, what it does, and why it’s there.
Mac and iOS developers have a number of different programming interfaces to get stuff to appear on the screen. UIKit and AppKit have various image, color and path classes. Core Animation lets you move layers of stuff around. OpenGL lets you render stuff in 3-space. SpriteKit lets you animate. AVFoundation lets you play video.
…and upon looking into the face of indescribable horror, a bug so unfathomably odd that it shook the foundations of all meager human beings, I was overcome by an indistinct feeling of dread and approximate horror previously unfamiliar to me.
Sometimes you stumble across a file. It might be something random in your Documents folder. It might be something a parent or a client sent you. Unfortunately, you have no idea what it might be. Files don’t have to have extensions on the Mac, so there’s not much hint what “Flongnozzle-2012” might contain. But if you’re comfortable in the Terminal, you have some built-in tools to help you identify files.
After WWDC, there are new SDKs (Software Development Kits), APIs (Application Programming Interfaces) and new languages to play around with, along with the usual extensions to existing interfaces. Getting up to speed quickly with a new SDK, especially a pre-release SDK, can mean the difference between having a good time with new software toys or becoming angry and making those around you miserable.
I love stories. I love telling stories, and I love listening to stories. I learn from stories. I believe that we, as a programming community, don’t tell enough personal stories around the campfire.
I’m a big fan of caveman debugging. That is, using log statements to gather information and visualize a program’s control flow. But I only use it very tactically: I need this one piece of information. Add a log or two and see what I get. Once I solve the problem I take out the logs before sending the code out for review and checking it in. I consider caveman debugging different from the logging an app does to report its activity or health. This should be designed like any other feature, and not be dependent upon developers randomly scattering log statements around the code base.
I’ve talked about stochastic profiling in the past, such as the fairly recent Rock Heads. It’s something I mention when I talk about debugging or performance tuning at various conferences. Interestingly enough, I had a need for it last night because I had stumbled into an often-reported, difficult-to-reproduce problem and wasn’t in a situation to hook up Instruments.
One of the wonderful(?) things about Objective-C is that it’s based on C. Part of the power of C is bit-bashing, where you can manipulate individual bits inside of a piece of memory. Have a bunch of boolean values but don’t feel like wasting a byte or two for each one? Represent them as individual bits! Luckily we tend not have to do this a lot of these days given the massive amounts of memory that we have to play with, even on iOS devices. That being said, there are times where bitwise operations appear in the Cocoa APIs, so it’s good to be comfortable with a couple of basic operations.
The Instruments Time Profiler is a common tool to use when finding out how much CPU time is being consumed for an operation, either directly by a function or a method, or on behalf of some other piece of code. You might discover that your image drawing is causing huge amounts of image conversion inside of Quartz. You’d then make sure your image is in a state that makes it draw faster.
Part of the fun of teaching a live class is fielding questions and thinking on your feet. Once I was showing some code that used @properties extensively in the interface, and one of the students asked “What are all the little fiddly bits that go after the
@property? I’ve used retain and assign and nonatomic, but don’t really know what they really do.” (There’s a TL;DR at the end of all the
@property attributes if you just want a quick cheat-sheet.)
Even though Apple is known for limiting what you can do on iOS compared to Mac OS X, they actually provide you with some information about the OS and hardware environment you’re running in, assuming you know where to look. Here I’ll be looking at three different places to accumulate this info: the
NSProcessInfo, the application bundle, and a Unix system call.
I sometimes see the question “How do I cast a method into a function pointer?” come up during classes or on some form of social media. One problem programmers have, which asking questions, is phrasing the question too specifically. In this case, the real question is “How do I use an Objective-C method as a callback for a C library?” Casting a method to a function pointer is one possible way of solving the problem. Is it the right way?
Last time you saw the parts of the Objective-C runtime API that let you query a bunch of the metadata the compiler keeps around once it’s done building your project. Like most discussions of API, it was pretty abstract. “Look at all the pretty tools! Ooh, we can print out Lists of Stuff! Isn’t that amazing!”
Behold, the Objective-C Runtime API. Here are the tools to let you peer into the metadata that the Objective-C compiler keeps around. Here are the tools that let you manipulate the underlying data structures. Here be the gateway to information and control. Here also be some sharp corners.
Last time we took a look at the motivations behind Objective-C message sending. It’s a layer of indirection that lets one chunk of code treat other, perhaps unrelated, chunks of code in a uniform manner. “I have a pile of views here, I shall draw them all with
-drawRect:, and I don’t care if the views are Buttons, Sliders, or World Maps.” There’s a loop that hits a collection and sends the same message to a bunch of objects:
_Here’s some links for the whole series:
So. That Clash of the Coders Thing. Kind of nice being able to flex mental muscles over a 72-hour sleep-deprived Dr Pepper-infused period of time, performing acts of violence upon the Objective-C runtime,
UIApplication, and the layer stack. It was a blast being able to use all my platform knowledge with the express purpose of subverting it.
Instruments is a cool tool. There is a lot it can do beyond “simple” things like profiling your application’s execution time or finding your memory leaks. It can also give you holistic views of the activity on a device, such as power consumption.
You can find all sorts of interesting and useful stuff in Apple’s header files. Don’t be afraid to explore them. I usually troll through the headers when a new major SDK version comes out (like IOS 7 probably will be this year) to see what’s new. I also use them for API exploration. As always, when in doubt be sure to read the official documentation. Apple’s documentation is good. It’s also voluminous. But once you’ve marinated in a framework for awhile, you know how things work and might only need a refresher or a nudge in the right direction. These days I usually spelunk in the headers, and then hit the docs if I’m not sure what the headers are trying to tell me.
If anyone would have told me 30 years ago that I’d actually enjoy writing, that I’d look forward to writing something new, that I’d earn part of my living from the act of writing, I would have sent them straight to a psychiatrist. Obviously they’re insane.
Just got back from the DC area, where some fellow Ranchers and I went to CocoaConf. If you’re not familiar with CocoaConf, it’s a traveling technical conference for Mac and iOS developers. I like to call it a peripatetic conference, where Dave Klein (who runs the conference) travels around with his family to different cities and puts on a great conference. There are conferences coming up in Dallas April 4, and in San Jose April 18.
Simple questions can be fun. A friend in the Pittsburgh CocoaHeads said “Hey MarkD. We’re having a discussion at work on the right way to iterate through an NSArray. One dude said to just use the
for...in syntax, and the other said that we should always use the block based iteration form. What do you think?”
I lied. Sorry. I thought this dive into DTrace would be a three-parter, but here’s a part 4, on static probes, suggested in a comment by Chris last month.
As you’ve seen before, DTrace can give you a huge amount of visibility into the guts of your computer. You saw the
syscall provider which lets you attach probes to system calls, those functions that let you take advantage of services from the kernel. You also saw the
pid provider which lets you look inside individual processes and trace the function activity inside of there.
The other day I was chatting with one of my colleagues at the Ranch and he asked me where I get my blog ideas. One fertile idea-ground is what sometimes happens during day-to-day work, solving a potentially hard problem in a way that’s actually pretty easy. And then I discover there’s a fair amount of ground work needed to understand it. Hence these multi-part War and Peace epics.
Last fall I took a week off to escape from the world. I assigned myself three tasks for that time: disappear and recover from a number of stressful deadlines, clean up my office area (affectionately known as “my cage”), and learn about CocoaTouch gesture recognizers. I ended writing a little tool for playing around with gesture recognizers that I called GestureLab.
Grand Central Dispatch, a.k.a libdispatch and usually referred to as GCD, is a low-level API known for performing asynchronous background work.
dispatch_async is its poster child: “Throw this block on a background thread to do some work, and inside of that block toss another block on the main thread to update the UI.”
Building small prototypes outside of your main code base can let you experiment with new technology and APIs. An interesting question is, where does that code live? In your $HOME? In a “Projects” github or bitbucket repository? Or maybe they should live next to the project the work was done for.
I’m becoming a conference junkie.
Source code control. What is it? Why would you want to use it?
Executive summary: If you’re not using source code control, you need to be.
Geometry is everywhere in modern programming. We have to know how to deal with points, sizes, and rectangles. Back in the old days we’d use
NSRect. These types were bitwise-identical with their Core Graphics counterparts (
CGRect), but weren’t type miscible, so you had to play games to use use one where another was wanted. With modern flavors of Cocoa, we can use them interchangeably. If you’re looking at a codebase that has both NSBlah and CGBlah for basic geometrical types, rest assured they’re the same at the bit-level.
Fast Enumeration, part 1 covered what fast enumeration is. Part 2 covered the method
countByEnumeratingState, which is the centerpiece of fast enumeration. This time around there’s actual code which implements a collection that can be fast enumerated, without cheating and falling back on one of Apple’s collections.
Fast Enumeration, part 1 covered what fast enumeration is,
NSEnumeration a bit, and introduced adopting fast enumeration in your own classes by doing a simple pass-through to Apple’s collections. This time around it’s time to look deeper at the central Fast Enumeration call, which I’ll refer to as
Fast Enumeration was introduced into Objective-C back in the 10.5 days. It’s the feature that lets you succinctly iterate through a collection:
I’ve been lucky enough to have gotten to tech review a number of Mac and iOS programming books. I find the process very enjoyable, if a bit time-consuming. I assume I do a decent job because publishers and authors come back to ask me to review subsequent editions of books, or entirely new books.
This question came up in an IRC channel the other day: “What’s the best way to set up a property that’s read-only externally, but modifiable inside of the class, so I can use properties or KVC to change it?”
__unsafe_unretained. That sounds pretty scary. It’s a new symbol added by ARC that’s used to decorate pointers. It pops up in Xcode’s autocomplete occasionally, and sometimes you see it in code you find on the net. What is it? When would you want to use it?
I usually encounter two classes of bugs on a regular basis. The first is of the form “I think I know where this is” which won’t take long to find. The steps are pretty easy: Figure out how to reproduce it. Set a couple of breakpoints. Add some caveman debugging. Find the problem and fix it. These are my favorite kind of bugs because they’re over and done with quickly, I can get a quick hit of that “you done did good” glow from making a software system better, and then move on to some more interesting problem.
When I’m developing new code, my usual habit is to do a lot of small iterations. That gives me a little bit of success fairly often. I’m not as happy if I have to work for a long time until I can see something appearing on the screen.
You know that sinking feeling in your stomach. That horrible emotion that you know that something has gone wrong, seriously wrong, and you’re going to be facing a mountain of pain. That terror that’s even worse than your significant other sitting you down saying “we need to talk”. It’s this:
As happens occasionally, an interesting technical discussion ensues in an IRC channel. Earlier this week, this question came up why does Apple do this to most of their
enums in the Cocoa headers:
Ever have one of those moments, after a flurry of activity, and realized what you’ve accomplished? Now that this summer is over, I realized that I’ve talked a lot. Three CocoaHeads presentations. Back-to-back 90 minute sessions at two CocoaConfs. Taught a week-long class with some extra evening sessions. Granted, that’s not a lot considering some folks who teach week-long classes a couple of times a month, or professional speakers out on a circuit, but for Just Some Dude who’d rather be writing software, it’s a lot.
In case you missed it, I (markd) appeared on NSBrief, interviewed after CocoaConf DC. I think we started around midnight, which is why Saul Mora and I are pretty punchy.
Cocoa has a number of classes that can hold arbitrary amounts of Stuff. Things like arrays, dictionaries, sets, index sets, character sets, strings, data, strings, and so on. These classes come in two flavors, mutable and immutable.
I like warnings. I really do. It reminds me that the compiler loves me and is looking out for me. (OK, the compiler at least tolerates me.)
You know that feeling. You’re on a deadline. It’s 9:00 at night. You have a demo the next morning. Suddenly Xcode freaks out. Apps running half the time. Rebooting your phone. Rebooting your computer. Finally the phone decides to run your App for awhile.
Ever be coding along, giddily hooking objects together and doing that voodoo that you do so well, and all the sudden you hit a wall. Things stop working. You’ve hit, what could be, A Bug. “Can this really be broken? What’s going wrong?” And then you’re stuck in a gumption trap , shaving yaks until you can get back to your important work.
Just got back from a weekend at CocoaConf down in Herndon VA. A lot of great sessions from Ranch folks, and from everyone else as well. One of my favorites was the session Chad Sellers from Useful Fruit had on Text, covering the text system from
NSString up through
NSTextView and back down to Core Text. I learned stuff.
I’m a fan of Caveman Debugging, where you use print statements to trace program flow and display specific program information. I was kind of surprised when reading Coders at Work how many industry luminaries do the same thing. It’s just another tool in the debugging arsenal, along with unit tests, debuggers, Instruments, and the plethora of other software investigation toys.
Today’s topic was suggested by Paul Bruneau - thanks!
Apple’s WWDC is next week! Woot! But I know a lot of folks can’t make it to WWDC. There are a number of conferences happening over the summer for folks to get their technical info fix.
I got a question from a friend of mine the other day:
Saving data to the file system and reading it back is a pretty common operation. One of the first ways many Cocoa and iOS programmers learn to read and write are by using the convenience functions provided by
NSData, and friends.
writeToURL:atomically: for writing and
dictionaryWithContentsOfURL: for reading.
Instruments is a very cool profiling application, but it’s one of those things that’s kind of hard to write about. You can outline the features it has, create some contrived debugging situations (“oh look, I’ve introduced a memory leak where no sane person could have accidentally created one.”), and make some pretty screen shots.
Update October 2013 - On 64-bit iOS (device and simulator)
BOOL is now actually
bool, so the sharp corners have thankfully gone away for that platform. For everything else, though…
If you’re an iOS programmer who only programs CocoaTouch, I want to encourage you to give desktop Cocoa a try. I’ve primarily been shipping iOS software for the last two years, but I’ve also been doing a fair amount of Cocoa programming on the desktop during that time, either writing helper tools or implementing parts of the iOS app on the desktop.
Every now and then I get a question about an idiom I use for looping through a collection of literal structures. This is handy for little lookup tables, or using pre-defined data to populate another data structure.
An idiom used by some Objective-C programmers is prefixing instance variable names with underscores. You do see this with explicitly declared instance variables:
One of the directions Apple is taking in Objective C that I’ve come to really like is the migration of stuff out of header files. I’m a firm believer that header files should only contain the public programming interface, along with any bookkeeping the compiler absolutely has to have And nothing else. Anything that doesn’t contribute to a person’s understanding of how to use your class shouldn’t be in there.
Last time we talked about protocols and why you’d want to use one. So, when would you want to make your own protocol? You make protocols when you’re defining some kind of mechanism for your object to use other objects to do its work. One use of protocols is defining the set of methods used for plugins. AMOSXP(3) has a section that builds plugins in Cocoa, using a protocol to spec out how the plugin and the host application interact with each other.
The last post about isEqual: vs isEqualToString: included some timings I made to test the performance of those two calls, along with
compare:. That posting mentioned going down a rabbit hole, verifying commonly held beliefs of about
isEqualToString:. The other rabbit hole I went down related to the performance tuning. A couple of commenters on the post asked some good questions relating to the timings, especially about literal strings.
_TL;DR: When to use
isEqualToString:? There’s no meaningful performance difference between the two. For convenience use
isEqual:. For a modicum of type safety use
isEqualToString:, but it’s not as safe as you might believe. If you have unicode strings with different normalizations, use
compare:. Be careful if
nils are involved. _
We have a lot of very convenient, very powerful methods at our disposal such as
[NSData dataWithContentsOfFile:]. This method goes to the file system, opens the file, reads in all the bytes, closes the file, packs the bytes into an
NSData, and returns it back to us. It replaces a loop and several other lines of code into one convenient package. If it can’t do the work, it returns
nil. That’s pretty simple.
Most Mac programmers have used the command line, even if only briefly. Some use it to drive their source code control, some use it for Unix utilities like
grep, and some use it to build and run. There’s a handy technique using the command line that lets you exert control over your GUI apps.
Timing how long a block of code takes is a useful tool. Maybe you’re choosing between two different calls that do similar things and you’re wondering which one is faster. If one is faster, is it faster-enough to make any difference? The usual techniques involve using a profiler like Instruments, or calling a time function like
gettimeofday() before and after your code and calculating the delta. Those of us on mach-based systems like iOS and OS X can use
mach_absolute_time(), which is the finest-grained timepiece available on the system.
Objective-C categories are cool. They allow you do something that you can’t do in most compiled languages: add new methods to existing classes. You can even add methods to classes that you didn’t write.
One of our engineers was working on a project and wrote some code that crashed when running on a device: