September 28, 2008
MacCode Release 1
Just a heads up to everyone, we've put out MacCode. Check it out.
Posted by Chris Forsythe at 11:27 PM | Comments (0)
December 03, 2007
Growl site redesign
For about a year now we've wanted the Growl site to be redone. )Probably longer than that actually, but I'm positive that at least for a year we've wanted it). The problem with a project like Growl is that you can't just commission someone to work on your design, since you can't pay them, but at the same time you want to get a high standard of quality out there.
Luckily we finally hit upon the right timing for a great guy, Dan Deming-Henes. He's come up with an awesome design that so far everyone loves. I'm posting here to get some feedback about the design itself, so make a comment if you love it, you hate it, or whatever.
Just for comparison, I'm posting two screenshots:
Posted by Chris Forsythe at 05:50 PM | Comments (7) | TrackBack
November 26, 2007
Interview with Jamie Hardt of calllog2ical (formerly iphonelogd)
Hi Folks,
Fresh on the heals of my interviews with Alex Schaefer and Rudy Richter is this interview with Jamie Hardt. Jamie is the author of a bit of Ruby magic which is rather useful, called calllog2ical (formerly iphonelogd). Read on for more on Jamie and his cool bit of software for the iPhone.
So who is Jamie Hardt anyhow?
I'm a sound designer and sound editor based in Los Angeles, California -- you can see my credits either on my website, soundepartment.com, or by searching for me in the IMDb.
I write software mainly just to scratch a particular itch I might have at a particular time. I wrote a cuesheet formatter called "Agent Orange" -- so named for its ability to kill tress -- a kind of program that turns CSV data into a sort of Gantt chart for audio playlists, because there were no good products on the market and I wanted to make sure any future products met a certain minimum standard of quality. It's also implemented in Ruby, and is distributed with a little Cocoa GUI to help people use it.
I'm completely self-taught as a developer; I never took any programming classes in school, and I only really got my start when I installed the Developer Tools CD from Mac OS X 10.3. My continuing education comes from K&R (the ANSI C version), developer.apple.com, cocoadev.com, and the Pickaxe Book. I had always done little projects in Filemaker, but as I was asked to build more and more complex databases, and I found myself using more and more complex processes in my work, I was frustrated with its limitations and started looking for something else.
How have you found that your workflow has changed since moving away from FileMaker?
Not really, it just makes the things I do easier; I don't have to tech support Filemaker databases anymore! I like being able to solve a problem for someone and doing it FINALLY, without having to come back and fix things for them, and leaving them happy, and Filemaker was kinda failing at that.
Filemaker is fine for applications you're doing yourself, but applications you do for another people is a different matter.
Are there any things that you miss from developing with FileMaker that you do not get with Ruby or Cocoa?
The speed of turning a simple project around, I guess, but I hesitate to call making a Filemaker database "developing."
What made you want to start working on calllog2ical?
I came to my iPhone from a Treo 650, and while my Treo was really beginning to wear on my patience, I really liked being able to download my call log from it at the end of the year, for tax purposes. There was a nice little shareware app on the Mac that would extract your Treo's call log and spit it out as CSV.
Apple, being who the are, made a very good phone but forgot to give us a way to extract a phone log. I'm a freelancer and do a lot of contract work, and I like to keep track of who I talk to on my phone and when so I can, as stated, properly document my cell phone as a business expense.
So I wrote the script to accomplish this task with the iPhone (I haven't written the iCal-to-spreadsheet script yet, but I don't think it'll take more than an hour or two). I was originally going to write a program that exports the call log to a text file, but there's a problem. When you clear the call log in Phone.app, the calls disappear from the database, and your iPhone will regularly expire old calls off the end of your call log. Thus, reading the call log at any one moment will not give you the call log for a long period (like a year).
What you need to do is have a program that you run regularly to extract phone calls from the backup and move into a database of some sort, that intelligently inserts only new events and won't drop events if they don't happen to appear in the call log today. The iCal Calendar Store just happened to be in the right place at the right time for me; I could've made up a little sqlite database to store the calls in, but the iCal database is suited specifically for this kind of time-dependent data, and the kind of presentation you get, on a calendar and in your agenda, is pretty appealing.
It's major weakness is that you have to run it regularly to move the calls across to iCal, and you might lose calls if you don't run the script as often as you clear your call log. You could go a long ways to fixing this by (for instance) detecting when an iTunes sync occurs, which I'm sure is possible by observing the iPhone backup files, though I haven't investigated this in depth. Another way to fix this is to write a script that runs on your *phone itself*, and backs up old calls every day before they get sweeped, but I personally am avoiding hacking my iPhone until Apple supports it.
Do you typically find that Apple leaves some things out that you need like with calllog2ical (or things like Perian or Growl)?
I think they accomplish everything they set out to do.
Is there anything you'd change about the iPhone (besides call logging), if you were given the chance?
Mostly calendar stuff, like showing which calendar an event is from and OTA subscribing to calendars (er syncing). Laptop tethering for the EDGE service would be nice too.
It's really an excellent phone for someone like me, that does most of his work on contract or freelance, and is responsible for keeping his own agenda and contacts. I think Phone.app and MobileSafari.app are the best programs of their kind on any phone.
Why Ruby over another language, such as Python?
In my process of getting frustrated with Filemaker, I went looking on the internet and found Ruby on Rails (it must have been at version 0.5 at the time or something like that). I was really inspired by some of the cool features in the Ruby language, went out and bought the Pickaxe Book to get a better handle on it. After dealing with Objective-C, I appreciated that Ruby has a very similar underlying mentality, and since I taught myself programming in ObjC I just found it more amenable to the way I like to work. Ruby gave me my first experience with things like lambdas and continuations and anonymous functions, and it has a way of doing these in a way that made me actually understand them for the first time.
I've played with Python as well, but I got the impression it's object-oriented features are kindof a bolt-on, and I have a serious psychological issue with syntactic whitespace (particularly tabs).
Did you need to go out and buy a book based on the fact that the documentation was lacking, or was there another reason?
Documentation of what? Ruby? I just like buying books, you can read the Pickaxe book on the web after all, I just liked having something on paper I could browse at leisure. I think documentation of the Ruby language itself is quite sufficient.
The Rails documentation has always been a little on the sketchy side, but this is a symptom of the fact that it's always getting new stuff put in it and the people who are on the edge of its development seem to get bored with doing things one way for too long :) The API docs are OK, but when you're trying to do something specific, Rails has this problem in that there may be five ways to do some things, and the Rails devs have been in love with each of them at one time or another and have done a blog entry about how their agile practice du jour is wicked cool. It can be difficult to find information on a particular rails mechanism without also getting advocacy for it.
Another related thing: When it comes to answering "How to do X?" type questions in Rails, you generally go thru the wiki or blog entries and see what other people did, and Rails makes awesome example code (I dare say one of its design objectives is to make code that reads well). Of course, on a language level, they get this kind of readability by hideously overloading and aliasing methods and functions, so a lot of the foundation Rails methods, like, say, ActiveRecord::Base::find(), just takes an anonymous hash for an argument, and this hash can contain string keys to values, symbol keys to values, or no hash at all, maybe a string, maybe an array of strings, maybe it need not be an array, merely an object that mixes in Enumerable. The method may take a proc as an argument, or it may yield values to a block (and the arity of the block might be 1 or 2 or none or any combination of those).
That ends my rant, but despite this, I really like the idea behind Rails, and it taught me a lot about programming, and maybe what not to do too ;)
Do you feel the documentation out there is now up to par?
see ibid.
How do you feel about things like RubyGems?
Without it using OSS libraries in Ruby would be inconvenient to say the least; it's a great way to distribute OSS libraries of code. I wouldn't use half the open-source software I do without tools like RubyGems and darwinports. My only gripe is that often my end users don't have them, so *I* have to resolve their dependencies for them.
Why did you choose to go with the GPL?
I was putting it up and the GPL v2 was the first one that came to mind? I honestly don't pay TOO much attention to these debates, but I tend to lean towards the GPL for anything that isn't published for strictly educational purposes.
I like the idea that the code is out in the open, and I wouldn't want someone to sell some kind of "Pro" version for 29.95 when all they did was slap a dialogue box on it. I also think the GPL strongly favors end-users by giving them the right to examine and extend the software they have.
Honestly it was really more of a whim than anything, I could just as well have made it BSD, and since Ruby is an interpreted-only language (for now), it's not really practical for people to add to the script without the changes being visible to all.
Why is calllog2ical important?
I suppose, aside from the fact that I can now do my taxes again, it shows how quickly you can write a little "mashup"-style script using the Cocoa Scripting bridge and your language of choice.
I also suppose, if you didn't value your privacy at all, you could publish your iCal to your website or whatever, and get some kind of twitter-style life-stream. That's not my thing, but some people might like it. Then there's variations on this, like employers keeping tabs on employees, etc.
What are your thoughts on the scripting bridges new to 10.5? (if you haven't messed with them, we can skip this one)
calllog2ical wouldn't have been coded in an hour without the scripting bridge; it's excellent for prototyping an application. For commercial software developers I don't think it's all that important, but for people who want to do a little hack every now and then it's excellent.
I'm curious what Apple's real "Development Roadmap" is for the scripting bridge. Will a RubyCocoa application I build today run in 10.6 without modification? Exactly how serious do they take the Scripting Bridge as a "platform" for development, particularly given that it's really not acceptable for commercial software?
Pies or Cakes?
French silk pie, please.
Posted by Chris Forsythe at 10:59 PM | Comments (0) | TrackBack
November 12, 2007
Interview with Ambrosia Software's Rudy Richter, co-programmer of iToner
Heya Folks,
Next in the series of interviews I'm doing with people who work on iPhone related projects is Rudy Richter. Rudy works on iToner, and works for Ambrosia Software Inc.. Click on through, and definitely check out both iToner and all of Ambrosia's products (personally I like SketchFighter)...
So who is Rudy Richter anyhow?
I'm a software developer with experience in Cocoa, Carbon and the evils of the CoreAudio HAL. I spent 7.5 years working for NASA, part of which I also worked for Rogue Amoeba on their Detour and SoundSource products. I currently work for Rogue Amoeba's competition in the audio space, Ambrosia Software. Some people consider me to be entirely evil, I'm not going to disagree with them.
What kind of Mac do you develop on? Do you have any other macs, or have you had any others previously?
At work I've got one of those 3.0GHz Mac Pro's with 5GB of ram and two 24 inch displays. At Home I've got a 2.66 GHz Mac Pro, a Dual 2.0GHz PowerMac G5, and a 1.5 GHz PowerBook G4 that I use for development. In all I've got in the neighborhood of 50 Macs from SE's to Mac Pro that all function, 2 Sun boxes, and just recently I was given the BeBox and NeXT Cube that Andrew Welch had bought in the 1990's.
What is your typical day like now that you work for Ambrosia Software?
I spend my day split between several support frameworks, publicly released products and unannounced products. A very different environment from both Rogue Amoeba and NASA, the projects range in their level of evilness which keeps things interesting. When someone needs a break from work we've got several video game systems hooked up to the big screen tv. We have a Wii and a PS3, so lunch time is usually accompanied by some Wii Sports. The PS3 has a thick layer of dust on it at this point. I've been here a year now, and you can count the number of times the PS3 has been used on two hands. It is definitely enjoyable to work here.
So you really like the Wii huh? Me too. What's your favorite Wii Sports game, and are you looking forward to any other games for the platform?
We play a lot of Golf and Tennis, but not much else. I don't have a Wii myself but I'm looking forward to Resident Evil: Umbrella Chronicles. PS3-wise I'm looking forward to God of War 3, Final Fantasy XIII and Resident Evil 5.
What led you to work on iToner?
In the period of time leading up to the release of the iPhone there were discussions internally at Ambrosia to include functionality in our Exporter framework for being able to export audio from WireTap Studio to the iPhone. I know quite a number of talented people in the mac development world and it turned out that one of them had written a program to do just that. Cedric Pansky had previously worked with Rogue Amoeba and written AirFoil 1.0, currently he's doing contract software development through his company, Azlance LLC. I suggested to him (at the urging of Michael Simmons) that he might want to talk to Andrew about releasing it as a product through Ambrosia. He agreed and 3 days later we started work on iToner. I was given the task of getting him up to speed with our frameworks and in about a week's time iToner was in its complete and shipping form. It has been a crazy roller coaster ever since then. Each Apple update to iTunes and the iPhone has been equally challenging and fun to work around. When Apple first broke us with iTunes 7.4's wiping of the Ringtones.plist. We had a plan of action before i even got to work, and within 1 hour we had a proof of concept workaround. The first test of my half of the solution with Cedric's half worked flawlessly. We spent the next 8 hours or so getting the solution polished and integrated into iToner and had a build out to testers that night. We shipped the update 24 hours after we started.
Why is iToner important?
Apple needs to realize that not everyone wants to use popular Music for their ringtones. Some people just want sound effects, others personalized ringtones (a lot of people we've heard from record their voices and use those as ringtones), others compose their own music and want to use that as ringtones. iToner allows these people to load their custom sounds onto their phone, audio that they have no other way to get onto their phone. Until Apple realizes this I expect we'll continue to have this back and forth battle with them. The battle has been fun so far, but I'd much rather see them adding features to the iPhone and fixing bugs than working against iToner.
So do you think that this cat and mouse game between Cedric, Ambrosia and yourself versus Apple is going to continue, or do you think they're done for now with changing things up?
I hope they're done breaking iToner, only time will tell. We all have iPhones ourselves and none of us are using music ringtones, we have a vested interest in wanting the product to continue working. We really like our iPhones but we want to customize them beyond the blessed sounds that the music industry is providing on the iTunes Music Store.
Do you think they are targeting iToner, or third party applications in general? Or do you think it's more that they are doing stuff that they need to do, and iToner is just collateral damage?
Some of the earlier updates appeared to whack us as collateral damage, but lately a lot of the updates seem to be directly targeting utilities that put custom ringtones in the user portion of the phone. iTunes 7.5 and iPhoneOS 1.1.2 seem to restore the rename a file to m4r trick, time will tell if that workaround will remain active.
You mean after Apple started selling ringtones through the online music store they seem to have started targeting iToner and applications like it, or prior to that?
Yup, it all started with iTunes 7.4. We weren't impacted by 7.4.1 or 7.4.2 since we weren't using any of the trickery that people had figured out regarding renaming files in the Finder and tricking iTunes into syncing them over. iPhone OS 1.1.1 was the next update that impacted us. We had a fix within a week of 1.1.1 shipping, it took another week and a half to perfect it.
What type of things do you guys have on your iPhones if it isn't music?
My test suite is the Wii sound effects, it constantly tricks people on the floor into thinking its time to play Wii Golf. The other Ambrosia employees mostly use sound effects or short audio clips from tv/movies. I think Cedric has sounds on his from the Final Fantasy games.
What do you think of the iPhone in general?
Its a great little phone. I will be glad when 3rd parties can officially develop apps for it, hopefully they won't limit it to dashboard widgets as their native app development platform. Having worked on EasyEnvelopes it becomes entirely apparent how limiting that will be. The vast majority of EasyEnvelopes is written in Cocoa.
Wait a second, so you're hoping for full fledged Cocoa applications are not something equivalent to desktop widgets? I'm slightly confused since dashboard widgets can use Cocoa, can you explain what the problems here are?
Correct, i'm hoping for full fledged Cocoa applications. Dashboard widgets can make use of cocoa through the use of a javascript-> cocoa bridge and a cocoa plugin. I can easily see Apple limiting the sdk to html/javascript widgets in an attempt to prevent people from getting direct access to the phone's OS.
EasyEnvelopes? What's that?
EasyEnvelopes is a dashboard widget that works on 10.4 and 10.5 that allows you to print addressed envelopes using your printer. Half javascript, half cocoa, all evil.
What do you like to do for fun?
I enjoy watching movies, rowing, programming and poking around inside iTunes. I recently took a trip to Las Vegas and went hiking in Red Rock Canyon, which was pretty enjoyable.
Addendum
I just spoke with Michael Simmons, Director of Marketing for Ambrosia. He says that iToner definitely works with 1.1.2, so happy toning. Here's what he had to say:
"In fact, it works better, as 1.1.2 now has a "Custom" ringtones section, keeping the iToner transferred ringtones separated nicely at the top of the overall iPhone ringtone list!"
Posted by Chris Forsythe at 04:52 PM | Comments (1) | TrackBack
November 08, 2007
Interview with Alex Schaefer of ApolloIM
Hey folks,
So here's the first in a series of interviews I'm going to be doing with people who work on iPhone related projects. This first one with with Alex Schaefer of ApolloIM. Click on through, and be sure to check the project out when you're done reading...
So who is Alex Schaefer anyhow?
Alex C. Schaefer is a one-man army whom just this morning won "Coffee Drinker of the Week" at his local Pete's Coffee. In addition to enjoying free coffee, Alex C. Schaefer enjoys problem solving, computer programming, poetry, Portal for the Xbox 360, drinking Guinness until the bar closes, and talking in the third person.
Ah, so you got the Orange Box? Are there any other games on that which you like to play, or did you get the box for just Portal?
I bought it for Team Fortress, I stayed for Portal. Portal is just such a wacky way of thinking of physics - it's brilliant, and it's only flaw is that it's begging for more levels.
Are there any other kinds of games that you like, or is Portal it?
Halo 3 has been sitting on top of my 360, waiting be unwrapped, but Orange Box has too many goodies to play with. It's five games in one, it's such a ridiculously great package. I'm knee deep into Half-Life 2, been doing some Team Fortress 2 online, and I plan on unlocking all achievements on Portal. I'm also a big fan of PC gaming - Supreme Commander is such a great game, I only wish my PC wasn't breaking down from old age so I could start playing it again.
What is it about Portal that's so fascinating? For those who have never heard of it, can you explain some of the game play?
It's just gameplay and problem solving that I've never seen before, and it's just got my attention right now. I keep wanting to play it over and over again to try and shave a portal off my total-portal-count, or seeing how fast I can complete the puzzle. It's very much a thinking man's game.
So no Wii or Playstation 3? How about DS Lite?
I have my WII, but i find I don't play it nearly as much alone as I do when I have company over. I can play wii all night with a few people, but alone I am more likely to play Starfox on my DS Lite or Marvel Ultimate Alliance on my 360. The Wii is great, but without buds, I'm just not that into it.
I guess that's enough of the gaming tangent, let's get back to you telling us more about yourself
In all seriousness, I'm a young developer. I'm more or less home grown, having dropped out of Compsci after my fourth semester in favor of a degree in Creative Writing, and as such since the end of "Data Structures 419" I've found a happy medium between computers and writing (be it Obj-C or something in trochaic hexameter). The logical explanation for that gig is that I enjoy finding structure where there seems to be none, and well, it's lead me to some interesting places
I just have to ask, what sort of interesting places?
I like breaking rules, and finding structure where I hadn't thought it existed. When you find structure where one would not expect there to be structure you're instantly confronted with sets of decisions that someone made and a board is revealed of purpose and direction, and to play with those forces in such a way as to elaborate either has provided me with great clarity. What started this entire thought dichotomy, and subsequent leaving Compsci for the English department, was Oscar Wilde and the poem "The Harlot's House" - an example of trochaic hexameter, actually - it's very carefully crafted, and up unto it I hadn't given books or poetry much of a chance, because I didn't see how deep the rabbit hole goes kind of.
Good poetry, like computer programming, becomes about a structure, and that's how you rise above "amateur" and into something with substance and function - not to say that I'm not amateur, I am, but I've produced my best work while being consciously aware of the rules in a system. With Wilde, he exercised grace & meter in a way that each word pushed forward feeling, and that's hard to do in poetry - so much of it is variable meaning, but he had a unified message that was evident throughout the poem and ends on such a crashing note that you are forced feel something. It's this unified structure that, for me, becomes about finding something that someone never intended to do or something that people assumed is useless and pushing it into a different light to see where it takes the bigger meaning of what you're trying to do.
What kind of Mac do you develop on? Do you have any other macs, or have you had any others previously?
I was a terrible mac basher until a lovely little day in 2004 when the University of Colorado hired me on as a OS X administrator based on my Linux experience, and I suppose that would make my first mac a PowerMac Dual Proc 1.6ghz. From there I bought a black MacBook the day it came out, and now the rest is history. The platform is elegant and makes sense, and while I still keep windows around for some reasons - those reasons dwindle each day. I'm now anxiously waiting for the next MacBookPro update (be it six months or more) to upgrade.
I've quickly come to love Xcode and the entire OS X development environment. It's fun to do - and that's the important part to me. I've never had a real coding gig in my life, and so it's all exploration for me - and if I'm going to explore and wander around, I need to enjoy doing it. It's a beautiful system for old coders and young programmers alike, and I encourage anyone to look into the platform, the system, the api what have you. While .NET is an incredible improvement over Microsoft's old development environments, it's got nothing on objective C in terms of simplicity to slip into a program and sheer joy of production of the code itself.
How did you get involved in the ApolloIM project?
I started ApolloIM in late July as an exercise to get me back into Cocoa, and because there was allure in working with an undocumented API. It was a bit of a wild goose chase - hunting down how apple did certain things within this class-dump'd mess of an API that the hacking team for the iPhone rigged up.
The aim of the program was originally just to get AIM, and so I found an Objective C wrapper for Firetalk from a program called Boombot (long dead, I believe - http://boombot.sourceforge.net), and using that as a base customized it into a client. After it was clear that TOC support wasn't enough and that we needed something with Oscar for .Mac support, buddy icons, etc we switched to libpurple. It took us three weeks to even compile libpurple, and it would not have been possible if it wasn't for the husband and wife team of PHD's from MIT and Harvard (respectively) to get it done (Core, Pogue, thanks again) - reason being that the hacked-together compiler for the iPhone (while impressive in it's own right) just wasn't ready yet, but they found a way to fit the square peg through the round hole.
Anyway, I'm involved with ApolloIM because it's the big feature that most phones have that iPhone does not. Who knows why exactly Apple didn't include a MobileiChat, but really I saw it as something that could be done and so I ran with it.
You mention TOC being the reason you switched to libpurple due to needing OSCAR. What exactly are these things?
TOC is this basic protocol for AIM that AOL develop, from my understanding (or it could be conjecture), to create an easier to use OSCAR. The difference between TOC and OSCAR is that TOC is old school and Oscar has all the neat stuff like buddy icons, status messages without being away, Direct IM (picture sharing, etc). The move to libPurple was done to move towards that full IM client feeling - TOC works, but it's really not full figured, and Apollo wants to be a full featured mobile client. libPurple also allows us to move towards the other protocols - I have never had an MSN account, and now I do - the library itself is incredibly flexible and allows us to extend our base infrastructure into something that is so much more.
What are the benefits of using libpurple for the ApolloIM backend?
Multiple protocols, stable connections, and one sane way to modularize and move from there. We built our own libPurple/Cocoa wrapper (With some inspiration from Adium), and it's allowed us to move towards having the full client that we want. We're not anticipating video confrencing or anything, but we know libPurple is moving in that direction - and as long as we focus on abstracting libPurple from our code while be conscious of implementing it's feature, I find we work out a paradigm to focus on our client implementation while leaving the IM protocol development to Sean Egan & co ( as well as the Adium contributors) over working hard on libPurple.
How do you and your team communicate/work together, and what have you learned from this experience?
Instant Messaging has been the way to do it. It's really been the three of us, and lately more or less just myself. We're a very small project right now and so we don't have the need for a big wiki or a bugtraq quite yet - we're happy with Google Code's "issues" system.
Given what you know now, would you work on ApolloIM all over again? If so, what would you change?
I would have delayed our release of 1.0 by two or more weeks. One thing I've learned is that competition can make you stronger, but it can also make you a little too insistent on releasing a product that was completely ready. We're up to 1.0.2 now, and I feel that's the version we should have released as 1.0. I know I've learned my lesson - don't
Why is ApolloIM important?
ApolloIM is important... I guess it’s because it's the one glaring omission from the iPhone. The iPhone was really designed to be a platform for universal communication, and they forgot this one piece - Instant Messaging. Just as Adium fills the role of the missing as the client for the missing protocols from iChat, ApolloIM becomes important because everybody uses one IM protocol or another and without it, a communications platform is incomplete. I can't tell you how many times someone hasn't picked up their phone, or missed a txt message - but somehow, they still respond on GChat.
We've been in a lull at the moment, I've been settling in to a new job, and since the announcement of Apple starting to officially sanction third party applications - we've been tidying up code in anticipation of an official compiler. We're taking our time now - for a while there in September and October we were releasing once a week, and certainly lacked some testing in rushing things out the door. For now, we're going to polish and try and get the missing protocols that people have been asking for, and also try to figure out what exactly a “Gadu Gadu" is.
FYI, GaduGadu is an im protocol used heavily in Poland
I know what GaduGadu is - but man, is it a funny name, so funny that that I sometimes say outloud as a pickmeup when Coffee is out of range.
So you're hoping that the SDK that was mentioned is in fact a full on Cocoa/Carbon SDK with a compiler and the whole kit and caboodle? What if the SDK is in fact just support for dashboard widgets, or something else that isn't Cocoa/Carbon with a compiler?
Yeah, we're betting an awful lot on a real compiler, but frankly you're not supporting third party app developers unless you have a real SDK with a compiler and documentation. The way I see it, we're preparing for the future - if the future is on an unsupported platform, then we have to make ourselves flexible enough to accommodate changes to it; the switch from iPhone firmware 1.0.2 to 1.1.1 hurt everyone's development efforts and has been a real reboot for the entire development scene, but it's coming back with a vengeance right now. If the future is on a supported platform, then we have to be ready to make the switch from clever little hacks (such as us relying on the host file instead of doing a real DNS lookup due to Apple's DNS resolver on the iphone being wonky) and get ready to support real solutions. We're looking to be legitimate, and regardless of the direction, we are in a position now to prepare for that direction when it becomes clear.
Right now, the system that's already established is little more than widgets. I think with 10.5, and the iPhone os (which is very similar in file system layout and has a lot of the same API), you can implement a jailed region for third party applications that would avoid OS integration. Really, just give me a socket and 20k of r/w space for configuration files and Apollo should work fine. I am sympathetic to Apple securing the iPhone - it's a phone first and foremost, but it's also a waste of potential if you let it just sit idly by waiting for someone to call you. I've done coding for J2ME and have played with .NET for mobile platforms, and I know it's more than possible to isolate part of the phone for third party development.
Apple has a great relationship with Cocoa developers, and I am eager to see their infrastructure expand to include this, one more, OS X platform. They can do it, we can code for it, and at the end of the day there's hundreds of iPhone apps out there that are being actively developed anyway - so why not bring them into the fold and make it a secure environment?
What do you like to do for fun?
I like doing new things constantly - if I'm not changing and going in a different direction constantly, then I'm really not having that much fun. I started taking up white water rafting this previous summer - and that was pretty fun, and I'm hoping to branch into Skydiving or something similarly death defying by this Summer.
Lately I've been browsing various open-source projects looking for bugs to fix or a feature to add, and I'm hoping they'll accept them. I'm also working really hard to get the Vanilla Crazy Cake achievement in Portal.
Anything else, Chris? :)
Ah, yes, one last thing. What's your favorite kind of pie and/or cake?
Frankly, I believe the cupcake to be a modern marvel of snack delivery and consistent quality. With one fell swoop, some baker somewhere out there (I'd wager a Frenchman, but it could have been a Belgian Baker) created the first truly portable and satisfying dessert delivery system. Jacques, as I imagine he was named - because if it was truly Belgian it'd either take the form of a waffle or chocolate and while Cupcakes can take on either quality, it is not mutually exclusive - woke up one day in what I'm sure was an epiphany from god himself. This beloved edict of passion for baking and appreciation of the divine will inside Jacques could only be what produced this modern marvel of dessert specification.
Now, to further justify my general classification that the cupcake is my favorite cake - I am including this line graph demonstrating the growth in the tastacity / delicousosity of the cupcake over the last 100 years.

The cupcake starts off steady with it's invention in 1900 with a steady 5% popularity amongst elitist French (but, once again, possibly Belgian) bakers. This steady growth was interrupted in 1932 in part due to the Great Depression in the United States, where the cupcake had contributed a total of 15-20% of the popularity growth in 1910 and 1920. In 1940 the Cupcake Deliciousness index only grew by 10% due to the popular distraction of "staying alive in WWII" and thus the inevitable "taking for granted" occurred - however by 1945 the Cupcake skyrocketed back into the public's hearts, minds, and mouths.
The cupcake continued amazing growth until 1970 when "The Cupcake Man" serial murderer struck, sending baskets of cupcakes to unsuspecting childhood idols such as Captain Kangaroo and bozo the clown with Ricin laced carrot cheesecake cupcakes. It quickly recovered on New Years Day 1980 when pop-culture icon Punky Brewster was sighted downing a bottle of Jack Daniel's and washing it down with a Vanilla Frosting / Chocolate Cupcake.
In conclusion, the cupcake has withstood "the test of time" with it's magical innovations in portable deliciousness, and it's continued deliciousness growth in the future both excites and scares me - but mostly excites, because the cupcake is my favorite kind of cake.
Ah, interesting. What flavor cupcake is your favorite though?
Chocolate. :)
Posted by Chris Forsythe at 04:02 PM | Comments (2) | TrackBack
November 07, 2007
iPhone obsessed
So I've had an iPhone since the first day it came out. At first it was just to try the thing out, but now I've truly become obsessed with it, much like I obsess over guitar hero or bioshock or sourdough bread.
It's very strange, so I'll be posting some iPhone related things on the blog until I figure things out with it. Yes, I realize that the web is full of iPhone stuff, so it won't be the normal stuff you're seeing out there. Or at least I'll pretend that it hasn't been done.
The strangest part of all of this is that I've grown to like the phone almost more than my mac, but in different ways. They're both products that are at their core very utilitarian, but pretty at the same time. I just find it easier sometimes to browser on my iPhone than on my mac. Neither are perfect machines, only my rice cooker is perfect, but they do indeed get the job done.
Posted by Chris Forsythe at 01:30 PM | Comments (1) | TrackBack
August 12, 2007
c4 weirdness?
I found this image the most interesting when searching for pictures on flickr for c4:
(in case it doesn't show up, it's an image of a diff (or diff-esque, haven't looked at a diff in a while) where Vinay Venkatesh is removed, Cabel Sasser switches spots with Wil Shipley, and Fake Steve Jobs moves to Sunday. Also, looks like Allan Odgaard replaced Vinay)
Assumably Vinay was removed due to this random post by Michael: http://www.drunkenblog.com/drunkenblog-archives/000767.html.
I was really looking forward to watching a dvd about virtualization if c4 for this year ever hits dvd (still waiting on last year's dvd Wolf!).
But the fact that Vinay was removed, and Michael was not, seems really.. strange. Michael threatened bodily harm. From talking to Vinay, he's never even talked to Michael. So eh to all that, but it would have been fair to have uninvited both parties, rather than just one party.
I got back from going out today with the wife to visit with family, come back, and then get pointed to the c4 thread on twitter. Apparently the topics that drunkenbatman brought up were.. questionable, uncomfortable, and just not fun. I wasn't there, so I don't know about it. But I do know that when I see something like this post, this post, this post, and this post, I wonder if db will be invited back next year. Added to the lack of posts for what seems like forever, other than the really chaotic posts at the end of when he was posting, and the one about Vinay, and you really start to wonder if db is relevant within the mac community at this point. I'm not saying that I'm relevant or not relevant, but I'm also not running a panel at a cool mac conference (although I tried to do a bit about Trac last year and got bumped for Hillegass (and was happier for it)).
It's just weird. The whole thing with DB vs. Vinay was handled strangely, the return of DB is strange without him posting relevant stuff (I'm talking about things like interviews) recently, and things like that. I hope he gets back into the mood to start writing interesting posts again, I enjoyed them, and enjoyed talking to him about random things via IM, but in the end I had to spend the money on something else, and I'm enjoying that quite a bit.
Update: Apparently someone did talk about vm tech, a Shawn Morel. Here is the post by Alex Payne about it: http://www.al3x.net/2007/08/c41-vmware-fusion-internals.html
Posted by Chris Forsythe at 12:41 AM | Comments (2)
February 27, 2007
Weekly cocoa challenge cancelled
Unfortunately I overestimated how much time I had on a week-to-week basis. As such, the "weekly" portion of the cocoa challenge is being discontinued.
I will still continue posting updates to the challenge when I do things, but the frequency isn't going to be anything consistent by any means. Sorry folks.
Posted by Chris Forsythe at 06:08 PM | Comments (0)
February 12, 2007
Some new code in MacCode (already!)
So Brian has added a nice little snippet for how to deal with hyperlinking text. He describes some of it here.
Also, Marcus is working on some CoreData snippets. Those should be fun.
Posted by Chris Forsythe at 09:40 PM | Comments (0)
February 09, 2007
More on the MacCode repo
So while at c4 I was talking to folks, and a few of us hit upon the aggravation of trying to find source code examples for mac apps. They are everywhere, but not in a centralized location. Apparently metrowerks used to have something you could submit code snippets to, but that's long ago in a far far away place.
So something has to be done. Code on cocoadev.com is hard to find because it's a wiki. Code in other places is either hard to find, hard to gather, or hard to just even know about. So basically what I've done is create a repo on Google's code site, and started adding code to it. I've not added much mind you, but I have started adding svn:externals along with other folks doing some work as well.
- PSMTabBarControl is now hosted out of this repo.
- All past and future weekly cocoa challenge source will be hosted out of this repo
- Some code Adam Iser wrote to give you pill bar toolbars is in the repo
- Other stuff
There's a need for code here, from anyone who is interested in submitting it. I think that for this to be successful, a community would have to form around it, in general. So I was thinking of creating a mailing list for this as well, but I wanted to know how much interest there is from other folks.
Also, and this is directed to jasarien directly, the solution for DudeMenu is in the same Xcode project as the previous Dude app. Hurray targets.
Anyhow, the repo info is here:
http://code.google.com/p/maccode/
If you are interested in submitting code, do a whois on my domain and you will find my email address to contact me with.
Posted by Chris Forsythe at 08:51 PM | Comments (1)
February 07, 2007
The weekly cocoa app challenge, week 4
This week, the challenge is, as requested, toolbars.
However, that howto on cocoadevcentral is not going to help you here. Go do that howto, and then come back here.
I'll wait..
waiting...
*launches the xbox 360*
*plays gears of war*
*plays ninety nine nights*
*plays tony hawk project 8*
*switches to the wii*
*plays raving rabids for an hour*
OK, done? Good.
Now it's time to learn the aged old trick of.. that's right. Not doing the hard work when someone has done it already. It's good to learn how to make a toolbar, but once you know how.. it sucks.
So, long story short, this challenge is 2 part:
1 - do the howto from cocoadevcentral. Learn how a toolbar is made programatically.
2 - do it the sane way after that, with generictoolbar
The app I am providing for this challenge is using generictoolbar. The url for the app is here: TwilightToolbar
Also. if you sign up on the Cocoaforge Forums, you will see the hidden Coding and Applescript forums, which can be used to discuss general cocoa, and these challenges.
Good luck!
Oh, and as always, #cocoa on irc.freenode.net can be used to discuss these challenges as well.
Posted by Chris Forsythe at 07:33 PM | Comments (6)
Change of location for source code or welcome to the maccode repo
I've decided that, at this point, it makes more sense to start hosting the source code for these projects in a svn repo.
Source code for week 1, 2 and 3 are all in the maccode repo. Week 3 is part of the week 1 project.
Look in the weeklycocoa directory once you do a checkout. If you've never used subversion before, now is the time to start learning how to use it.
Also, if you have useful code snippets, utilities, or whatever else which is 3 clause bsd or mit licensed, I'd be glad to see it in this repo. I'll post more about the maccode repo in a bit.
Also, if I'm posting about source code, guess what that means! Week four post coming up as soon as I do one last compile.
Posted by Chris Forsythe at 07:20 PM | Comments (0)
January 20, 2007
About pragma mark
So in the challenge this week, if you are following along on the summary page, I suggested to start using pragma mark and pragma in general.
I was even going to make a screencast about it tomorrow. It was scheduled.
However, my good friend Peter Hosey beat me to the punch. here is his explanation of how to use #pragma mark, in silent movie format. I hope this clears things up for you if any of you had any questions about it.
Also, be sure to read the comments for info about other uses of pragma.
Posted by Chris Forsythe at 10:39 PM | Comments (2)
January 18, 2007
Podcast interview
So Scott over at the Late Night Cocoa site interviewed me for his first podcast show.
One thing to note when you listen to this. I said "model view controller" at one point where I meant "master-detail interface". I have no idea why I said the first, but that should make way more sense when you listen to it.
Anyhow, here it is.
Posted by Chris Forsythe at 10:37 AM | Comments (0)
January 17, 2007
The weekly cocoa app challenge, week 3
So this week I decided to reimplement the challenge from week 1. Be sure to set the alternate image.
As always, discussion is welcome on #cocoa on freenode.
Dude Menu is this weeks challenge.
Posted by Chris Forsythe at 01:24 PM | Comments (18)
January 16, 2007
Source for weekly challenge number 2
Here's the source. Have fun.
Posted by Chris Forsythe at 11:48 PM | Comments (4)
January 08, 2007
The weekly cocoa app challenge, week 2
Check out that sweet icon too:
Be sure to keep your work handy, I'll probably be expanding on it.
Posted by Chris Forsythe at 09:21 PM | Comments (17)
irc channel to discuss the challenges
I've always held onto #cocoa on freenode for some reason, and this seems as good as any.
Anyhow, if you would like to discuss the challenges with others, get onto irc.freenode.net #cocoa
If you are not familiar with irc, try Colloquy
Posted by Chris Forsythe at 09:17 PM | Comments (0)
Source for weekly challenge number 1
As promised, here is the source for the weekly challenge, for week number 1:
Posted by Chris Forsythe at 09:14 PM | Comments (0)
January 06, 2007
Weekly Cocoa Challenge web page
I went ahead and made a summary page for the Weekly Cocoa Challenge.
It's here: Weekly Cocoa Challenge
Posted by Chris Forsythe at 12:41 AM | Comments (0)
January 03, 2007
The weekly cocoa app challenge, week 1
So for a while now I've always been saying the best way to learn something is to keep trying it. For Cocoa I've been working on things called "stupid apps". Basically these are a set of applications that perform 1-2 tasks, help me learn a new thing, and allows me to continue evolving with Cocoa.
So the rules:
1) I will post a new mini "stupid" app once every week or two. Some weeks I get super busy, so I may skip a week every once in a while.
2) If you are learning Cocoa, you try to reimplement the application. I won't be including readmes or anything so you'll also need to figure out the functionality, the api used, and the general goal of the app.
3) When I post a new app, I will also post source code for the previous app.
Got it? If you don't, post a comment.
Anyhow, here's the first app. Have fun:
Good luck, feel free to ask questions in the comments as well.
Posted by Chris Forsythe at 10:36 PM | Comments (22)
September 28, 2006
Bumped from C4
So I had told a few people I was presenting at C4, Wolf's get together next month. I was going to do a presentation on how to organize things around development, and use Trac in a lot of examples.
Unfortunately I've just been bumped from the playlist by whatever snazzy stuff is going on here..
Fear not, I'll still be attending. Or maybe you should fear. Either way, I'll be there.
Posted by Chris Forsythe at 06:27 PM | Comments (0)
DMG creation tips and tricks
Warning: This post is longer than my usual. You may want coffee. The focus of this post is how to make a DMG image with a background in an automated fashion.
About DMG
For those who are reading this who are not aware of it, DMG (Disk Image) is the format commonly used to distribute software on OS X. There are other formats, the more traditional like tar.gz/zip/.sit. For more information specifically about how to distribute software as a DMG, you'll want to read Peter Hosey's how to distribute your software (and his semi-in-depth overview of compression format usage on OS X).
Motivation/History
Quite a while back Adium and Growl both were shipped in dmgs created in a product called FileStorm. At the time, it was buggy and hard to use. It would crash a lot, and in the end was just a pain in the butt.
But we used it anyhow. For a while.
However, it's not automated. It also required that everyone have Filestorm installed and licensed, so for instance only one person could make the dmg on the Growl team (I had the Adium license file), and only one or two on the Adium team could use it.
Everyone jokes about replacing random things with a small shell script, but we pretty much did that. Except this uses Makefiles, Shell, and AppleScript.
So, before I begin writing about how to do this, I would like to state the process before and after the creation of this build system in order to release Growl.
This is the before:
- Change directories into the growlsourceco
- svn up to ensure there are no new changes
- Open Xcode and edit version numbers OR edit version numbers without opening Xcode
- Build Growl
- Open the GrowlTunes Project and build it
- Open the GrowlMail Project and build it
- Open the Beep-Cocoa Project and build it
- Open the Beep-Carbon Project and build it
- Open the GrowlDict Project and build it
- Open the growlnotify Project and build it
- Once Growl and the Extras are built, open Filestorm
- Go into Filestorm and ensure the paths are correct in the dmg project
- Make the dmg
- Test the dmg and upload
This is the process when making a dmg with the build system that was created:
- Change directories into the growlsourceco
- Open Xcode and edit version numbers OR edit version numbers without opening Xcode
- cd Release
- type make
- Test the dmg and upload
There's actually a lot more to the process we used when we used Filestorm, but as I felt that more bullet points would only lead to excessiveness. And besides, you get the point.
Anyhow, on to the nitty gritty. This is how to make your very own DMG Creation System. I am going to run down how the Growl system works, since it is more complicated, and then run through Adium's and Perian's systems. As each application has separate needs, I'll explain decisions behind each item along the way.
Getting Started or The Growl Release System
So with Growl we have a lot of different needs for anything that would build the dmg+projects:
- Something to build a specific target in Xcode
- Something to build multiple projects with multiple targets
- Something that can make a PKG file
- Something which can
- Something that can make a DMG (duh?)
- Something that can put a background on a DMG
- Something that can position icons in the DMG in specific ways.
Pretty early on a script or Makefile seems appropriate here, and we ended up with a Makefile+Applescript, so here's the long and short of the interesting bits. Here is a screenshot of the Growl disk image when mounted:
We can see from this image the requirements listed above., and more. It looks like a mess because it is, but that's more the fault of myself than anything else. For instance, let's look at the Perian DMG for the .5b4 release that I'm building now:
As you can see, the disk image can be made to be either randomized on disk or pretty strict. Let's move on to how to actually do all of this.
Top level Makefile
The first part you have to know about is that the top level directory of your source repo needs to have a file called Makefile in it. For a simple project you should plan ahead, and for a complex one you will appreciate this. At the very end of this blog post I will post the entire dmg making system, so if you'd like you can skip this for now. However, It will not be filled with comments, it will only have what is currently in the Adium/Growl/Perian build systems.
Basically the end result is to get a Makefile at the top level of the source tree that builds your project/targets how you like.
The release system also needs a folder called (unsurprisingly) Release, which will hold the rest of your release system items.
Here is the entire top level Makefile for the .7.4 release of Growl, with explanations along the way:
PREFIX?=
PREFERENCEPANES_DIR=$(PREFIX)/Library/PreferencePanes
Since Growl is a PrefPane, it lives in either ~/Library/PreferencePanes or /Librayr/PreferencePanes
FRAMEWORKS_DIR=$(PREFIX)/Library/Frameworks
GROWL_PREFPANE=Growl.prefPane
GROWL_FRAMEWORK=Growl.framework
This portion sets the framework directory and then the prefpane and framework names
BUILD_DIR=build
GROWL_HELPER_APP=$(PREFERENCEPANES_DIR)/$(GROWL_PREFPANE)/Contents/Resources/GrowlHelperApp.app
HEADERDOC_DIR=Docs/HeaderDoc
Setting some more stuff for use later in the script.
#DEFAULT_BUILDSTYLE=Deployment
DEFAULT_BUILDSTYLE=Development
BUILDSTYLE?=$(DEFAULT_BUILDSTYLE)
Here's where the fun stuff starts to happen. For those who don't follow this, basically this will allow you to change the build style by uncommenting one line and commenting another. If you happen to have 5 build styles, you could list 4 commented out and one uncommented, and easily switch between the whole lot of them.
CP=ditto --rsrc
RM=rm
This bit should be obvious based on the previous stuff.
.PHONY : all growl growlhelperapp growlapplicationbridge growlapplicationbridge-withinstaller frameworks clean install
all: frameworks
xcodebuild -alltargets -buildstyle $(BUILDSTYLE) build
growl:
xcodebuild -target Growl -buildstyle $(BUILDSTYLE) build
growlhelperapp:
xcodebuild -target GrowlHelperApp -buildstyle $(BUILDSTYLE) build
frameworks: growlapplicationbridge growlapplicationbridge-withinstaller
growlapplicationbridge:
xcodebuild -target Growl.framework -buildstyle $(BUILDSTYLE) build
growlapplicationbridge-withinstaller:
xcodebuild -target Growl-WithInstaller.framework -buildstyle $(BUILDSTYLE) build
clean:
xcodebuild -alltargets clean
All of this builds Growl and the frameworks or cleans it. Note the use of $(BUILDSTYLE) here.
install:
killall GrowlHelperApp || true
-$(RM) -rf $(PREFERENCEPANES_DIR)/$(GROWL_PREFPANE) $(FRAMEWORKS_DIR)/$(GROWL_FRAMEWORK)
$(CP) $(BUILD_DIR)/$(GROWL_PREFPANE) $(PREFERENCEPANES_DIR)/$(GROWL_PREFPANE)
open $(GROWL_HELPER_APP)
install-growl:
killall GrowlHelperApp || true
-$(RM) -rf $(PREFERENCEPANES_DIR)/$(GROWL_PREFPANE)
$(CP) $(BUILD_DIR)/$(GROWL_PREFPANE) $(PREFERENCEPANES_DIR)/$(GROWL_PREFPANE)
open $(GROWL_HELPER_APP)
headerdoc:
rm -rf $(HEADERDOC_DIR)
headerdoc2html -C -o $(HEADERDOC_DIR) Common/Source/GrowlDefines.h Common/Source/GrowlDefinesInternal.h Framework/Source/*.h Common/Source/GrowlPathUtil.h Display\ Plugins/GrowlDisplayProtocol.h Framework/Source/Growl.hdoc
gatherheaderdoc $(HEADERDOC_DIR)
uninstall:
killall GrowlHelperApp || true
@if [ -d "/Library/PreferencePanes/Growl.prefPane" ]; then \
echo mv "/Library/PreferencePanes/Growl.prefPane" "$(HOME)/.Trash"; \
mv "/Library/PreferencePanes/Growl.prefPane" "$(HOME)/.Trash"; \
elif [ -d "$(HOME)/Library/PreferencePanes/Growl.prefPane" ]; then \
echo mv "$(HOME)/Library/PreferencePanes/Growl.prefPane" "$(HOME)/.Trash"; \
mv "$(HOME)/Library/PreferencePanes/Growl.prefPane" "$(HOME)/.Trash"; \
fi
@if [ -d "/Library/Frameworks/GrowlAppBridge.framework" ]; then \
echo mv "/Library/Frameworks/GrowlAppBridge.framework" "$(HOME)/.Trash"; \
mv "/Library/Frameworks/GrowlAppBridge.framework" "$(HOME)/.Trash"; \
elif [ -d "$(HOME)/Library/Frameworks/GrowlAppBridge.framework" ]; then \
echo mv "$(HOME)/Library/Frameworks/GrowlAppBridge.framework" "$(HOME)/.Trash"; \
mv "$(HOME)/Library/Frameworks/GrowlAppBridge.framework" "$(HOME)/.Trash"; \
fi
The rest of this should be decently self explanatory. But, basically, the rest covers how to install and uninstall Growl. It's more convenience than anything else for developers, and is not required by any means to make this work.
This Makefile should be different for every project, but overall it should be pretty easy to modify this one for your needs. Besides, the fun bit is inside the Release directory anyhow. Let's move on to that.
The Release Directory, of Doom
Heh, DOOM. So ya, the release directory is what controls everything else here. Let's take a look inside:
growl-0.7/Release chris$ ls -1
Artwork
Get more styles.webloc
Growl Developer Documentation.webloc
Growl Documentation.webloc
Growl version history for developers.webloc
Growl version history.webloc
GrowlMail
GrowlSafari
Makefile
Uninstall Growl.app
dmg_growl.scpt
dmg_sdk.scpt
make-diskimage.sh
Specifically, what's required here to build a dmg with artwork is:
Artwork
Makefile
dmg_growl.scpt
make-diskimage.sh
This system only requires these 4 items and the top level to work. So let's get to the main Makefile, and then cover the other bits after that.
Release Makefile
SRC_DIR=..
BUILD_DIR=build
GROWL_DIR=$(BUILD_DIR)/Growl
SDK_DIR=$(BUILD_DIR)/SDK
RELEASE_NAME=Growl-0.7.5
RELEASE_DIRNAME=$(RELEASE_NAME)
RELEASE_DIR=$(BUILD_DIR)/$(RELEASE_DIRNAME)
CONFIGURATION=Deployment
BUILDFLAGS="CONFIGURATION=$(CONFIGURATION)"
PRODUCT_DIR=$(shell defaults read com.apple.Xcode PBXProductDirectory 2> /dev/null)
This bit here is where you start changing things. Specially, only 2 items, the CONFIGURATION and RELEASE_NAME. There's not much more to it here, as with before we have some settings that tell the script what things are. Some stuff is dynamically set, etc.
ifeq ($(strip $(PRODUCT_DIR)),)
GROWL_BUILD_DIR=$(SRC_DIR)/build/$(CONFIGURATION)
GROWLCTL_BUILD_DIR=$(SRC_DIR)/Extras/growlctl/build/$(CONFIGURATION)
GROWLDICT_BUILD_DIR=$(SRC_DIR)/Extras/GrowlDict/build/$(CONFIGURATION)
GROWLNOTIFY_BUILD_DIR=$(SRC_DIR)/Extras/growlnotify/build/$(CONFIGURATION)
GROWLTUNES_BUILD_DIR=$(SRC_DIR)/Extras/GrowlTunes/build/$(CONFIGURATION)
HARDWAREGROWLER_BUILD_DIR=$(SRC_DIR)/Extras/HardwareGrowler/build/$(CONFIGURATION)
GROWLMAIL_BUILD_DIR=$(SRC_DIR)/Extras/GrowlMail/build/$(CONFIGURATION)
GROWLSAFARI_BUILD_DIR=$(SRC_DIR)/Extras/GrowlSafari/build/$(CONFIGURATION)
RAWRJOUR_BUILD_DIR=$(SRC_DIR)/Extras/Rawr-jour/build/$(BUILDSTYLE)
else
TARGET_BUILD_DIR=$(PRODUCT_DIR)/$(CONFIGURATION)
GROWL_BUILD_DIR=$(TARGET_BUILD_DIR)
GROWLCTL_BUILD_DIR=$(TARGET_BUILD_DIR)
GROWLDICT_BUILD_DIR=$(TARGET_BUILD_DIR)
GROWLNOTIFY_BUILD_DIR=$(TARGET_BUILD_DIR)
GROWLTUNES_BUILD_DIR=$(TARGET_BUILD_DIR)
HARDWAREGROWLER_BUILD_DIR=$(TARGET_BUILD_DIR)
GROWLMAIL_BUILD_DIR=$(TARGET_BUILD_DIR)
RAWRJOUR_BUILD_DIR=$(TARGET_BUILD_DIR)
GROWLSAFARI_BUILD_DIR=$(TARGET_BUILD_DIR)
endif
Growl has a whole list of Extras that we ship (growlctl, GrowlDict, growlnotify, GrowlTunes, HardwareGrowler, GrowlMail, RawrJour, GrowlSafari) along with Growl, so we have to take that into consideration. The build system packages all of them up as well. So here we're telling Xcode (gcc and company) how to build it based on the style setup in Xcode.
# What to do before running this script:
# - Set version number in GHA. You can do this in GrowlController.m. Look for the "static struct Version version" line.
# - Set RELEASE_NAME
# - Edit the following two plist keys
# - Core/Resources/Info.plist
# - Core/Resources/GrowlHelperApp-Info.plist
Just some comments about what to do really.
.PHONY: all compile clean release source
all: compile release source
compile:
$(MAKE) $(BUILDFLAGS) -C $(SRC_DIR)
$(MAKE) $(BUILDFLAGS) -C $(SRC_DIR)/Extras/GrowlMail
$(MAKE) $(BUILDFLAGS) -C $(SRC_DIR)/Extras/GrowlSafari
$(MAKE) $(BUILDFLAGS) -C $(SRC_DIR)/Extras/GrowlDict
$(MAKE) $(BUILDFLAGS) -C $(SRC_DIR)/Extras/growlnotify
$(MAKE) $(BUILDFLAGS) -C $(SRC_DIR)/Extras/HardwareGrowler
$(MAKE) $(BUILDFLAGS) -C $(SRC_DIR)/Extras/growlctl
$(MAKE) $(BUILDFLAGS) -C $(SRC_DIR)/Extras/GrowlWidget
$(MAKE) $(BUILDFLAGS) -C $(SRC_DIR)/Extras/GrowlTunes
$(MAKE) $(BUILDFLAGS) -C $(SRC_DIR)/Extras/Rawr-jour
It rubs the lotion on the skin.
clean:
rm -rf $(BUILD_DIR)
Or else it gets the hose again.
source:
rm -rf $(RELEASE_DIR)
mkdir -p $(RELEASE_DIR)
cp -R $(SRC_DIR)/Bindings $(RELEASE_DIR)
cp -R $(SRC_DIR)/Common $(RELEASE_DIR)
cp -R $(SRC_DIR)/Core $(RELEASE_DIR)
cp -R $(SRC_DIR)/Display\ Plugins $(RELEASE_DIR)
cp -R $(SRC_DIR)/Docs $(RELEASE_DIR)
cp -R $(SRC_DIR)/Examples $(RELEASE_DIR)
cp -R $(SRC_DIR)/Extras $(RELEASE_DIR)
cp -R $(SRC_DIR)/Framework $(RELEASE_DIR)
cp -R $(SRC_DIR)/Growl\ Readme.rtfd $(RELEASE_DIR)
cp -R $(SRC_DIR)/Growl.xcodeproj $(RELEASE_DIR)
cp -R $(SRC_DIR)/Prefpane\ TestHarness $(RELEASE_DIR)
cp -R $(SRC_DIR)/Scripts $(RELEASE_DIR)
cp -R $(SRC_DIR)/images $(RELEASE_DIR)
cp $(SRC_DIR)/HACKING.txt $(RELEASE_DIR)
cp $(SRC_DIR)/License.txt $(RELEASE_DIR)
cp $(SRC_DIR)/Makefile $(RELEASE_DIR)
cp $(SRC_DIR)/README.rtf $(RELEASE_DIR)
cp $(SRC_DIR)/build.sh $(RELEASE_DIR)
cp $(SRC_DIR)/changes.txt $(RELEASE_DIR)
cp $(SRC_DIR)/generateSVNRevision.sh $(RELEASE_DIR)
cp $(SRC_DIR)/headerDoc2HTML.config $(RELEASE_DIR)
We really do copy all of this into the 2 dmgs that are produced, the SDK dmg and the Growl.dmg.
find $(RELEASE_DIR) \( -name build -or -name .svn \) -type d -exec rm -rf {} \; -prune
find $(RELEASE_DIR) \( -name "*~" -or -name .DS_Store \) -type f -delete
tar -cj -C $(BUILD_DIR)/ -f $(RELEASE_DIR)-src.tar.bz2 $(RELEASE_DIRNAME)
This is the bit I keep think I'll remove. It doesn't work right. But it's supposed to make a source bzball. The rest is decently commented, so if there's something I think is confusing just email me ( the_tick at this domain).
release:
@# clean build directory
rm -rf $(BUILD_DIR)
mkdir $(BUILD_DIR)
mkdir $(GROWL_DIR)
@#
@# copy uninstaller
@#
cp -R "Uninstall Growl.app" $(GROWL_DIR)
/Developer/Tools/SetFile -a E $(GROWL_DIR)/Uninstall\ Growl.app
@#
@# copy webloc files
@#
cp "Growl Documentation.webloc" "Growl version history.webloc" "Get more styles.webloc" $(GROWL_DIR)
@#
@# hide extensions of webloc files
@#
/Developer/Tools/SetFile -a E $(GROWL_DIR)/*.webloc
@#
@# copy the prefpane
@#
cp -R $(GROWL_BUILD_DIR)/Growl.prefPane $(GROWL_DIR)
@#
@# copy the extras
@#
These bits were all pretty well documented.
mkdir $(GROWL_DIR)/Extras
mkdir $(GROWL_DIR)/Extras/growlctl
cp $(GROWLCTL_BUILD_DIR)/growlctl $(GROWL_DIR)/Extras/growlctl
cp $(SRC_DIR)/Extras/growlctl/growlctl.1 $(GROWL_DIR)/Extras/growlctl
cp $(SRC_DIR)/Extras/growlctl/install.sh $(GROWL_DIR)/Extras/growlctl
Copy in growlctl
mkdir $(GROWL_DIR)/Extras/GrowlDict
cp -R $(GROWLDICT_BUILD_DIR)/GrowlDict.app $(GROWL_DIR)/Extras/GrowlDict
cp $(SRC_DIR)/Extras/GrowlDict/README.txt $(GROWL_DIR)/Extras/GrowlDict
Copy in GrowlDict
mkdir $(GROWL_DIR)/Extras/growlnotify
cp $(GROWLNOTIFY_BUILD_DIR)/growlnotify $(GROWL_DIR)/Extras/growlnotify
cp $(SRC_DIR)/Extras/growlnotify/growlnotify.1 $(GROWL_DIR)/Extras/growlnotify
cp $(SRC_DIR)/Extras/growlnotify/install.sh $(GROWL_DIR)/Extras/growlnotify
cp $(SRC_DIR)/Extras/growlnotify/README.txt $(GROWL_DIR)/Extras/growlnotify
Copy in growlnotify, the cli notification util for Growl.
mkdir $(GROWL_DIR)/Extras/GrowlTunes
cp -R $(GROWLTUNES_BUILD_DIR)/GrowlTunes.app $(GROWL_DIR)/Extras/GrowlTunes
cp -R $(SRC_DIR)/Extras/GrowlTunes/ReadMe.rtfd $(GROWL_DIR)/Extras/GrowlTunes
mkdir $(GROWL_DIR)/Extras/HardwareGrowler
cp -R $(HARDWAREGROWLER_BUILD_DIR)/HardwareGrowler.app $(GROWL_DIR)/Extras/HardwareGrowler
cp $(SRC_DIR)/Extras/HardwareGrowler/readme.txt $(GROWL_DIR)/Extras/HardwareGrowler
mkdir $(GROWL_DIR)/Extras/Rawr-jour
cp -R $(RAWRJOUR_BUILD_DIR)/Rawr-jour.app $(GROWL_DIR)/Extras/Rawr-jour
cp $(SRC_DIR)/Extras/Rawr-jour/Icon\ and\ Readme/Readme.rtf $(GROWL_DIR)/Extras/Rawr-jour
Rawr-Jour, GrowlTunes and HardwareGrowler all get copied in.
@#
@# build GrowlMail package
@#
mkdir $(GROWL_DIR)/Extras/GrowlMail
mkdir $(BUILD_DIR)/GrowlMail
mkdir $(BUILD_DIR)/GrowlMail-Resources
cp -R $(GROWLMAIL_BUILD_DIR)/GrowlMail.mailbundle $(BUILD_DIR)/GrowlMail
cp GrowlMail/InstallationCheck $(BUILD_DIR)/GrowlMail-Resources
cp GrowlMail/postflight $(BUILD_DIR)/GrowlMail-Resources
cp -R GrowlMail/English.lproj $(BUILD_DIR)/GrowlMail-Resources
cp -R GrowlMail/German.lproj $(BUILD_DIR)/GrowlMail-Resources
Copy in GrowlMail stuff to prepare it to be built into a PKG.
say enter your password
sudo chown -Rh root:admin $(BUILD_DIR)/GrowlMail
sudo chmod -R g+w $(BUILD_DIR)/GrowlMail
With PKG's, you have to set some permissions.
/Developer/Tools/packagemaker -build -p $(GROWL_DIR)/Extras/GrowlMail/GrowlMail.pkg -f $(BUILD_DIR)/GrowlMail -ds -v -i GrowlMail/Info.plist -d GrowlMail/Description.plist -r $(BUILD_DIR)/GrowlMail-Resources
Here we build the PKG.
sudo rm -rf $(BUILD_DIR)/GrowlMail
rm -rf $(BUILD_DIR)/GrowlMail-Resources
Some cleanup
cp $(SRC_DIR)/Extras/GrowlMail/GrowlMail\ Installation.rtf $(GROWL_DIR)/Extras/GrowlMail
And we copy in the final bit for GrowlMail, the Installation rtf.
@#
@# build GrowlSafari package
@#
mkdir $(GROWL_DIR)/Extras/GrowlSafari
mkdir $(BUILD_DIR)/GrowlSafari
mkdir $(BUILD_DIR)/GrowlSafari-Resources
cp -R $(GROWLSAFARI_BUILD_DIR)/GrowlSafari $(BUILD_DIR)/GrowlSafari
cp GrowlSafari/postupgrade $(BUILD_DIR)/GrowlSafari-Resources
sudo chown -Rh root:admin $(BUILD_DIR)/GrowlSafari
sudo chmod -R g+w $(BUILD_DIR)/GrowlSafari
/Developer/Tools/packagemaker -build -p $(GROWL_DIR)/Extras/GrowlSafari/GrowlSafari.pkg -f $(BUILD_DIR)/GrowlSafari -ds -v -i GrowlSafari/Info.plist -d GrowlSafari/Description.plist -r $(BUILD_DIR)/GrowlSafari-Resources
sudo rm -rf $(BUILD_DIR)/GrowlSafari
rm -rf $(BUILD_DIR)/GrowlSafari-Resources
cp -R $(SRC_DIR)/Extras/GrowlSafari/README.txt $(GROWL_DIR)/Extras/GrowlSafari
GrowlSafari is also a PKG installer, and is built the same way that GrowlMail is built. The next bit is for building the SDK that contains the Growl.framework, Growl-Withinstaller.framework, and Bindings. It's commented, so I won't go over it. But here it is:
@#
@# build the SDK
@#
mkdir $(SDK_DIR)
@#
@# copy the webloc files
@#
cp "Growl Developer Documentation.webloc" "Growl version history for developers.webloc" $(SDK_DIR)
@#
@# hide extensions of webloc files
@#
/Developer/Tools/SetFile -a E $(SDK_DIR)/*.webloc
@#
@# copy the scripts
@#
cp -R $(SRC_DIR)/Scripts $(GROWL_DIR)
@#
@# copy the frameworks
@#
mkdir $(SDK_DIR)/Frameworks
cp -R $(GROWL_BUILD_DIR)/Growl.framework $(GROWL_BUILD_DIR)/Growl-WithInstaller.framework $(SDK_DIR)/Frameworks
@#
@# copy the bindings
@#
cp -R $(SRC_DIR)/Bindings $(SDK_DIR)
@#
@# remove the AppleScript binding
@#
rm -rf $(SDK_DIR)/Bindings/applescript
Note here, we build the Applescript Bindings right into Growl, so there's no need to ship them on the SDK DMG.
@#
@# remove some symlinks
@#
rm $(SDK_DIR)/Bindings/realbasic/GrowlDefines.h
rm $(SDK_DIR)/Bindings/tcl/GrowlDefines.h
rm $(SDK_DIR)/Bindings/tcl/GrowlApplicationBridge.h
rm $(SDK_DIR)/Bindings/tcl/GrowlApplicationBridge.m
Wheeee, symlinks bad!
@#
@# delete svn and backup files
@#
find $(BUILD_DIR) -name ".svn" -type d -exec rm -rf {} \; -prune
find $(BUILD_DIR) \( -name "*~" -or -name .DS_Store -or -name classes.nib -or -name info.nib \) -type f -delete
This bit is always fun. Removing these should be part of your build system no matter what you end up doing. Or at least I would remove them :)
@#
@# make Growl disk image
@#
mkdir $(GROWL_DIR)/.background
cp $(SRC_DIR)/images/dmg/growl075DMGBackground.png $(GROWL_DIR)/.background
./make-diskimage.sh $(BUILD_DIR)/$(RELEASE_NAME).dmg $(GROWL_DIR) Growl dmg_growl.scpt
Here's the important bits. Basically in order for this to work you have to make a folder called .background and copy the image you want into it. Then you run the disk image shell script and it's done.
@#
@# make SDK disk image
@#
mkdir $(SDK_DIR)/.background
cp $(SRC_DIR)/images/dmg/growlSDK.png $(SDK_DIR)/.background
./make-diskimage.sh $(BUILD_DIR)/$(RELEASE_NAME)-SDK.dmg $(SDK_DIR) Growl-SDK dmg_sdk.scpt
@echo Build finished
The AppleScript
That's it for the Makefile. but what about the AppleScript and Shell script? I'll be including those in the zip file at the end of this post, but would like to review the AppleScript here. The shell script will not be gone through, it's pretty self explanatory.
tell application "Finder"
tell disk "Growl" open
tell container window
set current view to icon view set toolbar visible to false
set statusbar visible to false set the bounds to {30, 50, 485, 350}
end tell
This portion tells the finder how big to make the dmg. You're specifically interested in the second 2 numbers. This basically sets the width and height of the window.
close set opts to the icon view options of container window
tell opts
set icon size to 56
Here we can set the icon size of all of the items on the dmg.
set arrangement to not arranged
end tell
set background picture of opts to file ".background:growl075DMGBackground.png"
This is where you enter the name of the background artwork you are going to be using.
set position of item "Growl.prefPane" to {45, 41}
set position of item "Extras" to {162, 33}
set position of item "Scripts" to {36, 153}
set position of item "Growl Documentation.webloc" to {128, 123}
set position of item "Growl version history.webloc" to {265, 41}
set position of item "Get more styles.webloc" to {383, 41}
set position of item "Uninstall Growl.app" to {383, 123}
This sets the location of each of the icons on the DMG.
update without registering applications
tell container window
set the bounds to {31, 50, 480, 350}
set the bounds to {30, 50, 480, 350}
end tell
I believe this portion also tells the finder how to set the size of the window when mounted, albeit I'm not 100% on that. You'll need to play around with it.
update without registering applications
end tell
--give the finder some time to write the .DS_Store file
delay 5
This bit is important. The .DS_Store stores a lot of this info, so we
end tell
That's really all there is to this. The dmg shell script builds the rest and then the process is complete. No more need for Filestorm or other applications, plus this makes life a ton easier.
Auto Versioning
You can even automate versioning as well. The Adium MakeFile has this little tidbit:
PLIST_DIR=`pwd`/../Plists
ADIUM_PLIST=$(PLIST_DIR)/Adium_2
CRASH_REPORTER_PLIST=$(PLIST_DIR)/Adium\ Crash\ Reporter-Info
version:
@# update the plists
defaults write $(ADIUM_PLIST) CFBundleGetInfoString '$(VERSION), Copyright 2001-2007 The Adium Team'
defaults write $(ADIUM_PLIST) CFBundleVersion '$(VERSION)'
defaults write $(ADIUM_PLIST) CFBundleShortVersionString '$(VERSION)'
defaults write $(CRASH_REPORTER_PLIST) CFBundleGetInfoString '$(VERSION), Copyright 2001-2007 The Adium Team'
defaults write $(CRASH_REPORTER_PLIST) CFBundleVersion '$(VERSION)'
defaults write $(CRASH_REPORTER_PLIST) CFBundleShortVersionString '$(VERSION)'
plutil -convert xml1 $(ADIUM_PLIST).plist
plutil -convert xml1 $(CRASH_REPORTER_PLIST).plist
This writes the version out to to 2 plists, along with copyright information. So you'd set the version in the Makefile, hit Make, and this handles the rest.
openUp
Last and not least, before I go, I need to talk about a utility called openUp. The openUp utility won't exactly be required for this to all work, but it'll help (i.e. you want it). The scripts assume it is installed into /usr/local/bin, but you can modify that. I've included it in the Utilities folder on the zip file.
For what it does, I'll just copy and paste the comments from the .c file:
/*
* Shantonu Sen <<EMAIL REMOVED>>
* openUp.c - program to set the "first-open-window" field of a volume
*
* Get the directory ID for the first argument, and set it as word 2
* of the Finder Info fields for the volume it lives on
*
* cc -o openUp openUp.c
* Usage: openUp /Volumes/Foo/OpenMe/
*
*/
The end
Well, that's it. I hope this has been informative. Oh, here's the zip (2.4 mb).
Also, this is my first attempt at posting with the newer versions of Ecto. I rather like this, and will probably purchase it.
Posted by Chris Forsythe at 02:27 PM | Comments (1)
June 27, 2006
New Objective-C API?
We've all known for a while that Objective-C in 10.5 would have Garbage Collection, but it's kinda interesting to see that it'll have a whole new API (or at least a portion of a new API).
Check this out:
http://cia.navi.cx/stats/project/webkit/.message/577bb2.
Go Tim!
Posted by Chris Forsythe at 07:47 PM | Comments (2)
May 05, 2006
NSTableView
NSTableView rocks. This is all.
Posted by Chris Forsythe at 05:54 AM | Comments (0)
April 29, 2006
HOM - First release! :)
So I decided it's time for a first release of my higher order messaging framework. It has been tested in ChatKit, and appears to work fine, but it wasn't yet tested in a full bloated app. You can get 0.1b1 at http://trac.dpompa.com/hom.
Any feedback will be very appreciated :)
Posted by Ofri Wolfus at 04:56 AM | Comments (0)
March 31, 2006
Executing an Applescript from Cocoa
So I spent some time digging around and couldn't find much about cocoa+applescript except for examples of how to put the code in the same class as the cocoa. So after looking around, pestering some folks, and coming up with some of my own stuff, this is what I came up with:
#import "RunScript.h"#define runScriptName @"checknewnow"
#define runScriptType @"scpt"
@implementation RunScript- (IBAction)runScript:(id)sender
{
/* Locate that darn thing*/
NSString *scriptPath = [[NSBundle mainBundle] pathForResource: runScriptName ofType: runScriptType];
NSURL *scriptURL = [NSURL fileURLWithPath: scriptPath];
//NSLog(@"%@", scriptURL);NSAppleScript *as = [[NSAppleScript alloc] initWithContentsOfURL:scriptURL error:nil];
[as executeAndReturnError:nil];
//NSLog(@"foomx");
}@end
Thanks to David Smith and Andrew Wellington for their help.
Posted by Chris Forsythe at 11:01 PM | Comments (2)
March 08, 2006
Higher Order Messagin - Take II
So to continue my last post, you can get the source of my HOM framework at http://trac.dpompa.com/hom. No release is available yet, but you can build from source yourself. The code works fine for me, but wasn't tested by anyone else (yet). If you find any bugs and/or have any comments, please contact me.
Posted by Ofri Wolfus at 10:26 AM | Comments (2)
March 05, 2006
Where does one start with Cocoa?
So every day I get im'd by some random person asking me where to start with Cocoa. They first im asking how I'm doing, but eventually they get to the meat of it.
That started about 9 months ago.
I eventually started creating a page that had some book info, some mailing list info, and some neat websites. It's slowly evolved from something I threw together in five minutes to something that a lot of people seem to like. The point is to have a page that's short and sweet, with no flashy and just some good stuff to start off with.
So take a look at my Beginning with Cocoa page. And if you have any suggestions, leave a comment.
Posted by Chris Forsythe at 11:51 PM | Comments (1)
December 17, 2005
Higher Order Messageing (HOM)
First, i would like to say hello to everyone. This is my first post here :)
So in the last few weeks i was working on my own HOM implementation (which I intend to use in ChatKit), and it evolves pretty well. It now has the following prefix messages for NSObject:
* -ifResponds which performs the argument message only if the receiver can respond to it (it's simply a cleaner if([receiver respondsToSelector:sel]) [receiver doSomething]).
* -async which detaches a new thread and performs the argument message in that thread.
* -do is probably one of the more useful higher order messages. It's much easier to explain with an example: [[myObjct addObject:[someArray each]].
* -mainPerformAndWait: & -mainPerform which performs the argument message in the main thread.
It also provides these prefix messages for NSArray:
* -select which sends the argument message to each of the receiver's objects and returns the one that returned YES. Example: myArray contains @"a", @"hello" and @"aaa". [[myArray select] hasPrefix:@"a"] will return an array containing @"a" and @"aaa".
* -reject does the same as -select but returns the objects which returned NO.
* -collect performs the argument message and returns an array containing the results.
* -each which is used together with -do (see above).
The obvious question that raises is why? Why did i spend all that time making my one framework, when there are already other free open source implementations available?
Well, there are 3 major reasons:
1) Simplicity of the code. Implementing Higher Order Messaging is not that easy as it might look. The best implementation in my opinion is in MPWFoundation by Marcel Weiher (this is also where HOM was born). I had 2 problems with it. The first is that the code is really lacking comments. It also compiles with a lot of warnings due to the fact that a lot of methods are not declared in headers but used in implementation files. The second problem is that MPWFoundation contains a lot of other really cool stuff which i didn't really need. My original idea was to tear the HOM implementation out of MPWFoundation, reorganize it and document it, but the level of complication of it made me to give up. Other implementations are more organized then MPWFoundation, but they have their own problems (see below).
2) Modularity of the code. The implementations of HOM which i saw, all did the same thing - implemented ALL the higher order messages inside one object. MPWFoundation did them using MPWEnumFilter and others did it inside the trampoline itself. In my opinion this is really bad and prevents others from adding their own prefix messages. In my implementation, the trampoline object passes an invocation to its target. Not more, not less. The implementation of the prefix message itself is done in the target of the trampoline (the target will usually be the receiver of the prefix message), and can be expanded as needed.
3) It was fun, interesting and challenging to write :)
It needs a bit more polishing, but after that I'm going to release it under BSD license.
Posted by Ofri Wolfus at 10:01 AM | Comments (1)
December 01, 2005
Interviewed
I was interviewed by Victor over at MacNN
Here is a link to that podcast.
Posted by Chris Forsythe at 10:07 PM | Comments (0)
November 30, 2005
And on to a new thing
So I've finally done it. I've finally started to click with a language. It took countless books. The basic problem I've always had is getting past chapter 3 in any programming book. Most books, to me, seemed to be walking you up slowly to something, and then at chapter 4 went to a full run.
This isn't so bad if you have other people helping you, or if you have a lot of time, but I don't have either. It seems that lately when reading my concentration has gone south. That is until I started reading Programming in Objective-C by Stephen Kochan.
There are a couple of flaws with most Cocoa books, or at least the ones I have. The biggest strangest problem is that they all assume that you know C. Or Java is apparently something else that you could know that would get you right into it all. Not knowing any of it, having only taken a beginners course in c++ many years ago (note: most of the stuff from that class that I learned soaked up all the alcohol I drank), this made it kinda impossibly hard to get to learn Cocoa.
I had then started to try to learn C. C is alright to learn on your own, many have done it. It just takes a bit more concentration than I've had for a long while.
So I gave up on learning code for 3 months altogether, thinking I needed break. I also looked for a new book. One from an author I'd never heard of, and not a lot of folks have apparently. Also I wanted it to teach me C and Objective C. I didn't need to know the Apple frameworks yet, just the rules of the language.
And I found it. Kochan's book is great, and I'm glad I got it. I'm already on chapter 6, and started reading it about a month ago, on and off.
Posted by Chris Forsythe at 08:43 AM | Comments (0)


