Toolbox - Create NSObjectWithBenefit

In the Toolbox category I will provide you with a set of customisable extensions for different classes. I've a dedicated .h / .m file for this implementations. I named them TCExt for my custom extensions. You can import it whenever you need one of the following functionalities.

Today we will add a new superpower to our repertoire: Since pretty much any object within the Cocoa framework is subclassing NSObject, there are some benefits we can achieve by extending it. Use the following code carefully. It is immensely powerful, but should be used deliberately. The basic idea behind this is to extend every instance of the NSObject class with a setter and getter method for an NSMutableDictionary. This means that you can add any object you want for a key to any other object. It is enourmously helpful when working with TableViews. How often have you created an instance variable for a tableViewController just to save the last used cell? Now you can just pass this information around using this method.

Put this in your header file:

#pragma mark - NSObject

#pragma mark Associated Object

@interface NSObject (TCExtAssociatedObject)

- (id)tcExtAssociatedObjectForKey:(NSString *)key;
- (void)setTCExtAssociatedObject:(id)object forKey:(NSString *)key;

@end

 

And this in your implementation file:

@implementation NSObject (TCExtAssociatedObject)

static char staticTCExtAssociatedObjectKey;

-(void)setTCExtAssociatedObject:(id)object forKey:(NSString *)key
{
    NSMutableDictionary* dict = objc_getAssociatedObject(self, &staticTCExtAssociatedObjectKey);
    if (!dict) {
        dict = [[NSMutableDictionary alloc] init];
        objc_setAssociatedObject(self, &staticTCExtAssociatedObjectKey, dict, OBJC_ASSOCIATION_RETAIN);
    }
    [dict setObject:object forKey:key];
}

-(id)tcExtAssociatedObjectForKey:(NSString *)key
{
    NSMutableDictionary* dict = objc_getAssociatedObject(self, &staticTCExtAssociatedObjectKey);
    return [dict objectForKey:key];
}

@end

Now you just have to import the headerfile and use it like this:

[yourObjectWithBenefit setTCExtAssociatedObject:yourExtraObject forKey:@"keyForObject"]; // Set extra information

[yourObjectWithBenefit tcExtAssociatedObjectForKey:@"keyForObject"]; // Get the extra information

Just remember that you've to import the headerfile if you want to receive the information from a different class.

Advanced Codesnippets - Logging Snippets

As I mentioned before already, I'm a big fan of a documentation- and snippet-tool called Dash. I spent quite some time on developing a set of custom snippets that save me lots and lots of time. Objective C (if used correctly) is a language that is a joy to read. Functions implement parameters in a way that you can read them as if they're English sentences. This style has its negative sideeffects: Everything you do involves lots of typing.

But this 'problem' is solvable. I will post my personal solution for problems like this in a series of posts called Advanced Codesnippets. Everytime I post something remember: This is just the way I do it. Feel free to modify everything until it fits your needs.

Sometimes we want to log the value (or contents) of an object.

Here is my snippet called 'nlp-': This abbreviaten stands for: [N]S[L]og[P]arameter. The - is my symbol of choice for signing every snippet.

NSLog(@"@clipboard:%@\n",@clipboard);

All you have to do is to copy the name of the object and type the name of the snippet. The result can be seen in the video below.

But we can take this a step further. When working with arrays you oftentimes want to check how many items it contains. When you want to log this into console you'll have to write a pretty long line of code.

Here is my snippet called 'nlac-': This abbreviaten stands for: [N]S[L]og[A]rray[C]ount.

NSLog(@"@clipboard Count:%d\n",[@clipboard count]);

For a long time I also added following line after the snippet automatically:

// TODO: Remove

But this has been no practical solution for me because it cluttered up my todo list way too much. Maybe it's helpful to you though.

(If the video is not embedded for some reason, click here)

Thank you!

Thank you very, very much for all your feedback! I'm astonished how positive it has been and how much I actually got. Let me put it in some perspective: I've had around 400 unique visitors (visitors with bot-like behavior subtracted) in the first 4 days. Around 30 people sent in feedback (26 positive, 2 negative and 2 both). Some of you even send me Promo-Codes for their payed Mac OS X applications. I'll give them a try and if I can incorporate them into my daily workflow, I'll blog about them! So let me comment on the feedback I got so far:

  •  Current web address (http://176.28.14.172/tommi) looks a bit odd
    • You're absolutely right! The domain has been used by a close family member for the last 15 years and currently we can just do a redirect because an application of him uses the domain to receive data. We're working on this though.
  • Aesthetics of the blog, big images, text formatting
    • The last time I used a blogging software it was Serendipity about 5 years ago. Many things have changed and I'm fairly new to Drupal. I'm not 100% satisfied with the current look and will refactor a lot of it. The images on top will be replaced soon too.
  • Twitter
    • To be honest I'm not a big Twitter fan. I will tweet when I write a new article though. Feel free to follow me there.

 

Next steps and future plans:

I was asked, why I'm not using a Wordpressblog for this site. In it's current state you're right: For blogging WP would be much more adequate than a CMS instance. But I plan to also use this as reference, FAQ and service page for users of my soon-to-be-coming application.

 

Because I've to finish the application first and work at the same time, some content (except from the blog) will have to be in the queue until release.

 

Thank you all so much for the kind words! It really gave me confidence to pursue this path. If you've got any questions, feedback or comments feel free do drop me an email or a comment. You're welcome!

My Top 5 Mac OS X Developer Apps - March 2013

First of all: No, this is not one of the 42 bazillion "Top X Apps" lists you can find when you 'searchengine' it. I really don't care if you prefer Alfred over Spotlight, Chrome over Safari or Spotify over Pandora... Following apps are not about all those hipster videos you find on youtube. It's about saving time. Lots of precious time in your day as a developer. 

While getting more and more serious about programming and coding I oftentimes caught myself in bad habits or inefficient workflows. Since I realized how much time I wasted on daily repetetive-mini-tasks, I've been trying to get rid of them step by step. Most of them have been solved by the following applications. I'll try to explain why I love those tools so much.

Moom 

Moom is a window-management tool. Since Apple decided to improve (ruin) working with Spaces in Lion I don't use different Spaces and desktops anymore. Yes, I absolutely loved this feature in the Leopard & Snow Leopard days, but since Lion it's just a slow, animated and hard to control mess. I found myself juggling with different windows way too often and tried many tools until I found this one:

It enables me putting the windows I need right where I want them to be within less than a second. Switching screens? - No problem. Resizing? - No Problem. Everything works like it should. You can even save custom layouts for programs you usually use together. If you've opened a browser and your favourite html-texteditor, automatically put them next to each other. I can't even estimate how often I use it... >150 times a day?

CmdVees

Imagine the following: You're surfing your favourite coding site just to find the perfect solution for one of your problems... You need 3 lines of code put in 3 different places in the answer. Usually you would start by copying each line, tabbing into your editor, pasting it and going back. You're wasting time switching windows and reorientating yourself 6 times. This little tool adds a queue- or stackfunctionality to your clipboard. You can stay on your page and copy each item seperatly. Now go back to your coding window and paste by using [shift+cmd+v] and the last copied line will be pasted and popped from the stack. Press the same shortcut again and you get the line before. If you use the standard paste shortcut you can paste the same item as often as you wish. Pure magic. (Little hint: The standard shortcut configuration is a bit strange, just switch paste with standard paste)

Dash

Can't describe how much I just love this little cat-icon in my menubar... First of all: You have a lightning fast shortcut to any documentation you need. Cocoa? Python? Ruby on Rails? Java? Just download the documentation and import it. Now you're just one shortcut and search away from it.

My mainfeature is the codesnippet library though. You can set Dash up to listen to all your inputs and replace them. You can predefine the cursor location and replaceble segments of your snippets. For example:

@property (nonatomic, __PROPERTY__) __CLASS__ *__NAME__; /* @cursor */

I bound this snippet to "prop-". When I type this, a small window opens and the first replacement section (__PROPERTY__) is activated. Because I'm still programming with- and without automatic reference counting I've to interchange between strong, weak and retain a lot. I can then just fill out the gaps. When I hit enter the cursor sits already in the comment section reminding me to comment what's the use of this property. I've put some thought in lots of other snippets but this will be a blogpost of its own.

Dropzone

This is a neat little interface to create your own toolbox. It gives you access to a grid of icons in the menubar and an optional circle popover on one side of your screen. You can put tasks you use often in there. For example: I want to share a file via dropbox. I just drag and drop the file onto my "Share via Dropbox" icon and the file will be uploaded into my dropbox, set to public and the link will be copied into my clipboard.

Or I want to share some files with a colleague: Just drag them onto the mail icon and all my files will be zipped and put into a new mail draft automatically. There are about 30-40 of those workflows available on the DropZone website and you can create your own too!

Any Send

You've got several colleagues in your local network you're working with? And you're tired of putting files in your public folders or sharing emails? Well, then this one is for you: Everybody in your local network who installed the application will be shown to you when you click on the icon in your menubar. Then just click on the person and the file, text or link from your clipboard will be copied to the persons Mac. You can even configure it to automatically open links in a new tab (Well. You can. But don't. Nobody can resist the temptation of playing a joke on you ;-)).

These are the apps I currently (March 2013) use and love most. I saved so much time with them that they're worth every single penny. I thought of putting in SourceTree(Git-Rep Manager), Sublimetext 2 and Fantastical. They came close but are not as "irreplaceable" as the 5 above. Hope this was a worthy list of nice applications. When I searched for those kind of lists I found nothing but utter crap.

Creating a NSNumber++ macro

We all stumbled upon it: While using an NSNumber object we had to increase its integer value by 1. How did we do it? Since NSNumber is not mutable, we had to recreate the whole object by using a complicated looking and confusing line of code.

NSNumber *numberObject = [[NSNumber alloc] initWithInt:1]; // Init of our NSNumber object with integer value of 1
numberObject = [[NSNumber alloc] initWithInt:[numberObject intValue] + 1]; // Mentioned above line of code

Adding (Do NOT overwrite anything) this macro to your "YourAppName-Prefix.pch"-file will give you the opportunity to make your code more readable:


#define NSNumInc(n) do { n = [NSNumber numberWithInt:[n intValue] + 1]; } while (0);

From now on you can simply use:


NSNumInc(numberObject);

Keep in mind, that this does not make NSNumber a mutable object. We are still recreating the object. do not use it as a loop counter and for similar operations. You should stay with vanilla int for this.

How to create your own logging method...

As a developer logging to console is your daily bread and butter. You are probably using the provided NSLog() method to do so and there is (almost) nothing wrong with it. But what happens to your log-statements, when you release and ship your code? They'll keep logging and cluttering up every console. Well, more than >95% of your users will probably never check their consoles, but the ones whose consoles you're messing with will dislike this a lot. It is not just untidy and dirty but it can also become an embarrassing security issue for your application!

The standard procedure to handle this problem is to search for every NSLog() statement and comment it out or delete it every time you build a new release. This works, but wastes your time. Especially if you have to comment them back in later.

So let's fix this problem once and for all.

When working in xCode you've multiple options how to compile your project. The important ones are the "Debug" and "Release" options. Open your projects build settings and search for the preprocessor-macro section. Set "Debug" to 1 as seen in the screenshot:

Then open the "YourProjectName-Prefix.pch" file and add (do NOT overwrite) the following lines:

#ifdef DEBUG
#define DebugLog(message, ...) NSLog(@"%s: " message, __PRETTY_FUNCTION__, ##__VA_ARGS__)
#else
#define DebugLog(message, ...)
#endif

From now on all your logs will disappear when the debug flag is set to 0. From now on your logs will also provide you with additional information from which method / function you're currently logging:


NSLog(@"This is your standard logging method");
DebugLog(@"This is the new logging method");

2013-03-05 18:08:19.413 YourProjectName[13603:303] This is your standard NSLog()
2013-03-05 18:08:19.414 YourProjectName[13603:303] -[AppDelegate applicationDidFinishLaunching:]: This is the new logging method

Hello World!

Who would've thought that I'ld ever create a blog / website regarding myself again? Well, most certainly not me - At least not until the project I've been working on for the last couple of months reached a state where I had to consider releasing it. Right now I'm considering several different directions this blog / website could adopt to. The most probable way will be a blog where I'll write about iOS / Mac OS X Development and programming topics I find quite interesting. Additionally I'll create a page for each project that has been released (I hope to get done with the first one until April) and a page about myself. Because I don't have time to translate everything in German and English, I'll keep it in English. I'll reconsider multiple languages later... So long!

Tags: