Saturday, December 23, 2006
What will be coming up next year in Cocoa Samurai
Well everybody it’s the holidays and I hope your all doing OK. I just wanted to wish you all well and let you all know what’s coming up.
It seems this blog as been doing extraordinarily well from the statistics I’ve seen on Google Analytics. But I hope starting in January I can make it do even better. When I first started this blog it was really just something for me and a few of my friends around here mainly in AmesMUG (Ames Mac Users Group) but then It started getting picked up by a few other people... then came Scott Stevenson and CocoaDevCentral. That completely changed my audience overnight. Certainly the new Cocoa Blogs page lists this as a Cocoa Blog focused on beginners and certainly from the articles i’ve done I don’t fault Scott for coming to that conclusion.
When I started writing this blog I had the intention of writing a few things at first that simply spelled out how to do some things I had wanted to know when learning Cocoa. Things like the pragma mark I actually learned by digging through Adium source code, other things I had to dig through pages and pages of material to find it. This blog was to end that. You wanna know how to do gradient backgrounds? Here's how you do it simple and easy, save you the time and effort of digging up pages and pages of stuff to maybe find nothing or find it after a much longer time. I wanted to save developers the time and trouble and spill it out in an easy to follow format.
However that will begin to change in January. I will begin to do some intermediate to advanced articles as I can and instead focus on general Cocoa Development and likely Core Data. The reason I haven’t done any as of yet is
(1) I’ve been focusing a lot of time on learning new things by reading the Documentation and by experimenting like crazy more than any other time as a developer
(2) Im a Student still and I have an Open Source project AssignmentTracker X that I take seriously and another one I plan on starting soon. This project demands that I sacrifice a lot of my free time outside school and work to maintain it decently because I genuinely care about it (I use it myself) and I view it as a big part of my resume when I begin to apply anywhere for a job and as of yet I haven’t gotten that much done on the latest incarnation of it right now
(3) My tech support job working with Windows 98 POS (Point of Sale) Registers and Linux this fall has been more demanding than previously before (hey some things got easier, but still theres no patch for human stupidity) seriously though it's not that bad a gig... better than my job before that... Wendys...mmm guess what I did there
(4) As of late i’ve been doing a ton of time preparing to go to school full time, where before I was going part time and working a ton.
(5) In depth articles take time to write and i’ve been interrupted by all the above items
I hope that in January i’ll be able to arrange my schedule as such that I can have some dedicated blocks of time to work on my Open Source project and writing articles for Cocoa Samurai. For now my tech support will be a BIG drain on me which is why I haven’t done much for December and why Im not planning on doing any more articles for December. I simply need dedicated blocks of time to really get stuff done and having the phone interrupt every 5-10-15 minutes at work or when im at my apartment on pager is just annoying. Plus Im sure all you are either busy with finals or traveling around or preparing to travel regardless of where you are in life.
Now don’t think that the nice simple articles will vanish overnight because they won’t, but I hope to make this blog more appealing to all ranges of Cocoa Developers which is what I’ve intended from the beginning.
Lastly Happy Holidays everybody!!! I hope you all get what you want for Christmas or whatever you celebrate. Im just hoping to get that DS Lite and Brain Age :) And maybe the next article you read will have been written on a Core 2 Duo MacBook Pro (finally making the intel switch) instead of my current 1.25Ghz Powerbook G4 with 512MB ram :) Yes that’s how bad im off right now, on the other hand i’ve gotten good at optimizing my apps and finding what speeds up all the apps im using ( I just wish NeoOffice wasn’t so RAM hungry.) We’ll see what happens... have a great time everybody and a happy new year!
Thursday, December 14, 2006
[Alert] MacHeist Bundle!!! (Updated)
If you'll forgive me for not posting something totally mac development related...
I just thought since there was a Digg article earlier trying to rally people to this that I should do something and try and get the word out even further if I can
Were just past the halfway point in the MacHeist Bundle sale if I heard correctly and NewsFire has been unlocked as we reached $50,000 donated to charity. Still many people are evidently holding out on waiting till TextMate is unlocked. Well people if you hold out it won't be unlocked! At the rate things are going I fear we'll be just under the $100,000 needed to unlock TextMate.
It's not everyday you get insanely great Mac software for next to nothing and can donate money to charity all at the same time. Even if you don't want some of the software you can still give it to someone if you want. Personally myself I don't plan on giving up Vienna as I like having an Open Source RSS reader so at some point I will probably give NewsFire to someone.
If you don't know what TextMate is you can go here or here and find out or download a demo. I've been testing it and I love it, even if it probably won't replace Xcode for most of my serious coding work, but I've been finding for XHTML, PHP, and the small C examples I do in my books it's a sweet tool to have.
A bit of a misconception is that if you buy now you won't get TextMate, Im telling you if you buy now and MacHeist gets to $100,000 then you will be given it afterwards. Yes sometime soon i'll get my newsfire license even though I bought the bundle on the first day before NewsFire was unlocked (hey for Delicious Library, Disco and Rapidweaver alone it was more than worth the $49.)
Spread the word or if you were thinking of getting it just get it now I promise you won't be disappointed. You'll even discover some great new stuff and feel good donating some money to worthy causes. I had never tried Pangea Arcade before I got this and normally I probably wouldn't have bought it, and yet it's sucked up a big chunk of my time for the last few nights playing a couple of the games. Chances are you'll probably find a app you didn't think would be worth it but now like. Much respect to all those involved in MacHeist!
It seems like the rate of sales today is increasing slightly, but I know we can keep it up people!
[Update] As I discuss in the comments I didn't mean to seem like im putting TextMate down which im certainly not, I really like the app and Im using it more and more lately as I get the time to use it. However for my inital tests with Xcode projects im finding it hard to use TextMate interchangeably with Xcode and Objective-C. I'd be happy to discuss the specifics later, however my job has me swamped right now so this will have to wait until next week.
Friday, December 08, 2006
[Tip] When you must be precise be mach precise
Just thought i'd post a playful little tidbit. One of the things you should be as a programmer is playful and experimental. And todays tip I originally learned from Aaron Hillegass (yes the guy who write Cocoa Programming for Mac OS X) at the Student WWDC 06 Session, though you can find it documented on Apples site easily.
One of the things I do is play around with parts of a language i don't normally use to see what it's usefull for and sometimes test what benifets (if any) there are to it. One of the things I try to do from time to time is evaluate the speed of particular language features or methods in my apps. Probably the most accurate way to do this is to dig into the kernel and take time measurements in nanoseconds and that's what this simple little app does
#include < stdio.h> #include < stdarg.h> #include < mach/mach.h> #include < mach/mach_time.h> #include < unistd.h> int main() { uint64_t start = mach_absolute_time(); //you can do whatever you want between this... int i; for(i = 0; i < 2000; i++) { int l = 233 << 1; printf("\n\n%i\n\n",l); } //and here where we take the 2nd time measurement... uint64_t end = mach_absolute_time(); uint64_t elapsed = end - start; mach_timebase_info_data_t info; mach_timebase_info(&info); uint64_t nanoSeconds = elapsed * info.numer / info.denom; printf ("elapsed time was %lld nanoseconds\n", nanoSeconds); return 0; }in this case there isn't anything really important going in in this little test example, but you get the point of what benifets this can hold for you if you use it right.
Wednesday, December 06, 2006
Does Apple have a Grand Cocoa Strategy?
Well this week I’m a bit under the weather, but definitely getting better and still managing to get some coding done so I thought I’d indulge you with this bit of commentary that's been on my mind for a while. Before I do so I want you to know that Im working on a small something that mostly beginner Cocoa programmers may find very useful, though veterans may find it useful as well. I was amazed as I searched in Google to see if someone had already done this project and I couldn’t find one result that matched this. Then I searched Yahoo! just to make sure... nothing. Anyway I’ll reveal this once it’s done so keep tuned.
The Cocoa Strategy
One thing Im surprised i’ve never heard anybody discuss, or at least never seen it discussed anywhere (feel free to correct me if I’m wrong) is the strategy Apple has for the Cocoa (and related) Frameworks. For me learning Cocoa on Mac OS X 10.0.4 (on my first Mac a 733Mhz Quicksilver PowerMac G4) through 10.2 you got mostly a sense of... well this could be a great kit, it definitely has potential, but mostly you got the feeling that things were being fixed and brought up to standards.
It wasn’t till Panther ( Mac OS X 10.3) that I saw something in the SDK that made me really say wow (after everything you already saw wow at when being introduced to Cocoa.) That was Cocoa Bindings, it was like Apple saying “hey you remember writting all that code just to display data in a NSTableView? Forget it! Just bind it!”
At the time I was hugely impressed by this because this was a totally different style of programming. I had never conceived of not programmatically setting the data in a table. At first it feels like setting up some sort of intricate laser setup using precision angles with mirrors and saying “just trust me if you set this up like so it’ll connect.”
So now we have Cocoa Bindings. “Great!” you say. Then 10.4 Tiger came out and so did Core Data. More than this Core Data felt like a perfect extension of Cocoa Bindings. In bindings you got a huge reduction in code by letting Apple manage all this for you on the back end and all you had to do was make your Instance Classes Key-Value Coding/Observing ( KVC/KVO ) Compliant which was (and still really is unless you’ve become really lazy after Core Data) nothing hard to do at all. In Core Data you got data persistence, database-like querying and the ability to save data in 3 different formats with barely any effort.
When Tiger came out I thought to myself “Wow is this a grand strategy Apple has? Or are they just following up on the next logical step to make Cocoa better?” Looking at this you could easily make arguments one way or another. Wikipedia makes a comparsion of Core Data against an earlier NeXT Product called Enterprise Objects Framework. Now I’ve never used EOF, nor have I used WebObjects (which you use with EOF), but it does seem from the description that EOF and Core Data are definitely different in design, though somewhat similar in some of their functionality.
Could you say that Apple had a goal of one day of brining the functionality that now is Core Data to the Cocoa Framework? Maybe. This technology has obviously stuck around for years and years so Apple, or at least some part of Apple, has believed in it. However even if you think they really wanted this, surely there must be a grand strategy for Cocoa?
If you think this, then Leopard surely must put it to the test. We’ve put in a system (Bindings) to make some tasks which required a decent amount of code easy, then we put in a system to add data persistence and some SQL-like queries amongst other things. So what could be the next logical step?
Now because I went to WWDC 06 this gets slightly fuzzy in what I can and can’t tell you so I shall err on the side of caution when speaking of Leopard improvements. However I can say in this context that I didn’t see anything that spoke to me (strongly at least) that this is the next logical addtion to Core Data. There were some brand spanking new classes that were very impressive and used Cocoa Bindings (obviously.) The thing that spoke to me the most was the vastly improved Developer tools like Interface Builder (especially), Xcode and Xray. These new tools are practically like having a new framework which makes you vastly more productive.
So im curious what everybody thinks. Do you think Apple has somewhat of a grand strategy in mind for Cocoa? Or do you think Apple is more short sighted in this respect of just performing a great analysis of the framework after each Mac OS X release and giving the developers what they are trying to reach for? More or less what do you think should be included in Cocoa for Mac OS X 10.6? One interesting trend I see repeating itself over and over is that of Apple coming up with some great custom control (usually used in iLife) and then Cocoa developers working on their own custom implementation of that control, then Apple releases it officially in the next SDK for Mac OS X. I wonder how long that will continue?
Tuesday, November 21, 2006
[Commentary] TextMate and [Tutorial] Printing the contents of WebViews
Well things are a little busy this week, but im also getting things done fortunitely. I can finally fully walk around in my closet now thanks to my cleaning session I decided to do on my day off... hey it had to get done sometime. One thing I decided to do is to continue going through my C Book and finally get through coding all the exercises which leads me to my quick commentary on TextMate.
[Commentary] TextMate
I must say im rather late to the party when it comes to TextMate. The videos I saw gave me the impression it was a good text editor for code and so I downloaded it, but I never really gave it a try till recently. Last night I am going through my C programming language book by Denise Ritche ( I am determined to go through and code all the exercises in the book and I left off in the middle of the thing ) and so I decided to see how TextMate could handle the code from scratch and I can say after experience it handled everything excellently. Heck I could even tell TextMate to compile the C exercises for me so all I had to do was have a terminal open to execute the finished programs. Im still learning and evaluating TextMate before the trial is up, but it looks good and I think it’s something i’ll probably get here soon.
My only gripe with TextMate is that I wish it had code completion, but at the same time that might be venturing into the realm of starting to replace parts of Xcode which I don’t believe it’s meant to do.
[Tutorial] Printing WebViews
One thing you might think when printing a webview is that it should be as easy as something like simply going to File->Print when the WebView is visible or doing something like
- (IBAction)printWebView:(id)sender
{
NSPrintOperation *printOperation;
printOperation = [NSPrintOperation printOperationWithView:webView]
[printOperation setShowPanels:YES];
[printOperation runOperation];
}
However when this is run what happens? It only prints the visible bounds of the web view. At this point newbies and people unaccustomed to WebKit start to say things like WTF, etc. When you do this you are telling Mac OS X to print the WebView as it is visible. In order to print the whole contents of the WebView you must point it at it’s document view. So we end up with something like this:
- (IBAction)printWebViewContents:(id)sender
{
NSPrintInfo *printInfo = [NSPrintInfo sharedPrintInfo];
NSPrintOperation *printOperation;
NSView *webView = [[[myWebView mainFrame] frameView] documentView];
[printInfo setTopMargin:15.0];
[printInfo setLeftMargin:10.0];
[printInfo setHorizontallyCentered:NO];
[printInfo setVerticallyCentered:NO];
printOperation = [NSPrintOperation printOperationWithView:webView
printInfo:printInfo];
[printOperation setShowPanels:YES];
[printOperation runOperation];
}
Once that is is in place it will print all of the contents of the WebView. I set the margins myself in this case to try and make sure the specific document this method is printing fits the way I want.
[What do you want covered?]
One thing im starting to think about doing here soon is taking requests for covering various general cocoa topics. I used to be a n00b, but now Im sure I use a ton of things on a daily basis that I couldn’t figure out how to do when I was learning cocoa. If you think of something good post a comment about it here. I can’t guarantee i’ll cover everybody’s requests but if people want something explained in detail or elaborated on i’ll do my best to help you guys out.
[Happy Thanksgiving!]
Whatever you are doing this week I wish all of you safe travels or just a good time with friends and family regardless of what you are doing!
Saturday, November 11, 2006
[Tutorial] Lets get sorting
Well I am back people! This whole past couple weeks have just been crazy at work and in combination with hunting bugs in my first early Beta of AssignmentTracker X I haven't had much time for this blog lately, but now I am back and things have settled down and I am already full of stuff to post. Hey I'm just a student people, give me a break.
Well for today I am gonna post 2 things that made my own LicenseKeeper app a little bit better.
(1)I liked that I could easily store all my serial numbers, but I wanted them sorted by default
(2)When I resized the columns I wanted the app to keep track of the length of them
Let's get sorting!
Like many things in life Core Data has a slight trade-off in that you now have automatic data persistence, but the data is not sorted. If you create a Core Data app right now, like creating a simple table that displays entities with 1 attribute (lets say a name) and create a few entities without telling the array controller to sort them and then quit and reopen the app a few times, the order of the entities will be almost random every time.
So people new to Core Data then ask how do we keep this data sorted? Well Apples Documentations spells it out like so “ Objects in a persistent store are unordered. Typically you should impose order at the controller or view layer, based on an attribute such as creation date. If there is order inherent in your data, you need to explicitly model that.” In other words it's up to you to sort your data.
So all I did was create a controller class I called LKAppController with an outlet to the NSArrayController. Here is LSAppController.h.
#import < cocoa/cocoa.h > @interface LKAppController : NSObject { IBOutlet NSArrayController *licensesController; } @endThen I instantiated the class in Interface Builder and connected the outlet to the NSArrayController. And to sort the data I created a NSSortDescriptor and told the array controller to sort the objects it has with that sort descriptor in the awakeFromNib method. Here is LKAppController.m.
#import "LKAppController.h" @implementation LKAppController - (void)awakeFromNib { NSSortDescriptor * sd = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; [licensesController setSortDescriptors:[NSArray arrayWithObject:sd]]; [sd release]; } @endI should state that this is not Core Data specific, in fact this method can be applied to any array controller in Cocoa. Now this is easy because in this instance we have a bunch of objects that we just want to sort by their name. I suggest that if you have to have objects in some specific order for something like a Source list (where we might want some static items at the top then user items at the bottom of the list) that you create an attribute and call it something like “position” that's an int sort it like that or use some other attribute or method you like, the point is you must create the means to sort the way you want. The only area where it may get difficult to auto sort items is in NSOutlineViews in which case you may find this ( http://allusions.sourceforge.net/articles/treeDragPart2.php ) to be of interest. Keeping track of column length So now we have our data sorted by default I wanted to do something nice for myself and make the app remember the length of all the columns when I resized them so I could at any time change them to my hearts content. Many people don't realize you can do this, but if you poke around in the Cocoa Bindings you can bind the length as well as the minimum length and max length of the columns to an entity or in this case (to make things simple) to the preferences. So all you need to do is select the table column and go to the Bindings option in the IB Inspector. Select the width attribute. For this we'll bind to Shared User Defaults (once you select this you should see the “Shared Defaults” controller appear in the instances tab), with the controller key “values” and model key path “nameColumnHeaderWidth” for the name column. Repeat the process for each additional column (giving a unique name for each model key path) and now your app will remember the length of each column as you drag them! It's the nice little stuff like this that you do that your users will really appreciate when you put out your app.
Sunday, October 29, 2006
[Helpful App] AppKiDo
After posting about Docoa browser a couple people suggested I try AppKiDo which looked like a decent alternative. After testing it out for a while I thought I'd post some thoughts about it.
Upon launching it, AppKiDo takes a minute and begins parsing your documentation files, unfortunately this happens EVERY time you launch it. Upon completing this the documentation browser is launched. Right away unfortunately I saw something that I wish was different, I'm sorry but the brushed metal interface should really be changed to a unified interface. I installed UNO to see how AppKiDo would look with a unified UI (yeah I know I could have probably edited the NIB file, but I was lazy here) and it definitely looks better.
AppKiDo has somewhat of an odd interface, on the left is a drawer and on the right is where you can see all the documentation and it's various attributes. The Quicklist (drawer) has some usefull attributes like allowing you to only view things like view subclasses, classes with delegates, window classes, etc. Additionally you can search for classes, methods, etc in this drawer as well.
The window itself has 3 components: (1) A Browser (optional – can be hidden) This allows you to browse up and down the various classes as well as protocols, functions,etc for specific frameworks like AppKit, Foundation, Core Data, etc. (2) Detail view – This shows you the list of functions, procols, etc of any object you have selected. It has one big advantage over Docoa Browser and Xcodes Documentation browser in that it can show you all methods for a particular class, not only the ones specifically for that class but ones that it has inherited which makes AppKiDo very powerful in this instance. (3) The Documentation Viewer itself shows you the documentation for whatever you are looking at.
Overall AppKiDo is very powerful and definitely a good documentation browser. Yet at the same time I find myself wanting to rearrange the interface, AppKiDo doesn't feel natural. I may not know what the right interface is, but at the same time I know when something is wrong. Some things like the fact that I can browse classes just for specific frameworks on the quicklist drawer, but can't do the same in the browser feels incredibly akward.
Don't get me wrong I feel AppKiDo is a very powerful application, I just feel like it's user interface is holding it back and when it's interface gets a overhaul it could very well be the perfect documentation browser.
AppKiDo can be downloaded from here: http://homepage.mac.com/aglee/downloads/appkido.html
UPDATE: One commenter informed me I indeed overlooked the preferences where the brushed metal UI can indeed to be turned off, still brushed metal really shouldn't be the default
Friday, October 27, 2006
[Helpful App] Docoa Browser
Hello everybody! I just wanted to post something you may find interesting. Docoa Browser (based on Cocoa Browser from a LONG time ago) has been updated to run on the most recent documentation from Apple!
If you don’t know what Docoa Browser is, it’s basically a slim and fast documentation browser which allows you to browse most documentation by browsing through a simple column view which you can go through very quickly. I really liked this browser before when I was first learning cocoa and I still like it today. If you find the built in documentation browser to be a bit slow at times you can give Docoa browser a try. This was just posted to the Apple Cocoa mailing list yesterday, and I was only able to download it during my Ames Mac Users Group (AmesMUG) meeting, so I haven’t had a lot of time to test it, but so far it’s worked really well.
Now to be honest this app probably won’t satisfy all your documentation browsing needs, but it should perform well for basic documentation browsing. You can download it from here (warning! this is just the source code and not a prebuilt binary so you'll have to compile it yourself): http://www.muratnkonar.com/docoafortiger/Docoa-0.3.4mnk.zip
Tuesday, October 24, 2006
[Commentary] Thoughts on the HIG
Im working on my next tutorial which will appear soon, but for now i’d thought I’d share a few thoughts and see what you all think.
Ok once again there seems to be a big topic on everybody’s minds and this time it’s the Human Interface Guidelines. Scott has some insightful commentary on this. I believe early on when I first started learning Cocoa, I took a look at this document. As far as I can remember people have been chastising Apple for not following it. Right away some things didn’t make sense like the specific types of apps that brushed metal was supposed to be used on, etc.
Personally I don’t think I’ll read the HIG again anytime soon. Why? Because if you really think out a solution and take into account the users perspective while following what should be common sense, you don’t really need the HIG.
Remember when your designing an app, your designing a solution to a problem so you should try and make it simple. Right away when someone looks at your app it should be very apparent what the app does and give the user a good idea of how it works. If someone has to spend a good while looking around at your app to begin to figure out these things then your solution is already too complicated, they might not be able to use everything right away but they should get the gist of it.
A big pitfall of some developers is throwing too much at your user. A good example is maybe your developing a simple image edit app. If your user is typically a amateur photographer and just wants to maybe crop and do some adjustments to the image quality, do you think they’ll really need a metadata inspector window constantly showing and taking screen real estate?
Of course you can suffer from the exact opposite of this and throw too little at your user to the point where they are constantly opening up things. For example Im not pro photographer but, I presume Apple did some research and decided it was a good idea for pro photographers to have access to a bunch of panels for color correction, image adjustment, metadata, etc in Aperture.
Another thing I tell myself when designing UI’s is “Don’t be like the Windows developers!” Now this is not to say that all windows UI designers are crap, it’s just there are so many Windows programs I look at and go “why did they do this?” and “wtf is the purpose of this?” and so on.
One of my friends who goes to Iowa State University told me in one of his classes they covered this new Windows framework (who’s name escapes me at the moment, I think it’s the windows presentation framework or something like that) that can make all these magical UI effects. He was in a group and they were designing a UI which I believe was a login window or something like that. Should be simple right? Well they wanted to have a paper clip dance around the window and have other visuals. My friend (evidently being the only sane person in the group) didn’t like this idea. Around this time the teacher came by, now you think anybody who was sane would chastise the group for putting up such a dumb idea that wastes so much resources on something so simple. But the teacher thought it was a good idea. Now I should issue a disclaimer that not all teachers at ISU are like this thankfully.
So in conclusion here are the basic points
- Identify what the problem is your solving
- Define everything you require to solve the problem
- Don’t throw everything at once to the user, define the common tasks your users will be performing on the app and design around that (but allow them to get to the more complicated parts easily if they need to get to them)
- Design everything around the basic purpose of your app
- Go for the simplest solution first (you’ll get more done faster and your users will love your app because they can get things done faster) even if it takes a little bit of trial and error to find what that is “the simplest solution is usually the most elusive” - Jonathan Ive (may not be exact quote, I can’t find my iMac movie)
- Don’t waste resources on things you really don’t need in your app.
Monday, October 16, 2006
Coming Soon...
Sorry I haven't written for a little bit, first I was surprised that I was picked up by CocoaDevCentral and then I kept spending lots of time working on AssignmentTracker X. The Good news is im planning on an expansion into the LicenseKeeper app and will show you how to auto sort items in Core Data and always restore the length of columns the user sets them to in tables, and maybe a couple other little things if I get around to it.
It's just an easy one to get me back on track of writting here more. For now I must work on getting AssignmentTracker X 2.0 Beta 1 out the door then I'll write here.
Monday, October 09, 2006
Holy Crap I've been picked up by CocoaDevCentral!
I was taking a random look at the performance of my sites and realized I never looked at how my brand new blog Cocoa Samurai is doing. When I saw the chart I saw a huge surge of visitors to the page, when looking at where the visitors where coming from I saw CocoaDevCentral on the list. When I visited the page I saw my name right next to Wil Shipley.
Friday, October 06, 2006
[Commentary] Cocoa vs. Carbon
Wil Shipley seems to have started what eventually would become a big rolling snowball with his entry linked in my previous entry. It's gotten Daring Fireball and Scott Stevenson talking.
What's going on here is a grievance against the fact that several frameworks Cocoa programmers must use are only available in Carbon. Why is this a big grief? Carbon frameworks are written in procedural C style language which is a big departure from the object oriented style of Objective-C.
The reason I prefeer Cocoa/Objective-C myself is because it's so easy to use and get straight to what you want. A good starting example of this is CTGradient which I am using for various elements in AssignmentTracker X currently.
CTGradient is an Objective-C wrapper around Core Graphics (which is written is Carbon/Procedural C) and because of that I can write a couple lines of code and be done with it. To be specific heres a short example of a NSView subclass using CTGradient copied straight from AssignmentTracker X's 2.0 source code
@implementation ATXStartupWizardBackgroundView - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; if (self) { swGradient = [[CTGradient unifiedNormalGradient] retain]; angle = 90; } return self; } - (void)drawRect:(NSRect)rect { [swGradient fillRect:rect angle:angle]; } @endsimple and really easy! All you have to declare in the header is a CTGradient instance and a float for the angle, and if you take a look at the CTGradient source code... well it's doing a lot for you for such a simple function of creating a simple gradient grafted onto a NSView. In fact way more than I'd ever want to begin to show you here, just download it and take a look at it for yourself and you'll get an idea of why if this is a lot for just a gradient, it must be a ton for other functions. It's not that C is crap, far from it. I still continue reading through The C Programming Language 2nd Edition written by Denis Ritche himeself and appreciate a lot of things in C. C is a good programming language but in some instances like it's used in Carbon, it clearly shows it's limits. Heres something that's never really been said yet (at least not directly), when your going from Cocoa to Carbon your literally thrown from one world to another. When your in Cocoa your relatively familiar with the bounds, limits and expected behaviour of cocoa world, then suddenly your thrown into the land of procedural programming. At the very least Apple should be aware this severely limits the learning curve for new programmers or even Cocoa veterans who have never touched Carbon before and thus limits the productivity of the mac developer community as a whole. I have to agree with Wil Shipley here in that regardless of Carbons origins it's only been used as a compatibility library and really to help all the Mac programmers out there we need to move all the frameworks to Cocoa. When they are all moved to Cocoa, Apple can do all the optimizing on the backend and provide us with an easy Objective-C interface on the frontend in a similar way that they did with Core Data, thus reducing the amount of code in all apps, increasing programmer productivity, and allowing more of the devleoper community to show off all the great stuff in Mac OS X.
Thursday, October 05, 2006
[Links] Cocoa vs Carbon & Searching with Google Code
Wil Shipley on Carbon vs Cocoa
Our good friend Wil Shipley has written up a good article on why some frameworks desperately need to be moved from Carbon to Cocoa: http://wilshipley.com/blog/2006/10/pimp-my-code-part-12-frozen-in.html
Scott Stevenson on searching for code with Google Code
Scott Stevenson has written up a good starter intro to searching for code under specific programming languages and licenses: http://theocacao.com/document.page/312
Moved to Blogger Beta
If you get all articles brand new in the RSS feed it's not a bug in your RSS agregator it's the fact that I just moved my blogger blogs to Blogger Beta which is great because it doesn't require that I spend time waiting for articles to publish now it's just done. The only downside is that once I publish the first article under the new beta all articles come as brand new.
Monday, October 02, 2006
[Tutorial] Good Documentation with Doxygen
Well today's tutorial isn't specific to Cocoa, but it's a good tool Mac Developers should use. Doxygen is a simple tool that goes through your source code and auto generates documentation which you can browse through in several formats. If you've browsed through Xcodes menu's you'll have noticed in the Script menu there is a category for HeaderDoc which Xcode provides the ability to insert predefined HeaderDoc comments for generating HeaderDoc documentation.
After some experience with HeaderDoc I can tell you it's no where near up to par with Doxygen. Doxygen's documentation is much easier to browse through and much nicer on the eyes as well so I'll show you how to use Doxygen.
Step #1 - Download Doxygen
Download Doxygen from here: http://www.stack.nl/~dimitri/doxygen/download.html#latestsrc
Step #2 - Create your Projects Doxyfile
The thing about Doxygen is that you don't need to actually distribute the documentation, you can just distribute the Doxyfile for your project which is a configuration file that tells Doxygen how you want it to create the documentation. When someone wants the documentation all they need to do is load the Doxyfile into Doxygen and tell it to go and generate all documentation.
So now lets launch Doxygen, you'll get a window like this
Before we continue I reccomend (though it's not necessary) that you create a folder called "Documentation" in the root level of your project directory (the same one that has the *.xcodeproj file.)
Now click on the Wizard button...
Here you fill out the basic info about the project like the name, version, etc. The source code directory is where you have placed all your source code files you want Doxygen to create documentation for. Really you should have a "Source" folder at your root level of your project for all source code (not auto generated by Xcode) in your project, either way point the source directory at the root level of your project directory and tell it to scan recursively. Then point the destination directory at your newly created Documentation directory.
Switch over to the "Mode" tab...
Here is where you may want to change settings to what you personally (or your team) want. Personally I reccommend that you tell Doxygen to generate documentation for all entities and include corresponding source code so you know everything that is and isn't documented as well as see what was in the source code at the time the documentation was generated. Leave it optimized for C++ output and switch over to the "Output" tab.
Here again you can chose what you like, but really the easiest to navigate around in (IMHO) is to generate with frames and a navigation tree. The search function requires PHP and since Xcode can search your methods and text pretty well i'd leave that alone as it's really unecessary. You'll also want to uncheck the LaTeX option and if you like you can also generate a nice RTF file containing your documentation as well.
After that switch over to the Diagram tab and tell it to not generate any Diagrams as Xcode can do this much better than Doxygen can. Click ok and you'll be brought back to the Window though Step 2 will say it's not saved. Click the save button and save the Doxygen file in your Documentation folder.
Step 3 - Generate the Documentation
Now by Step 3 on the Doxygen window click the Select button and point it at your Documentation folder. Then go down to Step 4 and click the Start button and Doxygen will go through and start generating your documentation. When you look at your Documentation folder again you'll see a html folder and (if you selected it) a rtf folder for each type of Documentation respectively. You can browse through all your classes now... the only thing is theres no documentation just a listing right now.
Step 4 - Write Documentation
So lets write some documentation! Ok well it's not that painful, trust me it'll help a lot of people. Everytime I think about documentation I remember this quote from a KDE mailing list
in your header file of the class your documenting...
Documentation is like sex, when it's good it's really really good and when it's bad it's better than nothing at all.So here's how you write Doxygen documentation For instance items in your header (*.h) file you would create documentation like so...
NSButton *saveButton; /**< On main window to save all data */ NSArrayController *objectsArrayController; /**< Main table columns are binded to this array */ NSWindow *mainWindow; /**< Window visible at launch for loading views into */The next type of documentation can be done on your header file as well as your *.m implementation file for method documentation
/** Generates a number of categories from the number specified in n @param n number of categories to generate */ - (void)generateCategoriesWithCount:(int)n;the "@param" is used to tell Doxygen about the method parameters you want it to document. Lastly you can provide a description of the classes themselves in the Documentation. This I would place before the #import
//! ATXAboutBoxController. /*! ATXAboutBoxController is a class based on Adium's LNAboutBoxController with some tweaks and is designed to display the aboute box in a scrolling credits text box with some simple version information on other text labels, setting options in Interface Builder whenever possible. */Once you do that to all the source code you can and rerun Doxygen, you get something beutiful... Questions? Comments? Write a comment below to let me know what you think!
Wednesday, September 20, 2006
[Tip] Pragma Mark ( Organizing your source code )
Well I've just been frustrated today by several things going on including getting a wireless ethernet adapter to work so to get my mind off everything I thought i'd just post an easy quick tip before going to bed.
One thing many new people aren't aware of in Xcode is the Pragma mark in source code. Pragma mark is simply a way to organize your methods in the method list pop up button in Xcode (as were using it here, though there are more uses of pragma mark on other platforms/IDE's.) On a default project you might see something like this
Now on a very small project with only a few methods that's not really hard to go through. The problem is as soon as you have a ton of methods in any one file it's difficult to do down through the list and find the one method your looking for, and even if you don't have a ton of methods you should use pragma mark to help you organize your code for yourself and (if your working with anybody else) your team. With pragma marks you can do 2 types of labels
#pragma mark -which will simply put a horizontal line spacer in your code. (Warning! - When using this you cannot have a space after the "-" otherwise Xcode assumes you are making a text label (below in next example) and won't insert a horizontal spacer line.) And there is
#pragma mark label namewhich will add a label in bold to your method pop up list. When using this one be very simple and to the point so it's obvious of where the method your looking for is at. So if we add some of those pragma marks to the source code like
#pragma mark Initialization Methods #pragma mark -to the source code when we want to add a label you can make the list now look like this Now again this example is small and that second label doesn't make sense where it is (just wanted to put a 2nd one in there), but when you start getting into bigger and bigger projects it's practically mandatory to add pragma mark labels and spacers to your source code. Do yourself a favor and from the start of working on a cocoa project use pragma marks to help you organize your code. Remember that Xcode reads methods on any given file you are viewing/editing from top to bottom and will put the methods and labels on that popup list as it encounters them. It may not matter where you put your methods in your file for compiling them, but it will matter where your methods are if you intend to use the pragma mark labels.
Tuesday, September 19, 2006
[Link] Using delayed messages in Cocoa/Objective-C
Just thought I'd quickly post this while coding tonight. If you haven't seen Scott Stevensons Blog Theocacao you should as he posts a lot of great tips.
Recently he posted about using delayed messages in Cocoa, specifically within the context of awakeFromNib methods (though this can be used anywhere) which is called right after all the contents of the nib are loaded off of disk or at least that's how it's supposed to work. Sometimes awakeFromNib is called when the contents of nibs aren't truly 100% loaded so therefore the need to delay a method execution can be helpful. In my experience this is rare (at least on my PowerBook G4) though it can happen. At the very least it could help you in the future. Take a look at his post.
Using Delayed Messages in Cocoa
[Correction] Prototyping Interfaces Tutorial
In my first tutorial I realized I made one significant mistake and left something out
For the NSTextView in order to bind it to "value" you must uncheck "Multiple Fonts allowed" otherwise it assumes you are working with a NSAttributedString (string with attributes like bold, italic,etc) vs a plain NSString.
Sorry for any confusion this may have caused.
Monday, September 18, 2006
[Question] Is NSEnumerator really faster than using a for loop?
Now this is a classic question. One of the strange things you see just learning Cocoa/Objective-C is this thing called the Enumerator loop which looks something like
NSArray *anArray = // ... ; NSEnumerator *enumerator = [anArray objectEnumerator]; id object; while ((object = [enumerator nextObject])) { // do something with object... }and naturally people ask if using NSEnumerator is really faster than using a for loop like this example
NSMutableArray *my array = //... int i; for( i=0; i < LIMIT ; i++) { NSManagedObject *obj = [myArray objectAtIndex:i]; //do something with object }The answer to this question is yes just a little bit though. I've been told by some smart people (though I haven't verified) that the kernel XNU on Mac OS X is optimized for Objective-C messages, even if you don't believe that we all know Apple optimizes so much of their own software to take advantage of Altivec(PPC), hardware accelleration, etc. So naturally you should assume Apple has given you some reason to use this loop. To test what is really faster I went to CocoaDev and grabbed code off a page where a discussion on this very topic took place (take a good look at the source code.) I compiled this code myself and then ran it once, cleared out the test and ran the test 3 times, all tests using 10,000 objects and 10,000 iterations then punched in the results in NeoOffice. Here are the results (all times are in seconds): (pay attention to the NSEnumerator and for loop tests (first 2 on the left in the graph) for now) as you can see yes the NSEmumerator loop is faster than the for loop but only by a few seconds and that was with 10,000 objects and 10,000 iterations. When I did the same test with 1,000 objects and 1,000 iterations the results all land roughly within 1/10th of 1 second +/- a few milesconds. The conclusion Really just to stay in Cocoa standards you should use NSEnumerator, but at the same time it's not the end of the world if you don't. There are some examples where you might really need to know what the index of the object your dealing with is, in which case you should use a for loop. Now as for those last 3 tests on there aren't that important, I included them because they do show you can gain some speed by really optimizing the heck out of your code if you really want to do so. I encourage you to go to the CocoaDev page linked above and look at the code for yourself to see what you really want to use for yourself, but as you'll see the code is vastly more complicated than you'll want unless you really need to squeeze every last ounce of peformance out of your application.
Saturday, September 16, 2006
Introduction and [Tutorial] Prototyping Interfaces with Interface Builder
Introduction
Welcome everybody! I find most tutorials out there are really good, but sometimes they leave out some better ways to do one part of the tutorial or I just find nobody really explains how to do various little things. That's why I started this blog, I wanted to post various tips, tricks and tutorials on how to do various tasks that all Cocoa Programmers go through and at the same time get discussions going on everything in Cocoa to help everybody out. I believe that by doing this I help you and myself at the same time.
In everything I do I also believe in the term Wil Shipley first used* "Code Samurai." By that I mean that you try and hold yourself to high coding standards and always are striving to master Cocoa.
[Tutorial] Prototyping Interfaces with Interface Builder
For my first tutorial im going to start out simple with an app I initially gave to one of my friends to do, but he was lazy didn't have time. But I wanted bad enough (even though I wouldn't use it that often) that I did it myself in a few minutes. I called it LicenseKeeper and all it does is store licenses to various applications you have and allow you to sort through them and perform live searches, and add your own notes all with 0 lines of code**. And now i'll show you how to make this app.
First off launch Xcode and create a "Core Data Application." File -> New Project
Call the application LicenseKeeper and save it where you want.
The Data Model
In Core Data you don't create Instance Subclasses to create objects, you create Entities and use the data model to define the structure of the entity. So now double click the LicenseKeeper_DataModel.xcdatamodel file on the source list to the left so it opens the data model in it's own window.
Now we'll just create one Entity "License." Click on the + icon in the Entities table and name the Entity "License." Then on the properties pane just to the right click on the "+" button and click on Add Attribute, then do this 2 more times. Name the attributes "name", "serialNumber" and "notes." Define all 3 of these to be Strings from the popup button in the detail pane or in the table itself.
Next open the MainMenu.nib file by double clicking it in the source list and drag the window (height wise) to be bigger by a few inches. Now (heres the tricky part) just click the data model window and move it over so you can see the window in Interface builder and the entity in the data model. Got it? Good.
Now hold down the alt/option key and drag the entity from the data model window to the interface builder window you just resized. As soon as you let go Interface Builder will ask you if you want to prototype the interface for one object or many objects. Select Many Objects.
Assuming you did everything correctly you should end up with an interface looking like this
Now this interface is really good even for a basic application, it obviously has some quirks. For starters Interface Builder lists your attributes in alphabetical order and so the license key and the notes should be switched around in the table and the detail part of the view.
So first off you'll have to double click inside the table view to really click the header and move it around, so move the serial and notes headers around. Additionally swap them around (vertically) in the detail section below the table and delete the textfield for the notes and instead drag a NSTextView to it instead and resize it vertically to be bigger.
Double click inside the text view and on the inspector pane (make sure the inspector says NSTextView instead of NSScrollView) bind the "value" to the License Array Controller with the controller key "selection" and the Model Key Path "notes."
Lastly change the Window title to "License Keeper" then Save and quit Interface Builder. Go to Xcode and hit the Apple + R key to build and run the application and it should run like in the screenshot below
What did we just do?
We accomplished several things today
1. We built a Core Data Application
2. We created and defined an entity
3. We dragged the entity over and prototyped an inteface within Interface Builder
3. We rearanged the interface and binded an NSTextView object to an attribute in our entity
This is a very simple application, but also a very capable one that benifets from Core Data so it has undo, redo, live search and persistence. By default Core Data applications store their data (in non Document based application template) in XML format. Core Data allows you to save your data in XML, SQL (sqlite) or Binary formats and you can change it, but i'll leave that for another day.
Questions? Comments? Think certain parts of this tutorial could be written better? Want me to expand on a certain topic?
Leave a comment here
* at least amongst mac developers as far as I am aware
** aside from the predefined code Xcode auto-generates
Friday, September 15, 2006
Cocoa Samurai Opens Soon...
Soon I'll open this blog and begin bringing you some great Cocoa/Xcode/Developer Tool tips!