<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;D0IASH4zeSp7ImA9WhdXGUU.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387</id><updated>2011-09-03T00:45:49.081+07:00</updated><category term="cocoa" /><category term="tech" /><category term="my life" /><category term="nscodernsk" /><category term="opinions" /><category term="crashkit" /><category term="howto" /><category term="programming contests" /><category term="stuff" /><category term="coding" /><title>Mikhail Kalugin's blog</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://fourdman.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>57</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/MikhailKaluginsBlog" /><feedburner:info uri="mikhailkaluginsblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DEUMSHk9eSp7ImA9WhZVEE0.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-6310767755738730224</id><published>2011-05-22T02:29:00.002+07:00</published><updated>2011-05-22T02:31:29.761+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-22T02:31:29.761+07:00</app:edited><title>Symbolicating crash logs</title><content type="html">&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;Introduction&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This post is devoted to a frequent routine of many iOS/Cocoa developers: symbolicating crash logs from users. If you're not interested in details and just want The Solution you can go directly to the section named "symbolicatecrash".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;The Solution to what?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, according to Apple's &lt;a href="http://developer.apple.com/library/ios/#technotes/tn2151/_index.html"&gt;Technical Note TN2151&lt;/a&gt; one can symbolicate crash logs just dropping them at Device Logs section in XCode's organizer window. All what they ask you for is a dSYM and .app file somewhere on your disk.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In practice, that's not so smooth. As for me, it never worked as supposed to. Well, it works fine for the latest debug build. But never for any of old AdHoc builds. All you can get from XCode is just symbolication of stack frames related to system libraries, but frequently that's not enough to realize what went wrong.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;Symbolication crash logs manually&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the follow chapter I'll try to explain how one can symbolicate a crash log without XCode. Our main tools here will be atos, otool and dwarfdump.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A few words about what is a crash log. That's basically just a plain text file. It contains three sections in essence: headers, stack traces for all threads and binary images information. Headers contain basic info about device, crashed process, versions, date/time and crash reason.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Stack traces look like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;...&lt;br /&gt;10  YandexMaps                     0x00003a22 0x1000 + 10786&lt;br /&gt;...&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, a frame number goes, then binary image name, then an absolute frame address, finally the same address, but represented as a sum of binary image load address and offset. The process of symbolication is exactly about converting that frame address into a readable symbol name. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The end of file contains a list of all binary images loaded. The list consists of lines like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;0x1000 -   0x1bbfff +YandexMaps armv7  &amp;lt;257b985709d23dc690477e12bc17fa48&amp;gt; /var/mobile/Applications/97CB76B8-19C5-4266-938E-26669B5CCAD3/YandexMaps.app/YandexMaps&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, image's address range goes. Then image name, architecture, image's UUID and a path, from where the image was loaded. The UUID is actually the most important info here — that's the key to finding a corresponding .app/dSYM file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;dwarfdump&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If configured properly, XCode creates a dSYM file together with every app build. dSYM files contains debug information (sadly, for your app only) in a widely used DWARF format. So dwarfdump is a command line tool for dumping info from such files.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First thing you do is finding a corresponding dSYM file for your crash log. The UUID described in the previous section is the key. You can get the UUID from a dSYM file with the following command:&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;dwarfdump --arch &amp;lt;arch&amp;gt; --uuid &amp;lt;dsymname&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;If you store all dSYMs in a specific place, you use grep to find the necessary one:&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;dwarfdump --arch &amp;lt;arch&amp;gt; --uuid *.dSYM | grep &amp;lt;first-digits&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Finally when you find the dSYM, you can get information about a frame address:&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;dwarfdump --arch &amp;lt;arch&amp;gt; --lookup &amp;lt;address&amp;gt; &amp;lt;dsymname&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Usually dwarfdump is enough to extract information about all your app's stack frames — you just go line by line. Unfortunately, that doesn't work if you're curious about frames belonging to system libraries. That's where we need the next two tools.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;otool and atos&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Surprise: there are no dSYM files for system libraries in the SDK. Good news are that we can extract all necessary information directly from binary images. We could do that with our app as well, but usually it's much easier to store just a dSYM file instead of a pair of the dSYM and .app. &lt;/div&gt;&lt;div&gt;Exactly as with dSYM, first we need to make sure that we have a binary image with matching UUID. We can read image's UUID with otool:&lt;/div&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;otool -arch &amp;lt;arch&amp;gt; -l &amp;lt;binary-image&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;div&gt;The output is quite long but we're only interested in a section like this:&lt;/div&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;Load command 7&lt;br /&gt;    cmd LC_UUID&lt;br /&gt;cmdsize 24&lt;br /&gt;   uuid FD032EF9-2890-39ED-957A-A99CA51F120C&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;div&gt;Forgot to say: you can easily find all necessary binary images in /Developer/Platforms/iPhoneOS.platform/DeviceSupport/.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now when we have the image we can use it to convert numeric addresses to symbols. That's exactly what atos does. You do that this way:&lt;/div&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;atos -arch &amp;lt;arch&amp;gt; -o &amp;lt;binary-image&amp;gt; -l &amp;lt;image-load-address&amp;gt; &amp;lt;list-of-interesting-addresses&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;div&gt;The output is pretty straightforward and looks like this:&lt;/div&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;-[__NSOperationInternal start] (in Foundation) + 652&lt;br /&gt;-[NSOperation start] (in Foundation) + 16&lt;br /&gt;-[NSRunLoop(NSRunLoop) runUntilDate:] (in Foundation) + 56&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;div&gt;-l option allows us to use exactly the same address as in the crash log without any additional math. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;symbolicatecrash&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Originally symbolicatecrash is a script shipped with the SDK by Apple. But exactly as XCode it is too capricious. Thanks to &lt;a href="http://www.twitter.com/nskboy"&gt;@nskboy&lt;/a&gt;, there is a working fork of it. It needs only a dSYM file anywhere on disk (versus dSYM+app required by the original version) and also fixes few nasty bugs. You can get it from &lt;a href="https://github.com/nskboy/symbolicatecrash-fix"&gt;GitHub&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;The usage is very easy:&lt;/div&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;./symbolicatecrash -o symbolicated.crash &amp;lt;original-crash-log&amp;gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;div&gt;It works stably for me and I'm pretty sure it will for you. &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-6310767755738730224?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/mIKUtl-3-gY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/6310767755738730224/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2011/05/symbolicating-crash-logs.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/6310767755738730224?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/6310767755738730224?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/mIKUtl-3-gY/symbolicating-crash-logs.html" title="Symbolicating crash logs" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2011/05/symbolicating-crash-logs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YESHYyfCp7ImA9Wx5aF0k.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-4789577610056873845</id><published>2010-11-14T20:19:00.001+06:00</published><updated>2010-11-14T20:31:49.894+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-14T20:31:49.894+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cocoa" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Why ignoring compiler warnings is bad</title><content type="html">&lt;p&gt;Imagine that you're observing the following bug: for some reason your method gets its arguments with values different from what it was called with. Then you learn that it's not a debugger's fault, because adding a couple of NSLog's gives the same result. Then you learn that it's not a compiler's bug too, because changing it to clang/llvm gives nothing too. WTF?!, you think now.&lt;/p&gt;&lt;p&gt;The make the situation more real, here's the code which can help to feel that:&lt;/p&gt;&lt;pre&gt;// MyClass.h&lt;/pre&gt;&lt;pre&gt;﻿@interface MyClass : NSObject {&lt;/pre&gt;&lt;pre&gt;}&lt;/pre&gt;&lt;pre&gt;- (void)printFloat2:(float)x;&lt;/pre&gt;&lt;pre&gt;@end&lt;/pre&gt;&lt;pre&gt;// MyClass.m&lt;/pre&gt;&lt;pre&gt;﻿@implementation MyClass&lt;/pre&gt;&lt;pre&gt;- (void)printFloat:(float)x {&lt;/pre&gt;&lt;pre&gt;&lt;span style="white-space: pre;"&gt; &lt;/span&gt;NSLog(@"x = %f", x);&lt;/pre&gt;&lt;pre&gt;}&lt;/pre&gt;&lt;pre&gt;- (void)printFloat2:(float)x {&lt;/pre&gt;&lt;pre&gt;&lt;span style="white-space: pre;"&gt; &lt;/span&gt;NSLog(@"x = %f", x);&lt;/pre&gt;&lt;pre&gt;}&lt;/pre&gt;&lt;pre&gt;@end&lt;/pre&gt;&lt;pre&gt;// main.m&lt;/pre&gt;&lt;p&gt; &lt;/p&gt;&lt;pre&gt;﻿#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;/pre&gt;&lt;pre&gt;#import "MyClass.h"&lt;/pre&gt;&lt;pre&gt;int main(int argc, char *argv[]) {&lt;/pre&gt;&lt;pre&gt;&lt;span style="white-space: pre;"&gt; &lt;/span&gt;NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];&lt;span style="white-space: pre;"&gt; &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;MyClass * obj = [[MyClass alloc] init];&lt;/pre&gt;&lt;pre&gt;[obj printFloat:42.0];&lt;/pre&gt;&lt;pre&gt;[obj printFloat2:43.0];&lt;/pre&gt;&lt;pre&gt;[obj release];&lt;/pre&gt;&lt;pre&gt;[pool release];&lt;/pre&gt;&lt;pre&gt;return 0;&lt;/pre&gt;&lt;pre&gt;}&lt;/pre&gt;&lt;p&gt;What you think will it print out? Well, here's the answer:&lt;/p&gt;&lt;pre&gt;﻿x = 0.000000&lt;/pre&gt;&lt;pre&gt;x = 43.000000&lt;/pre&gt;&lt;p&gt;You see that the first line looks a bit wrong.&lt;/p&gt;&lt;p&gt;So, what's wrong? To tell the truth, I don't fully understand it and I would be glad if you could explain it. What is obviously not good it that we have a compiler warning at the appropriate line. -[MyClass printFloat:] isn't public so the compiler warns us that it can't find the method. Fixing that by declaring the method as public resolves the bug. Another good reason to fix all warnings in the code.&lt;/p&gt;&lt;p&gt;Here's what I discovered while trying to understand why does it behave so:&lt;/p&gt;&lt;p&gt;1. If we change argument type to double, everything works fine without declaring the method.&lt;/p&gt;&lt;p&gt;2. If we substitute obj with a proxy in order to dump NSInvocation, we see that methods have the same signature, but the argument is already different at the moment of forwardInvocation:.&lt;/p&gt;&lt;p&gt;It looks clear that the compiler somehow uses information from method declaration when storing the argument, but I don't understand why and how.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-4789577610056873845?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/Hdmv0GnNA8k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/4789577610056873845/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2010/11/why-ignoring-warnings-is-bad.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/4789577610056873845?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/4789577610056873845?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/Hdmv0GnNA8k/why-ignoring-warnings-is-bad.html" title="Why ignoring compiler warnings is bad" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2010/11/why-ignoring-warnings-is-bad.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIMQnY_fSp7ImA9Wx5aF04.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-6410885034483535599</id><published>2010-11-14T16:25:00.001+06:00</published><updated>2010-11-14T16:29:43.845+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-14T16:29:43.845+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="opinions" /><title>Obvious things</title><content type="html">&lt;p&gt;Yesterday I finally bought a copy of Rework (and have already read half of it till today) When I wrote about my buying on twitter, @yurabereza replied (it's my translation of his tweet): "I haven't read it yet, but I heard that it only consists of banalities :) I can advice some really good books". All I think about it doesn't fit into a short tweet, so I want to reply on his tweet here.&lt;/p&gt;&lt;p&gt;Let's put Rework aside because I'm not about it and let's talk about banalities. And clearnesses as well, since in this case they are the same. To my opinion, ignorance and lack of attention to banal and obvious things is an essential problem of many people. When they talk about these things they say that it's obvious and just move forward. But when it comes to the point, all these obvious things aren't done for some reason.&lt;/p&gt;&lt;p&gt;Here's sore example: meetings. Everybody knows that they're demotivating, that one needs to limit their time, that one have to have a clear plan in the beginning and discuss only concrete questions. However most of my last meetings were just horrible. But still, if I asked any of participants about those simple rules, he or she would say: "yes, sure, that's clear". It looks like just that "sure" lets their brain forget about the rules right in the begging of every meeting.&lt;/p&gt;&lt;p&gt;I don't see a reason to read "really good books" about I guess "non-banal things" until I can follow banal things for the beginning. (by the way, many of people around me don't follow even a half of ideas from Rework. I myself a year ago wasn't getting a half of them too. Fortunately, during last year in Yandex I learned a lot). I really believe that we should pay much MORE attention to things that seem obvious to us.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-6410885034483535599?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/1MwWGlEc_MA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/6410885034483535599/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2010/11/obvious-things.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/6410885034483535599?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/6410885034483535599?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/1MwWGlEc_MA/obvious-things.html" title="Obvious things" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2010/11/obvious-things.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAFQ3o4eSp7ImA9Wx5RF04.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-6979208487161397326</id><published>2010-08-25T18:39:00.002+07:00</published><updated>2010-08-25T18:45:12.431+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-25T18:45:12.431+07:00</app:edited><title>Discovering non-documented calls to your delegate object</title><content type="html">&lt;p&gt;It can happen that you provide a delegate object to some third-party code and want to know how that code uses your object. Here's a quick way to discover many new things about your delegate is used: just override respondsToSelector like this:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;- (BOOL)respondsToSelector:(SEL)aSelector {&lt;br /&gt; NSLog(@"Was tested for %@", NSStringFromSelector(aSelector));&lt;br /&gt; return [super respondsToSelector:aSelector];&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-6979208487161397326?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/ES8o-ksqxhM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/6979208487161397326/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2010/08/discovering-non-documented-calls-to.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/6979208487161397326?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/6979208487161397326?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/ES8o-ksqxhM/discovering-non-documented-calls-to.html" title="Discovering non-documented calls to your delegate object" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2010/08/discovering-non-documented-calls-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYNRn8zfyp7ImA9WxFXFk4.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-2001459177170143765</id><published>2010-05-23T18:52:00.006+07:00</published><updated>2010-05-24T00:36:37.187+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-24T00:36:37.187+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cocoa" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Maintaining application state between launches</title><content type="html">&lt;p&gt;Maintaining state between launches is an important job of any iPhone application. Unfortunately it's not trivial when your app has many views having dependencies among each other. And coming of iPhone OS 4.0 will not make your life easier since applications can be (and will be) terminated anyway. &lt;br /&gt;&lt;p&gt;So, when your application is relatively simple, saving its state is simple as well. You can do it this way:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;in the applicationWillTerminate: method you save your state into NSUserDefaults&lt;br /&gt;&lt;li&gt;in viewDidLoad: or applicationDidFinishLaunching: (whichever is more convenient for you) you read the state from user defaults and apply it (say, set current tab of a UITabBarController)&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;After your app gets bigger these methods start to grow and become very messed, especially if you have a navigation controller with potentially deep navigation stack. UIViewController implements NSKeyedArchiver, however after I experimented with it, I realized that it codes/encodes pretty weirdly and moreover anyway there's no way to restore dependencies between view controllers (if you, say, passed an object from Nth view controller to (N+1)th and expect to have the same instance in both controllers). &lt;br /&gt;&lt;p&gt;Thus I want to describe the approach to saving application state we used in Yandex.Maps application.&lt;br /&gt;&lt;p&gt;First, we don't use NSUserDefaults in order to separate state from application preferences. We store the state in a separate file. Then, we declared three protocols very similar to NSCoding:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;@protocol YMCoder&lt;br /&gt;&lt;br /&gt;- (void)encodeObject:(id&lt;NSCoding&gt;)object forKey:(NSString*)key;&lt;br /&gt;- (void)encodeController:(id&lt;YMPersistantController&gt;)vc forKey:(NSString*)key;&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;br /&gt;@protocol YMDecoder&lt;br /&gt;&lt;br /&gt;- (id)decodeObjectForKey:(NSString*)key;&lt;br /&gt;- (void)decodeController:(id&lt;YMPersistantController&gt;)vc forKey:(NSString*)key;&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;br /&gt;@protocol YMPersistantController&lt;br /&gt;&lt;br /&gt;- (void)decodeStateWithDecoder:(id&lt;YMDecoder&gt;)decoder;&lt;br /&gt;- (void)encodeStateWithCoder:(id&lt;YMCoder&gt;)coder;&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;  &lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Now each controller (not necessarily UIViewController) implements YMPersistantController like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; - (void)encodeStateWithCoder:(id&lt;YMCoder&gt;)coder {&lt;br /&gt; [coder encodeObject:[NSNumber numberWithBool:self.searchActive] forKey:@"searchActive"];&lt;br /&gt; [coder encodeController:self.searchController forKey:@"searchController"];&lt;br /&gt; }&lt;br /&gt; - (void)decodeStateWithDecoder:(id&lt;YMDecoder&gt;)decoder {&lt;br /&gt; self.searchActive = [[decoder decodeObjectForKey:@"searchActive"] boolValue];&lt;br /&gt; [decoder decodeController:self.searchController forKey:@"searchController"];&lt;br /&gt; if (self.searchActive) {&lt;br /&gt;  [self activateSearch];&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The controller doesn't care about when this methods are called (since they can be called a bit later after launch to visually decrease app launch time) or about naming conflicts (it can be guaranteed while coding/decoding). All it cares about is only its own state and dependent controllers. &lt;br /&gt;&lt;p&gt;Finally, we implemented a kind of NSKeyedArchiver, which takes a root controller, recursively encodes it from NSData or decodes an NSData given. Encoding/decoding is called from applicationWillTerminate:/applicationDidFinishLaunching: respectively. &lt;br /&gt;&lt;p&gt;This is it. Actually, I see nothing tricky or special in this approach, but it was the key to adding persistence to Maps application painlessly because existing code was already complex and hard to redesign.&lt;br /&gt;In the end I want to point at completely different solution I saw in three20 code. Shortly speaking, the idea is that your view controllers have URLs like webpages. You store the URL like /themap/search/resultdetails?query=coffee&amp;resultid=42 in user defaults and then restore from it. I find this approach pretty interesting, so you're thinking about persistence in your app take a look at three20's code, it may fit you better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-2001459177170143765?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/d8_FlilbdqM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/2001459177170143765/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2010/05/maintaining-application-state-between.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/2001459177170143765?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/2001459177170143765?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/d8_FlilbdqM/maintaining-application-state-between.html" title="Maintaining application state between launches" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2010/05/maintaining-application-state-between.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4NSHsyfCp7ImA9WxBSEEw.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-4685576150891539495</id><published>2009-12-07T03:26:00.013+06:00</published><updated>2009-12-17T06:49:59.594+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-17T06:49:59.594+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cocoa" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>ASIHTTPRequest vs NSURLConnection</title><content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;br /&gt;
&lt;br /&gt;Performing HTTP requests and fetching data via HTTP is a quite frequent task in iPhone applications. iPhone SDK provides three kinds of API to do that:
&lt;br /&gt;
&lt;br /&gt;1. BSD sockets. Say hello to unix and old good socket(), read(), ... Of course, you can use it to do HTTP, but I bet nobody does it this way on iPhone. 
&lt;br /&gt;
&lt;br /&gt;2. CFNetwork.  It's a Core Services framework for networking. According to ADC it's a &lt;blockquote&gt;low-level, high-performance framework that gives you the ability to have detailed control over the protocol stack.&lt;/blockquote&gt; And according to ADC again &lt;blockquote&gt;CFNetwork is based, both physically and theoretically, on BSD sockets.&lt;/blockquote&gt; 
&lt;br /&gt;Unfortunately, as every CF framework, it's a pure C framework so it's quite inconvenient to be used. Fortunately, there is a framework called as &lt;a href="http://allseeing-i.com/ASIHTTPRequest/"&gt;ASIHTTPRequest&lt;/a&gt;. It's very popular and frequently recommended on forums when somebody asks about how to download an URL. 
&lt;br /&gt;
&lt;br /&gt;ASIHTTPRequest is based on CFNetwork framework. It's important to say that ASI is synchronous by its nature. So if you want asynchronous URL fetching, you need to use NSOperationQueue (in last versions ASIHTTPRequest can do that itself so you just call [request startAsynchronously]). 
&lt;br /&gt;
&lt;br /&gt;3. NSURLConnection. A pretty Objective-C class which lets you do HTTP in just a couple of lines. According to ADC it's based on top of CFNetwork. In contrast to ASIHTTPRequest, NSURLConnection is asynchronous by design. But there is a method which lets you use it in a synchronous manner. 
&lt;br /&gt;
&lt;br /&gt;One of the biggest benefits of ASI over NS is that ASI provides a lot of useful functionality for building multipart POST requests, using compressed requests, authentication, proxies, .... 
&lt;br /&gt;
&lt;br /&gt;However the question bothering me all last week is: who is faster? Apparently, since NSURLConnection is based on top of CFNetwork, pure CFNetwork should be faster in all cases. But is ASIHTTPRequest faster than NSURLConnection?
&lt;br /&gt;
&lt;br /&gt;&lt;h2&gt;The battle&lt;/h2&gt;
&lt;br /&gt;
&lt;br /&gt;In order to find out who is faster, I've performed some tests. There was 2 tests for each mode (synchronous and asynchronous) for each framework:
&lt;br /&gt;&lt;ol&gt;
&lt;br /&gt;&lt;li&gt;Download 64 files, 4 kb each. (256 kb in total)
&lt;br /&gt;&lt;li&gt;Download one 256 kb file. 
&lt;br /&gt;&lt;/ol&gt;
&lt;br /&gt;All files was stored on Amazon S3. 
&lt;br /&gt;
&lt;br /&gt;So, in total there was 4 tests for each framework. Since results may differ from run to run (internet is a quite unstable thing), each test was run 10 times and then the best download time was picked as the result. 
&lt;br /&gt;
&lt;br /&gt;ASIHTTPRequest was as of 7th Dec 2009 (a3b974c67699c85bbe89277e016d277c590ccaab). 
&lt;br /&gt;
&lt;br /&gt;Tests was done in the Simulator and on my iPhone 2G, both laptop and iPhone was connected to the same wi-fi network.
&lt;br /&gt;
&lt;br /&gt;Here is the results (in seconds):
&lt;br /&gt;&lt;table style="width: 100%;"&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td colspan=2" style="text-align:center;"&gt;Simulator&lt;/td&gt;&lt;td colspan=2 style="text-align:center;" &gt;iPhone 2G&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td style="text-align:center;"&gt;ASI&lt;/td&gt;&lt;td style="text-align:center;" &gt;NS&lt;/td&gt;&lt;td style="text-align:center;" &gt;ASI&lt;/td&gt;&lt;td style="text-align:center;" &gt;NS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=5 style="text-align:left;" &gt;Asyncronous&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;64 files&lt;/td&gt;&lt;td style="text-align:center;" &gt;6.18&lt;/td&gt;&lt;td style="text-align:center;" &gt;2.69&lt;/td&gt;&lt;td style="text-align:center;" &gt;6.91&lt;/td&gt;&lt;td style="text-align:center;" &gt;3.81&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1 file&lt;/td&gt;&lt;td style="text-align:center;" &gt;0.64&lt;/td&gt;&lt;td style="text-align:center;" &gt;0.57&lt;/td&gt;&lt;td style="text-align:center;" &gt;6.33&lt;/td&gt;&lt;td style="text-align:center;" &gt;5.21&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=5 style="text-align:left;" &gt;Synchronous&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;64 files&lt;/td&gt;&lt;td style="text-align:center;" &gt;19.56&lt;/td&gt;&lt;td style="text-align:center;" &gt;9.92&lt;/td&gt;&lt;td style="text-align:center;" &gt;28.56&lt;/td&gt;&lt;td style="text-align:center;" &gt;13.30&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1 file&lt;/td&gt;&lt;td style="text-align:center;" &gt;0.65&lt;/td&gt;&lt;td style="text-align:center;" &gt;0.59&lt;/td&gt;&lt;td style="text-align:center;" &gt;6.02&lt;/td&gt;&lt;td style="text-align:center;" &gt;3.98&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;You can get the source code of the test project &lt;a href="http://github.com/fourdman/ASI-vs-NS/zipball/master"&gt;here&lt;/a&gt;. The repository contains detailed logs of the runs presented above. 
&lt;br /&gt;
&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;br /&gt;
&lt;br /&gt;So what do we see? In all tests ASIHTTPRequest is slower than NSURLConnection, approximately in 2 times. The difference is less when we download 1 big file, but is still sensible. 
&lt;br /&gt;
&lt;br /&gt;So in case you can make multipart POST requests yourself, choose NSURLConnection. :) (I'm kidding — of course, ASI provides a lot of other nice functionality, therefore if you don't care about performance much, ASI is a good choice)
&lt;br /&gt;
&lt;br /&gt;Another interesting fact we can notice is that synchronous mode is quite expensive when we perform many requests.  
&lt;br /&gt;
&lt;br /&gt;And finally some obvious to everybody, but still important facts:
&lt;br /&gt;&lt;ul&gt;
&lt;br /&gt;&lt;li&gt;Simulator is always faster then real iPhone. On fetching big files, up to 10 times. Moreover, you can notice that Simulator behave completely differently at all. So ALWAYS test your application performance on a real device.
&lt;br /&gt;&lt;li&gt;Fetching lots of files is always slower that fetching 1 single file. (NSURLConnection somehow managed to download 64 files faster than 1 file in asynchronous mode on iPhone. But if we check the logs, we see that in most cases downloading 64 files is still slower) 
&lt;br /&gt;&lt;/ul&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-4685576150891539495?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/p8kEcHUsyQI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/4685576150891539495/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/12/asihttprequest-vs-nsurlconnection.html#comment-form" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/4685576150891539495?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/4685576150891539495?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/p8kEcHUsyQI/asihttprequest-vs-nsurlconnection.html" title="ASIHTTPRequest vs NSURLConnection" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>8</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/12/asihttprequest-vs-nsurlconnection.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MDR3ozfCp7ImA9WxBSEE0.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-8363030174324730848</id><published>2009-12-07T02:45:00.003+06:00</published><updated>2009-12-17T05:17:56.484+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-17T05:17:56.484+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="howto" /><category scheme="http://www.blogger.com/atom/ns#" term="cocoa" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Easiest iPhone unit-testing ever using Google Toolbox for Mac</title><content type="html">One of the reasons why I wasn't actually writing iPhone/Mac unit tests for a long time is that setting them up using SenTestingKit is a bit... tricky. Even when you know how to do it, it takes rather a lot of time. &lt;br /&gt;&lt;br /&gt;Fortunately, there is &lt;a href="http://code.google.com/p/google-toolbox-for-mac/"&gt;Google Toolbox for Mac&lt;/a&gt;. It's a collection of different source code which Google uses in its own Mac/iPhone projects. And this toolbox has some nice stuff for unit-testing as well. &lt;br /&gt;&lt;br /&gt;Here is a little cheat sheet which I use then I need to set up unit tests in my project:&lt;br /&gt;&lt;br /&gt;1. Create "Tests" group in your project.&lt;br /&gt;2. Of course, you don't need the whole toolbox. Therefore I have a minimalistic set of required source files. You can download it &lt;a href="http://github.com/fourdman/MiniGTM/zipball/master"&gt;here&lt;/a&gt;. Then copy folder called as "UnitTesting" to &lt;code&gt;(project)/Tests&lt;/code&gt;.&lt;br /&gt;3. Create a new build target and say call it "Unit Tests". The target should have "Application" type.&lt;br /&gt;4. Open the newly created target and add Run Script phase to the end&lt;br /&gt;5. Set script contents to &lt;br /&gt;&lt;code&gt;&lt;br /&gt;"$SOURCE_ROOT/Classes/UnitTesting/RunIPhoneUnitTest.sh"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;6. Ensure using finder, that the mentioned file above is actually present (&lt;code&gt;$SOURCE_ROOT&lt;/code&gt; is your project's folder) and has executable bit set. Adjust this path in case of any different layout.&lt;br /&gt;7. Add all &lt;code&gt;.m&lt;/code&gt;  source files from UnitTesting group to the target&lt;br /&gt;8. Add all necessary code for your tests&lt;br /&gt;9. Removed all source files from Tests group from you main target (since XCode automatically added them there)&lt;br /&gt;&lt;br /&gt;That's it. Now you can write tests as follows:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;MySuperTest.m:&lt;br /&gt;&lt;br /&gt;#import "GTMSenTestCase.h"&lt;br /&gt;&lt;br /&gt;@interface MySuperTest : GTMTestCase { &lt;br /&gt;}&lt;br /&gt;@end&lt;br /&gt;&lt;br /&gt;@implementation MySuperTest&lt;br /&gt;&lt;br /&gt;- (void)setUp&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void)tearDown&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void)test1 &lt;br /&gt;{&lt;br /&gt; STAssertNotNil(obj, @"");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Since GTM uses SenTestingKit you can use the same assertion macroses as with SenTest. Also please note, that you can have just an &lt;code&gt;.m&lt;/code&gt; file. (it isn't related to GTM/SenTest, just a convenient practice since you rarely #import test files) &lt;br /&gt;&lt;br /&gt;One of the biggest benefits of using GTM is that you have tests as application-type target. That means that you can debug tests just by running the appropriate target with enabled breakpoints. And of course, you can debug tests not only in the simulator, but on a real iPhone as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-8363030174324730848?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/hm0thk7d5Os" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/8363030174324730848/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/12/easiest-iphone-unit-testing-ever-using.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/8363030174324730848?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/8363030174324730848?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/hm0thk7d5Os/easiest-iphone-unit-testing-ever-using.html" title="Easiest iPhone unit-testing ever using Google Toolbox for Mac" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/12/easiest-iphone-unit-testing-ever-using.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE4AQn84cSp7ImA9WxJbFk8.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-5029325813203928014</id><published>2009-07-26T22:18:00.008+07:00</published><updated>2009-07-26T22:42:23.139+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-26T22:42:23.139+07:00</app:edited><title>Видео-блоггинг (for russian-speaking readers)</title><content type="html">Я бы хотел поэкспериментировать с новым жанром: видео-блоги. В основном из-за интереса к тому, что вообще выйдет.&lt;br /&gt;&lt;br /&gt;К счастью, есть области (в основном это программирование), в которых у меня есть шанс рассказать что-то новое зрителю. Но, к сожалению, самому мне довольно сложно выбрать с чего начать. Потому что все темы выглядят одинаково очевидными и всем и так известными.&lt;br /&gt;&lt;br /&gt;Поэтому я бы хотел попросить помощи у вас, уважаемые читатели. Если вам было бы интересно увидеть мини-лекцию на какую-либо тему в моем исполнении — дайте знать. Об областях моей экспертизы вы можете узнать из &lt;a href="http://www.mikhailkalugin.com/#resume"&gt;резюме&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Рассказывать я планирую на русском (на английском и так полно всего). Именно поэтому и эта запись вдруг на русском.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-5029325813203928014?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/XXfVCbR8MgA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/5029325813203928014/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/07/for-russian-speaking-readers.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/5029325813203928014?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/5029325813203928014?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/XXfVCbR8MgA/for-russian-speaking-readers.html" title="Видео-блоггинг (for russian-speaking readers)" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/07/for-russian-speaking-readers.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYCQH4yeSp7ImA9WxJWGE8.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-560920281434042378</id><published>2009-06-23T15:35:00.003+07:00</published><updated>2009-06-24T12:09:21.091+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-24T12:09:21.091+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="howto" /><category scheme="http://www.blogger.com/atom/ns#" term="cocoa" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Cocolua: Lua + Objective-C</title><content type="html">&lt;p&gt;I do not love Objective-C. It makes me feel like I'm in the beginning of 90's. Lots of stupid syntax, square brackets everywhere, separate interfaces/implementations,... Okay, I feel you got me. &lt;br /&gt;&lt;p&gt;There are two "official" solutions for people like me: RubyCocoa and PythonCocoa. Hovewer there is a third solution which people rarely think about: Lua (and other embeddable languages). &lt;br /&gt;&lt;p&gt;This solution slightly differs from RubyCocoa/PythonCocoa. Lua is a very lightweight (but powerful) language which depends on C only. You don't need to pull many N-megabyte frameworks and libraries. Lua was created as an embeddable language: you add its interpreter's source code to your project and use is programmatically. Apart of many other things that means that you can use Lua even on the iPhone and no one will ever notice that. &lt;br /&gt;&lt;p&gt;Thanks to &lt;a href="http://luaforge.net/projects/luaobjc/"&gt;Tom McClean, Eric Wing and others&lt;/a&gt;, integrating Lua into your project is terrifically easy. Here is a little tutorial (you can download an exemplary project from &lt;a href="http://github.com/fourdman/cocolua/tree/master"&gt;http://github.com/fourdman/cocolua/tree/master&lt;/a&gt;):&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Download lua's source code from lua.org: &lt;a href="http://www.lua.org/ftp/lua-5.1.4.tar.gz"&gt;http://www.lua.org/ftp/lua-5.1.4.tar.gz&lt;/a&gt;&lt;br /&gt;&lt;li&gt;Download LuaCocoa from &lt;a href="http://www.assembla.com/spaces/LuaCocoa/trac_mercurial_tool"&gt;http://www.assembla.com/spaces/LuaCocoa/trac_mercurial_tool&lt;/a&gt; (you'll need mercurial):&lt;br /&gt;&lt;code&gt;hg clone http://hg.assembla.com/LuaCocoa&lt;/code&gt;&lt;br /&gt;&lt;li&gt;Add/copy LuaObjCBridge.{h,m} to your project&lt;br /&gt;&lt;li&gt;Add/copy all Lua interpreter's *.{h,c} from src/ without lua.c and luac.c&lt;br /&gt;&lt;li&gt;Compile and ensure that there are no errors. &lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;How to use it?&lt;/b&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;Launching a script&lt;/em&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;br /&gt; // create an interpreter&lt;br /&gt; lua_State* interpreter = lua_objc_init(); &lt;br /&gt;       &lt;br /&gt; // do stuff: prepare globals, etc&lt;br /&gt;&lt;br /&gt; // run a script&lt;br /&gt;    luaL_dofile(interpreter, scriptPath);&lt;br /&gt;       &lt;br /&gt;    // get the error status&lt;br /&gt;    char *luaError = (char *)lua_tostring(interpreter, -1);&lt;br /&gt;&lt;br /&gt; // do stuff again: read globals, etc&lt;br /&gt;&lt;br /&gt; // kill the interpreter&lt;br /&gt; lua_close(interpreter);&lt;br /&gt;&lt;/blockquote&gt;&lt;/code&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;Reading/writing global variables&lt;/em&gt;&lt;br /&gt;&lt;p&gt;There are two options here: property-list compatible values and just id instances. &lt;br /&gt;In case you want to transfer property-list compatible values across the bridge you do as follows:&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;br /&gt;lua_objc_pushpropertylist(interpreter, value);&lt;br /&gt;lua_setglobal(interpreter, "globalVar");&lt;br /&gt;&lt;/blockquote&gt;&lt;/code&gt;&lt;br /&gt;&lt;p&gt;Shortly saying you put the value on top of Lua interpreter's stack and then assign that value to a global variable. Property-list compatible values (NSNumber, NSString, NSData, NSArray, NSDictionary) are special in that way that they're automatically transformed into appropriate Lua's native types: number, string, string, table, table. &lt;br /&gt;&lt;p&gt;In case you have an arbitrary object, you do as follows:&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;br /&gt;lua_objc_pushid(interpreter, object); &lt;br /&gt;lua_setglobal(interpreter, "globalVar");&lt;br /&gt;&lt;/blockquote&gt;&lt;/code&gt;&lt;br /&gt;&lt;p&gt;In this case on Lua's side you get a table corresponding to the transfered object. And, for instance, you can do:&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;br /&gt;globalVar:describe()&lt;br /&gt;&lt;/blockquote&gt;&lt;/code&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;Calling Cocoa code from Lua&lt;/em&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;br /&gt;theClass = objc.class("NSObject");&lt;br /&gt;theInstance = theClass:alloc():init();&lt;br /&gt;&lt;/blockquote&gt;&lt;/code&gt;&lt;br /&gt;&lt;p&gt;For more info please read LuaCocoa's code or Lua's documentation on its C API.&lt;br /&gt;&lt;p&gt;Actually, there is another even more easier way to operate with Lua's interpreter: &lt;a href="http://www.assembla.com/wiki/show/LuaCore"&gt;LuaCore&lt;/a&gt;. This framework provides an even more cool interface:&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;br /&gt;LCLua *lua = [LCLua readyLua];&lt;br /&gt;[lua pushAsLuaString:@"this is the value of s" withName:@"s"];&lt;br /&gt;[lua pushDictionaryAsTable:[NSDictionary dictionary] withName:@"d"];&lt;br /&gt;[lua pushGlobalObject:self withName:@"myObject"];&lt;br /&gt;[lua runBuffer:@"print(s)"];&lt;br /&gt;[lua runBuffer:@"print(myObject:description())"];&lt;br /&gt;&lt;/blockquote&gt;&lt;/code&gt;&lt;br /&gt;&lt;p&gt;Finally, here are some useful links on Lua and embedding it:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;&lt;a href="http://www.lua.org/"&gt;Lua's home page&lt;/a&gt;&lt;br /&gt; &lt;li&gt;&lt;a href="http://metalua.luaforge.net/"&gt;Metalua: Lua with metaprogramming&lt;/a&gt; (for pervs)&lt;br /&gt; &lt;li&gt;&lt;a href="http://luaforge.net/projects/luaobjc/"&gt;Original LuaObjCBridge project&lt;/a&gt;&lt;br /&gt; &lt;li&gt;&lt;a href="http://luaforge.net/docman/view.php/253/1455/lua_example1.dmg"&gt;A simple example of how to use LuaObjCBridge&lt;/a&gt;, pretty old and without downloadable code. But you can download &lt;a href="http://github.com/fourdman/cocolua/tree/master"&gt;my implementation&lt;/a&gt;.&lt;br /&gt; &lt;li&gt;&lt;a href="http://www.assembla.com/spaces/LuaCocoa"&gt;ewing's branch of LuaObjCBridge&lt;/a&gt;, adds support for Objective-C 2.0 and contains important bug fixes&lt;br /&gt; &lt;li&gt;&lt;a href="http://gusmueller.com/lua/"&gt;Original LuaCore project&lt;/a&gt;&lt;br /&gt; &lt;li&gt;&lt;a href="http://www.assembla.com/wiki/show/LuaCore"&gt;ewing's branch of LuaCore&lt;/a&gt; &lt;br /&gt; &lt;li&gt;Tutorial: &lt;a href="http://heavycoder.com/tutorials/lua_embed.php"&gt;"Embedding Lua in C: Using Lua from inside C."&lt;/a&gt;&lt;br /&gt; &lt;li&gt;Tutorial: &lt;a href="http://drj11.wordpress.com/2008/04/03/embedding-lua-in-5-minutes/"&gt;"Embedding Lua in 5 Minutes"&lt;/a&gt; by code monk&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-560920281434042378?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/VSYnX9-22ZU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/560920281434042378/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/06/cocolua-lua-objective-c.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/560920281434042378?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/560920281434042378?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/VSYnX9-22ZU/cocolua-lua-objective-c.html" title="Cocolua: Lua + Objective-C" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/06/cocolua-lua-objective-c.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkADQXw_cSp7ImA9WxVVGUs.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-3663270633175442297</id><published>2009-03-13T22:04:00.003+06:00</published><updated>2009-03-13T22:12:50.249+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-13T22:12:50.249+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="crashkit" /><title>CrashKit</title><content type="html">Today I have good news: &lt;a href="http://www.yoursway.com/"&gt;we&lt;/a&gt; are launching a limited beta of &lt;a href="http://crashkitapp.appspot.com/"&gt;CrashKit&lt;/a&gt;, our multi-language online crash reporting tool.&lt;br /&gt;&lt;p style="text-align: center;"&gt;&lt;img class="screenshot" src="http://crashkitapp.appspot.com/static/images/marketing/bugs.png" width="387" height="220" /&gt;&lt;/p&gt;&lt;br /&gt;We've started building it a few weeks ago for our consulting project (written in Java). And CrashKit has already saved our asses a couple of times since then. You feel like a real guardian angel watching over your product and being able to react before your users get what's happened. &lt;br /&gt;&lt;br /&gt;CrashKit already has all lively important features but also there are many terrific features on our roadmap: collection of usage statistics, two-way customer interaction, much better bug tracker integration, more notification options, branding and internationalization. And, of course, more supported languages and frameworks. If you are missing any particular feature or have anything else to say, please drop us a line.&lt;br /&gt;&lt;br /&gt;CrashKit is free to use during the beta period, and will always be free for open-source and small personal projects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-3663270633175442297?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/L-AOf8KPMfw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/3663270633175442297/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/03/crashkit.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/3663270633175442297?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/3663270633175442297?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/L-AOf8KPMfw/crashkit.html" title="CrashKit" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/03/crashkit.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUADRHszeCp7ImA9WxVQFkg.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-4710921648360746447</id><published>2009-02-01T18:28:00.004+06:00</published><updated>2009-02-03T15:36:15.580+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-03T15:36:15.580+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="nscodernsk" /><title>NSCoder Night (Novosibirsk)</title><content type="html">&lt;p&gt;Есть такое событие, проводящееся во многих городах америки и европы – NSCoder Night (&lt;a href="http://nscodernight.com/"&gt;nscodernight.com&lt;/a&gt;). Суть мероприятия состоит в том, что раз в неделю вечером Cocoa-девелоперы собираются в кофейне и кодят. Кодят что хотят и как хотят. Что-то вроде мини-хакатона. &lt;br /&gt;&lt;p&gt;Я решил организовать такое же мероприятие в Новосибирске. Каждый вторник с примерно 19 до 23х я (и возможно еще пара сотрудников &lt;a href="http://www.yoursway.com/"&gt;YourSway&lt;/a&gt;) буду сидеть в кофейне на ВЦ со своим черным макбуком и что-нибудь хачить. &lt;br /&gt;&lt;p&gt;Если вы программист под Cocoa или только собираетесь научиться — хватайте свой ноут и присоединяйтесь. &lt;br /&gt;&lt;p&gt;Первая встреча в этот вторник, 3ого февраля. О предстоящих встречах, а также обо всех новостях будет сообщаться на &lt;a href="http://nscodernight-nsk.blogspot.com/"&gt;http://nscodernight-nsk.blogspot.com/&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-4710921648360746447?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/hcFfsLTUPfY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/4710921648360746447/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/02/nscoder-night-novosibirsk.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/4710921648360746447?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/4710921648360746447?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/hcFfsLTUPfY/nscoder-night-novosibirsk.html" title="NSCoder Night (Novosibirsk)" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/02/nscoder-night-novosibirsk.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQGR3ozfyp7ImA9WxVQGEk.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-6374221781408389415</id><published>2009-02-01T02:28:00.005+06:00</published><updated>2009-02-05T21:05:26.487+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-05T21:05:26.487+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cocoa" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Cocoa Garbage Collection and GData</title><content type="html">&lt;p&gt;Several days ago I lost almost all night debugging a nasty bug with &lt;a href="http://code.google.com/p/gdata-objectivec-client/"&gt;GData client for Objective-C&lt;/a&gt;. The bug was so stupid that I was about to hit my head against a wall when learned what's wrong.&lt;br /&gt;&lt;p&gt;But let's start from the beginning. Generally, my goal was to fetch Google Calendar calendars, find the specified one and add an entry. It could(!) be done with Google's API the following rather simple way:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;- (GDataServiceGoogleCalendar *)calendarService {&lt;br /&gt; static GDataServiceGoogleCalendar* service = nil;&lt;br /&gt; if (!service) {&lt;br /&gt;  service = [[GDataServiceGoogleCalendar alloc] init];&lt;br /&gt;  [service setUserAgent:@"My-App-1.0"];&lt;br /&gt;  [service setShouldCacheDatedData:YES];&lt;br /&gt;  [service setServiceShouldFollowNextLinks:YES];&lt;br /&gt; }&lt;br /&gt; [service setUserCredentialsWithUsername:username&lt;br /&gt;           password:password]; &lt;br /&gt; return service;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void)fetchCalendars {&lt;br /&gt;&lt;br /&gt; GDataServiceGoogleCalendar* service = [self calendarService];&lt;br /&gt; [service fetchCalendarFeedWithURL:[NSURL URLWithString: kGDataGoogleCalendarDefaultOwnCalendarsFeed]&lt;br /&gt;        delegate:self&lt;br /&gt;     didFinishSelector:@selector(calendarListFetchTicket:finishedWithFeed:)&lt;br /&gt;       didFailSelector:@selector(calendarListFetchTicket:failedWithError:)];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void)calendarListFetchTicket:(GDataServiceTicket *)ticket&lt;br /&gt;               finishedWithFeed:(GDataFeedCalendar *)feed {&lt;br /&gt;  // Wow, it works!&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;- (void)calendarListFetchTicket:(GDataServiceTicket *)ticket&lt;br /&gt;                failedWithError:(NSError *)error {&lt;br /&gt; // Oops... &lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;p&gt;Simply saying you get GDataServiceGoogleCalendar object and ask it to fetch calendars passing it an object and a pair of selectors. The service asynchronously fetches calendars in background and calls an appropriate selector when done. The code above is almost the same code as in the Google's example application. &lt;br /&gt;&lt;p&gt;But... it rejected to work in my project. For some unknown to me reason callbacks was never called. When I tried to add breakpoints inside the framework, even NSURLConnection callbacks was not called.  &lt;br /&gt;&lt;p&gt;After some tries to figure out a difference between my app and the exemplary, I found that my application uses Garbage Collection and the exemplary not. I immediately supposed that GData framework doesn't support GC. However after I enabled GC for the example it continued to work perfectly. &lt;br /&gt;&lt;p&gt;I had read some blogs and forums but still hadn't found anything interesting. And now I'll unveil an important detail missed in the code above. In fact, &lt;code&gt;fetchCalendarFeedWithURL:&lt;/code&gt; returns a ticket, GDataServiceTicket object. Ticket allows you to check in callbacks which fetch request was finished. Since at that moment I was experimenting and thinking that there will be only one ticket, I wasn't doing anything with &lt;code&gt;fetchCalendarFeedWithURL&lt;/code&gt;'s return value.&lt;br /&gt;&lt;p&gt;"OK", — I said and wrote it the following way:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;GDataServiceTicket * ticket = [service fetchCalendarFeedWithURL:[NSURL URLWithString: kGDataGoogleCalendarDefaultOwnCalendarsFeed]&lt;br /&gt;       delegate:self&lt;br /&gt;    didFinishSelector:@selector(calendarListFetchTicket:finishedWithFeed:)&lt;br /&gt;      didFailSelector:@selector(calendarListFetchTicket:failedWithError:)];&lt;br /&gt;[ticket retain];&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;p&gt;Apparently I decided that ticket was being disposed by garbage collector and Google's framework was dying because of that. Actually, I was absolutely right. But I wrote a completely stupid fix. Because if you read documentation on Cocoa's GC you know that I had changed nothing. Because retain/release call don't do anything if garbage collecting is enabled. I don't know why (maybe because it was 3 am) I supposed that it'll help. &lt;br /&gt;So, finally, the correct solution is to do &lt;code&gt;fTicket = [ticket retain]&lt;/code&gt; (if you want to support classical memory management) or &lt;code&gt;fTicket = ticket&lt;/code&gt; (if you target on Leopard only), where &lt;code&gt;fTicket&lt;/code&gt; is an instance variable, for example. This way garbage collector won't release ticket object. &lt;br /&gt;&lt;p&gt;Finally, I should note that exemplary app was doing everything right. But for some reason I hadn't noted that. So if you're using Cocoa with GC don't lazy to read &lt;a href="http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/Introduction.html"&gt;Apple's guide on it&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-6374221781408389415?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/beESbVdTOJI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/6374221781408389415/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/02/several-days-ago-i-lost-almost-all.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/6374221781408389415?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/6374221781408389415?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/beESbVdTOJI/several-days-ago-i-lost-almost-all.html" title="Cocoa Garbage Collection and GData" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/02/several-days-ago-i-lost-almost-all.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YFSHkzeCp7ImA9WxVRFkw.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-3702881473917090407</id><published>2009-01-22T02:15:00.006+06:00</published><updated>2009-01-22T16:11:59.780+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-22T16:11:59.780+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cocoa" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Flexible Pop-Up Menus on Cocoa</title><content type="html">&lt;div&gt;Today I've got tired from strange bugs in my old implementation of pop-up menus and spend a couple of hours to write it from scratch. So, meet MKPopUp:&lt;/div&gt;&lt;br /&gt;&lt;div&gt;MKPopUp is a very small library for creating custom pop-up views (pie menus, whatever else) on Cocoa. It has interface quite similar to NSMenu's one. If you want to show a pop-up based on your NSView view (which you may just draw with Interface Builder), you write something like:&lt;/div&gt;&lt;code&gt;&lt;br /&gt; MKPopUp * popUp = [[MKPopUp alloc] initWithView:popUpView];&lt;br /&gt; [popUp setDelegate:self];&lt;br /&gt; [popUp appearWithEvent:event forView:self withDelay:0];&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;div&gt;If you need to position your pop-up differently from default, you implement this delegate method:&lt;/div&gt;&lt;code&gt;&lt;br /&gt;       // (this method should return screen coordinates of the bottom left corner of pop-up window)&lt;br /&gt; - (NSPoint)positionPopUp:(MKPopUp*)popUp withEvent:(NSEvent*)event {&lt;br /&gt;  NSPoint pos = [event locationInWindow];&lt;br /&gt;  pos = [[self window] convertBaseToScreen:pos];&lt;br /&gt;  return NSMakePoint(pos.x + 10, pos.y + 10); &lt;br /&gt; }&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;div&gt;You can check whether the pop-up is shown by calling &lt;code&gt;[popUp isVisible]&lt;/code&gt;. When you need to close it, you call &lt;code&gt;[popUp close];&lt;/code&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;MKPopUp supports hierarchical pop-ups as well (just set parentPopUp property in parent when opening a child pop-up).&lt;/div&gt;&lt;br /&gt;&lt;div&gt;You can download the source code and some examples from &lt;a href="http://github.com/fourdman/mkpopup"&gt;http://github.com/fourdman/mkpopup&lt;/a&gt;. However I can definitely that this implementation is not free from bugs too, so don't blame me and use it on your own risk.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;b&gt;Upd.:&lt;/b&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/ErP3C13oA4c&amp;hl=en&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/ErP3C13oA4c&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-3702881473917090407?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/pUYNya_NWWg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/3702881473917090407/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/01/flexible-pop-up-menus-on-cocoa.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/3702881473917090407?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/3702881473917090407?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/pUYNya_NWWg/flexible-pop-up-menus-on-cocoa.html" title="Flexible Pop-Up Menus on Cocoa" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/01/flexible-pop-up-menus-on-cocoa.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMGRXsyfCp7ImA9WxVREko.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-7197872691228100931</id><published>2009-01-14T18:38:00.007+06:00</published><updated>2009-01-18T16:27:04.594+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-18T16:27:04.594+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="opinions" /><category scheme="http://www.blogger.com/atom/ns#" term="stuff" /><title>Simple Accounting</title><content type="html">&lt;div&gt;Today, I've decided to take responsibility on YourSway finances. Earlier I was using plain text files to track my accounts and transfers, but handling &gt;10 accounts (different personal accounts of all developers, corporate account, customers), using plain text files is a true suicide. &lt;/div&gt;&lt;br /&gt;&lt;div&gt;My main requirement: simplest operations on accounts and transfers from one account to another. Also I want to annotate transfers with tags and perform simple queries like "how much money I gave to Andrey this month". Also I want to store somewhere our debts (maybe as a tagged transfers). But I don't need to plan budget — I just need to see the whole story and current state. So mostly it'll be a personal tool than "small business". Ah, the last important requirement — perfect UI.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Today I've tried the following tools:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt; Moneydance, &lt;a href="http://moneydance.com/"&gt;http://moneydance.com/&lt;/a&gt; — looked promising at first glance, but UI incredibly sucks — I failed just to add a simple transaction. Rejected.&lt;br /&gt;&lt;li&gt; Xero, &lt;a href="https://www.xero.com/ "&gt;https://www.xero.com/ &lt;/a&gt;— online accounting tool. They entertained me with their way to check if I'm a human — I had to win tic-tac-toe game instead of standard captcha. Supports accounts management, invoices, reports, graphs. Functionally looks full. UI is acceptable, but not beautiful. In addition, tracking simple money transactions from one account to another still feels too complex. Rejected.&lt;br /&gt;&lt;li&gt; Quicken Online, &lt;a href="http://www.quickenonline.com"&gt;http://www.quickenonline.com&lt;/a&gt; — another online app. For some reason they asked me about my bank. As far as I understood they link your operations to real bank accounts. I must googled wrong words. Rejected.&lt;br /&gt;&lt;li&gt; Mint, &lt;a href="https://wwws.mint.com/"&gt;https://wwws.mint.com/&lt;/a&gt; — looks sexy and interesting. But I failed to add any account because they link operations to real bank accounts too. A wrong pick again.&lt;br /&gt;&lt;li&gt; Expensr, &lt;a href="https://www.expensr.com/ "&gt;https://www.expensr.com/ &lt;/a&gt;— yet another online app. Allows simple accounts, transactions between them, has a nice table showing transactions, simple statistics. Generally it's the first app that doesn't suck, but 1) it doesn't support accounts in different currencies (maybe I just haven't found that) 2) there are a lots of small but nasty details in UI. Rejected.&lt;br /&gt;&lt;li&gt; moneytrackin, &lt;a href="http://www.moneytrackin.com/"&gt;http://www.moneytrackin.com/&lt;/a&gt; — another good online app. It supports almost all features I need too (accounts, transfers, tags). And I would choose this one... but 1) it doesn't show all accounts balance on a single screen 1') it doesn't show list of _all_ transactions on a single screen 2) it shows too much of ad. Rejected.&lt;br /&gt;&lt;li&gt; Squirrel, &lt;a href="http://www.squirrelapp.com/"&gt;http://www.squirrelapp.com/&lt;/a&gt; — desktop app. Cool (maybe even TOO cool, too much animations) UI, but not very functional. I can't pick different currencies for different accounts. Transfers can't be annotated. But this app won Apple Student Product Design Award 2008. To tell the truth it really looks like a student's project. Rejected.&lt;br /&gt;&lt;li&gt; Money, &lt;a href="http://www.jumsoft.com/money/"&gt;http://www.jumsoft.com/money/&lt;/a&gt; — desktop app. Actually, the best app I found. It can everything I need. Except the one critical bug: when I transfer money from an account in euro in an account in rubles, it decreases the same number from both account WITHOUT any conversion. Since all my accounts are in different currencies, I can't use it. Rejected.&lt;br /&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;It's surprising, but I haven't found anything which was better than old good Excel. I'll definitely try to describe my expectations later and explain in details what I want to see. Perhaps you can advise smt to me. But right now I can say that I don't know any usable tool for small business accounting.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-7197872691228100931?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/nCbAyere7sM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/7197872691228100931/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/01/simple-accounting.html#comment-form" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/7197872691228100931?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/7197872691228100931?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/nCbAyere7sM/simple-accounting.html" title="Simple Accounting" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>7</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/01/simple-accounting.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUHSHg8fCp7ImA9WxVSFUQ.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-592175681109437801</id><published>2009-01-10T15:17:00.002+06:00</published><updated>2009-01-10T20:03:59.674+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-10T20:03:59.674+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="howto" /><category scheme="http://www.blogger.com/atom/ns#" term="cocoa" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Unit Testing Objective-C Applications and Frameworks</title><content type="html">Was trying to debug unit tests for my Cocoa application and found an excellent series of posts about using and debugging unit tests for Objective-C: &lt;a href="http://chanson.livejournal.com/119097.html"&gt;Xcode: Unit Testing Series&lt;/a&gt;.&lt;br /&gt;&lt;s&gt;Too bad that Apple doesn't include all this information in ADC Library.&lt;/s&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-weight:bold;"&gt;Update:&lt;/span&gt; Have just found &lt;a href="http://developer.apple.com/mac/articles/tools/unittestingwithxcode3.html"&gt;http://developer.apple.com/mac/articles/tools/unittestingwithxcode3.html&lt;/a&gt; — decent documentation on OCUnit from Apple. For some reason I haven't seen it in my offline Library. Hm.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-592175681109437801?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/M7gY4TpgDeQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/592175681109437801/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/01/unit-testing-objective-c-applications.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/592175681109437801?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/592175681109437801?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/M7gY4TpgDeQ/unit-testing-objective-c-applications.html" title="Unit Testing Objective-C Applications and Frameworks" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/01/unit-testing-objective-c-applications.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIBQH07eSp7ImA9WxVSFUU.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-946270575330264540</id><published>2009-01-09T13:54:00.001+06:00</published><updated>2009-01-10T15:42:31.301+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-10T15:42:31.301+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="howto" /><title>Slow VMWare Start</title><content type="html">I use VMWare Fusion in my work frequently. Recently I noticed a frustrating problem: my virtual machine started to resume from suspended state for several minutes instead of just two seconds as it was earlier. What was frustrating me more is that this machine was starting fine on other computers. So I was thinking about some caches deep inside my VMWare (which I wasn't going to search for).&lt;div&gt;&lt;br /&gt;&lt;div&gt;Yesterday I found a simple explanation: my printer. Earlier my macbook was connected to a printer but some time ago it broke down and I deleted it from the OS's preferences. But VMWare was still thinking that I have that printer and was trying to attach to it. Unchecking "enable printing" in the vm's preferences resolved the problem.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-946270575330264540?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/BqRsgYeP49M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/946270575330264540/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/01/slow-vmware-start.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/946270575330264540?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/946270575330264540?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/BqRsgYeP49M/slow-vmware-start.html" title="Slow VMWare Start" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/01/slow-vmware-start.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMMRHg7cCp7ImA9WxVREko.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-7780316820277229213</id><published>2009-01-08T18:52:00.002+06:00</published><updated>2009-01-18T16:28:05.608+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-18T16:28:05.608+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="my life" /><title>Fresh Wish List</title><content type="html">&lt;div&gt;&lt;div&gt;In case somebody wants to make a gift to me (for some reason), here is an updated wish list:&lt;/div&gt;&lt;ul&gt;&lt;li&gt;good mouse (for games and coding the same time, wired, not mighty mouse!)&lt;/li&gt;&lt;li&gt;external 1 Tb hard drive (ideally wifi-capable)&lt;/li&gt;&lt;li&gt;T-shirt with some cool label ("because the ones who think they are crazy enough...", xkcd-stuff, whatever showing what a geek I am)&lt;/li&gt;&lt;li&gt;dumbbells set from 5 to 30 kg (as a replacement for gym visiting)&lt;/li&gt;&lt;li&gt;cooking book (with recipes _proven_ to work)&lt;/li&gt;&lt;li&gt;toaster (because my old toaster almost a year lives in our office)&lt;/li&gt;&lt;li&gt;kitchen machine (just a cool thing)&lt;/li&gt;&lt;li&gt;dishwashing machine (to wash the kitchen machine)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;s&gt;set of screwdrivers (for some reason I lost all my old screwdrivers :( )&lt;/s&gt;&lt;/li&gt;&lt;li&gt;blender (in case nobody will be generous enough for a kitchen machine)&lt;/li&gt;&lt;li&gt;waffle cooking machine (waffles, m-m-m!)&lt;/li&gt;&lt;li&gt;very small spade (for car, to dig out from snowdrifts)&lt;/li&gt;&lt;li&gt;&lt;s&gt;jeans (yes! just jeans!)&lt;/s&gt;&lt;/li&gt;&lt;li&gt;good teapot with spout that doesn't leak (ALL my previous teapots had such nasty bug)&lt;/li&gt;&lt;li&gt;automobile GPS (last time I tried to use Maps on iPhone I miraculously didn't fell from a bridge at 60 km/h)&lt;/li&gt;&lt;li&gt;couch (friends, it's primarily for you :)&lt;/li&gt;&lt;li&gt;CD/DVD standings (just a cool stuff)&lt;/li&gt;&lt;li&gt;glass form for baking cakes, lasagna, ... (I sleep and dream about it, really)&lt;/li&gt;&lt;li&gt;can opener (I really like my old one, but it seems that I'm only one such fan)&lt;/li&gt;&lt;li&gt;coffee machine or coffee pot (I can't drink instant coffee)&lt;/li&gt;&lt;li&gt;thermos (since I liked mountain skiing it's a must)&lt;/li&gt;&lt;li&gt;iLife and iWork '09 (because of full-screen Pages and iPhoto support of Faces and Flickr)&lt;/li&gt;&lt;li&gt;old Nissan Skyline | Toyota Celica GTFour '92 | MMC Lancer Evo X | Subaru Impreza WRX STi (no comments)&lt;/li&gt;&lt;li&gt;small plane &amp;amp; pilot's license (no comments)&lt;/li&gt;&lt;li&gt;New Zealand citizenship (no comments)&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-7780316820277229213?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/drPc6wJB4ww" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/7780316820277229213/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/01/fresh-wish-list.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/7780316820277229213?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/7780316820277229213?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/drPc6wJB4ww/fresh-wish-list.html" title="Fresh Wish List" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/01/fresh-wish-list.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEESHwzcSp7ImA9WxVSFUU.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-5218981449347751561</id><published>2009-01-07T18:41:00.001+06:00</published><updated>2009-01-10T15:43:29.289+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-10T15:43:29.289+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="my life" /><category scheme="http://www.blogger.com/atom/ns#" term="opinions" /><title>"it's OK this way"</title><content type="html">&lt;div&gt;&lt;div&gt;Once a long time ago in my first summer programming school I had noticed that I say "it's ok this way" too often. Every time we was encountering a bug or was going to add a small feature I was saying "it's ok this way already, we don't need it". I was doing that subconsciously and what's interesting, when I realized that I felt ashamed and disappointed by myself.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Actually I also noticed that apart my main occupation I do use this words in everyday life too, again totally subconsciously. Every time I see something wrong or annoying me (for inst., broken tap in the bathroom or impudent co-worker), I can unwittingly say "ok, to heck with this" instead of fixing the tap (what sometimes can take less than 5 min) or criticizing that guy. I'm sure that if you watch over yourself you'll find something like this too.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Eventually I started to be inclined to think that words like "it's ok this way" are one of most dangerous words ever. Because to my opinion it's a kind of laziness which _stops_ progress. Fortunately it's obvious to most of my friends, however I also know numerous guys (including me) who still behave such lazy way.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm going to provide two explanations of why I think these words are so bad. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The first thing why I think so is the expectations. Agreeing to something what seems to satisfy your expectations but contains a bunch of small flows you fetch the result which actually is below your expectations. That also means that you deprive yourself from "good" and "excellent" result. You conscientiously choose poor results in everything. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The second thing is the time. Since "ok"-level results don't satisfy you, subconsciously they're irritating you all the time. And they become more and more irritating every day. Every time you encounter them. Poor project design makes you writing crap-code every day; old bug is annoying you every time you want to demonstrate your product; a little misunderstanding with your girlfriend can cause a break eventually. And so on.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Summarizing, I can derive two simple rules:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;if something increasingly annoys you, there is no sense to stand and defer actions because eventually you'll all the same get rid of the annoying reason but till that time you'll lose much more than if you solved the problem in the very beginning&lt;br /&gt;&lt;/li&gt;&lt;li&gt;if you aim at excellent results, prepare to long and exhausting war with many small but important details (because they are exactly what make your result "excellent")&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-5218981449347751561?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/tWF5dJmaOZg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/5218981449347751561/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/01/its-ok-this-way.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/5218981449347751561?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/5218981449347751561?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/tWF5dJmaOZg/its-ok-this-way.html" title="&quot;it's OK this way&quot;" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/01/its-ok-this-way.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEHR38-cSp7ImA9WxVSFUU.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-651529274220915284</id><published>2009-01-07T18:18:00.002+06:00</published><updated>2009-01-10T15:43:56.159+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-10T15:43:56.159+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="howto" /><category scheme="http://www.blogger.com/atom/ns#" term="tech" /><title>How To Move Your Blog to Another Google Account</title><content type="html">&lt;div&gt;Some time ago (actually, almost half a year) I decided to consider mikhail.kalugin@gmail.com as my main e-mail address and to forget about fourdman@gmail.com. But unfortunately this my blog was created as fourdman so I had to login as fourdman to write posts. Today I've finally got tired from that and decided to somehow move the blog to my actual Google Account. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;I've not found any "standard" way of changing blog ownership, so I used a quite simple way to do that (say fourdman is "account A" and mikhail.kalugin is "account B"):&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Login from account A and add account B as author&lt;/li&gt;&lt;li&gt;Login from account B and accept the invitation&lt;/li&gt;&lt;li&gt;Login from account A and give B administrator access&lt;/li&gt;&lt;li&gt;Login from account B and remove A from authors&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;That's rather intuitive solution, but to tell the truth I was a bit surprised that it's possible to remove original blog creator from authors.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-651529274220915284?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/x3wRDV7FvTk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/651529274220915284/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2009/01/how-to-move-your-blog-to-another-google.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/651529274220915284?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/651529274220915284?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/x3wRDV7FvTk/how-to-move-your-blog-to-another-google.html" title="How To Move Your Blog to Another Google Account" /><author><name>Mikhail Kalugin</name><uri>http://www.blogger.com/profile/10107944881228582375</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_QHTgpQhUtbM/SWScMB_xCmI/AAAAAAAAAh4/aboxKmsr17g/S220/userpic.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2009/01/how-to-move-your-blog-to-another-google.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEBR3o9eip7ImA9WxVSFUU.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-5125922542236515480</id><published>2008-09-08T23:33:00.002+07:00</published><updated>2009-01-10T15:44:16.462+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-10T15:44:16.462+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="my life" /><category scheme="http://www.blogger.com/atom/ns#" term="opinions" /><title>Backup key</title><content type="html">As some of my friends already know I bought a car recently. Mitsubishi Lancer, 2004, 1.6l, manual transmission, left-hand wheel. I think it's a perfect car to be the first car (I got driver license less than a month ago). In my opinion it lacks a bit of dynamics, but that's a nitpicking. It's an awesome car.&lt;div&gt;&lt;br /&gt;However this post is about another thing: about user interfaces. With the car I got two alarm keys: main and a backup, in case the main is lost. Here is a photo of them:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_P2VtTJwX2TA/SMVUFA4F_gI/AAAAAAAACrI/J9fB_e0icrI/s1600-h/keys.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_P2VtTJwX2TA/SMVUFA4F_gI/AAAAAAAACrI/J9fB_e0icrI/s400/keys.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5243689786254163458" /&gt;&lt;/a&gt;&lt;br /&gt;The first, main, has a lot of functions: it shows temperature, which car element was "touched", call function, anti-robbery mode... I can't even recall all of them. And also it has only three buttons: #1, #2 and light. First two buttons are programmable. In addition they have additional functions for long presses: for example, when you press the first button for three seconds, you turn engine on. Actually, key's interface is even more complex, so I won't describe it in details here. I'll just say that I still don't understand how the open the trunk remotely. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;The second key as you can seen is much more simpler. It doesn't have a display. But to me it's much more better. I don't have to read huge user manual to understand, what each of buttons means. I don't have to scroll through the microscopic menu as with the "big brother". I just press a button and it works. Well, ok, such key has cons. I don't have any feedback from the car. I can't even ensure that my car is accessible now. This cons are serious and that's why I'll continue to use the first key. But I don't understand why manufacturers don't understand how over-engineered is the main key (as far as I know, most alarm systems have such mega-complex keys). &lt;/div&gt;&lt;div&gt;&lt;br /&gt;Finally I want to say that in my opinion such complexity is dangerous in extreme situations: what's the help of "panic" mode, if I won't be able to turn it on in panic?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-5125922542236515480?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/Pwx9F0ynPcY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/5125922542236515480/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2008/09/backup-keys.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/5125922542236515480?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/5125922542236515480?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/Pwx9F0ynPcY/backup-keys.html" title="Backup key" /><author><name>Mikhail Kalugin</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="21" src="http://bp1.blogger.com/_P2VtTJwX2TA/R4iutE4jpoI/AAAAAAAACEE/Aw7vk4haZBs/S220/x_d2fc89b6.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_P2VtTJwX2TA/SMVUFA4F_gI/AAAAAAAACrI/J9fB_e0icrI/s72-c/keys.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2008/09/backup-keys.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEDQ3Y6cCp7ImA9WxVSFUU.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-4085621396781021574</id><published>2008-08-31T14:59:00.001+07:00</published><updated>2009-01-10T15:44:32.818+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-10T15:44:32.818+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tech" /><category scheme="http://www.blogger.com/atom/ns#" term="stuff" /><title>Recursive screen sharing</title><content type="html">Mac OS X 10.5 has a nice feature called "Screen Sharing". I think it's obvious what this thing does.&lt;br /&gt;Being bored by everything a couple of days ago I connected to my friend's Mac and asked him to connect to me. To tell the truth, I thought that this action will be blocked by Mac. But nevertheless Andrey did successfully connected to me. And... slowly but faithfully the following started to appear on our screens (take a look on a menu, which travels through the time and space :).&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_P2VtTJwX2TA/SLpR3pLFxPI/AAAAAAAACrA/ziq1FDovE7k/s1600-h/screen+sharing.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_P2VtTJwX2TA/SLpR3pLFxPI/AAAAAAAACrA/ziq1FDovE7k/s400/screen+sharing.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5240591132786017522" /&gt;&lt;/a&gt;&lt;br /&gt;I have to say that after this our Macs became totally irresponsible so we was unable to kill screen sharing. Thus we had to find a third computer to run "kill -9".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-4085621396781021574?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/Ywe8C8B-myY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/4085621396781021574/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2008/08/recursive-screen-sharing.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/4085621396781021574?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/4085621396781021574?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/Ywe8C8B-myY/recursive-screen-sharing.html" title="Recursive screen sharing" /><author><name>Mikhail Kalugin</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="21" src="http://bp1.blogger.com/_P2VtTJwX2TA/R4iutE4jpoI/AAAAAAAACEE/Aw7vk4haZBs/S220/x_d2fc89b6.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_P2VtTJwX2TA/SLpR3pLFxPI/AAAAAAAACrA/ziq1FDovE7k/s72-c/screen+sharing.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2008/08/recursive-screen-sharing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEMRno_eyp7ImA9WxVSFUU.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-7693114638547481672</id><published>2008-05-15T04:49:00.001+07:00</published><updated>2009-01-10T15:44:47.443+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-10T15:44:47.443+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cocoa" /><category scheme="http://www.blogger.com/atom/ns#" term="stuff" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>[NSWindow _close];</title><content type="html">This evening I spend debugging some really weird bug in my Cocoa-based application. As last resort I decided to take a disassembler and check the internals of the AppKit. To my greatest astonishment, I found there the following code:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_P2VtTJwX2TA/SCtgnP5fP1I/AAAAAAAACc8/KPlZbbLAKpk/s1600-h/Picture+18.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_P2VtTJwX2TA/SCtgnP5fP1I/AAAAAAAACc8/KPlZbbLAKpk/s400/Picture+18.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5200356422128189266" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is the [NSWindow _close] method. I have no idea what string constants with such values do there. I have never had Google SketchUp on my computer and I suppose OCDisasm doesn't know about it too. Thus, I think I have a documental evidence of unnatural relationships between Apple and Google's code. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-7693114638547481672?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/cxj97L5hrj4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/7693114638547481672/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2008/05/nswindow-close.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/7693114638547481672?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/7693114638547481672?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/cxj97L5hrj4/nswindow-close.html" title="[NSWindow _close];" /><author><name>Mikhail Kalugin</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="21" src="http://bp1.blogger.com/_P2VtTJwX2TA/R4iutE4jpoI/AAAAAAAACEE/Aw7vk4haZBs/S220/x_d2fc89b6.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://bp0.blogger.com/_P2VtTJwX2TA/SCtgnP5fP1I/AAAAAAAACc8/KPlZbbLAKpk/s72-c/Picture+18.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2008/05/nswindow-close.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkENSHc4eCp7ImA9WxVSFUU.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-6416773627880156167</id><published>2008-01-21T07:41:00.001+06:00</published><updated>2009-01-10T15:44:59.930+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-10T15:44:59.930+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="opinions" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Indians, indians</title><content type="html">&lt;p&gt;Have just found the following line of code while debugging &lt;a href="http://wala.sourceforge.net/wiki/index.php/Main_Page"&gt;WALA&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;code&gt;&lt;br /&gt;static public final boolean verbose = ("true".equals(System.getProperty("...."))&lt;br /&gt;? true : false);&lt;br /&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;That's probably the most popular "stupid" line of code I've ever seen. Constructions like&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;code&gt;(....)?true:false&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;if (...) { return true; } else { return false; }&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;can be found in almost every project. Really is it so hard to notice that a boolean result can be assigned or returned?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-6416773627880156167?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/8yIMMPHAR38" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/6416773627880156167/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2008/01/indians-indians.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/6416773627880156167?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/6416773627880156167?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/8yIMMPHAR38/indians-indians.html" title="Indians, indians" /><author><name>Mikhail Kalugin</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="21" src="http://bp1.blogger.com/_P2VtTJwX2TA/R4iutE4jpoI/AAAAAAAACEE/Aw7vk4haZBs/S220/x_d2fc89b6.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2008/01/indians-indians.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAESH4-fip7ImA9WxVSFUU.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-7081103491184994386</id><published>2007-12-25T01:31:00.001+06:00</published><updated>2009-01-10T15:45:09.056+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-10T15:45:09.056+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="my life" /><title>Wish-list</title><content type="html">I never liked wish-lists in blogs. I thought that it is too boldly. But after seeing terrible situations, when friends don't know what to present on a birthday and thus give all the money to a single guy, who buys something strange for all, and after that friends present this gift as collective. Troubles are obvious. Firstly, friends don't even conceive what to present. Secondly, they put all responsibilities on a somebody, getting rid of corresponding difficulties. As a result everybody feels unhappy. Therefore, I suppose that publishing a wish-list in several weeks before a birthday may be a good thing.&lt;br /&gt;&lt;br /&gt;So...&lt;br /&gt;0. Polarizing filter&lt;br /&gt;1. Good sharp cooking knife. Or a set of knives.&lt;br /&gt;2. High-quality wine/whiskey/cognac glasses.&lt;br /&gt;3. Music in any form (CDs, SACDs, DVD-Audio, LPs)&lt;br /&gt;4. Books without translation (Adams Douglas, O. Henry, Oscar Wilde, old England classics)&lt;br /&gt;5. Juicer&lt;br /&gt;6. Cooking book&lt;br /&gt;7. Classic CS books (Knuth, Brooks, Joel, Dragon Book)&lt;br /&gt;8. Matured whiskey&lt;br /&gt;9. Small portable headphones (not in-ear, but without a head-band)&lt;br /&gt;10. Comfortable chair from IKEA (even cheapest would be great)&lt;br /&gt;11. Apple Mighty Mouse Wireless&lt;br /&gt;12. External HD Box&lt;br /&gt;13. iPhone&lt;br /&gt;14. iMac 24"&lt;br /&gt;15. Porsche 911 Turbo&lt;br /&gt;16. Business offer from Steve Jobs&lt;br /&gt;17. Google's controlling stock (just a joke, let pass)&lt;br /&gt;&lt;br /&gt;Note: This list may be updated later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-7081103491184994386?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/-SgU5GYtn_8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/7081103491184994386/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2007/12/wish-list.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/7081103491184994386?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/7081103491184994386?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/-SgU5GYtn_8/wish-list.html" title="Wish-list" /><author><name>Mikhail Kalugin</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="21" src="http://bp1.blogger.com/_P2VtTJwX2TA/R4iutE4jpoI/AAAAAAAACEE/Aw7vk4haZBs/S220/x_d2fc89b6.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2007/12/wish-list.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAGRXk6eSp7ImA9WxVSFUU.&quot;"><id>tag:blogger.com,1999:blog-6052529346117968387.post-4939312972030139739</id><published>2007-12-09T18:15:00.001+06:00</published><updated>2009-01-10T15:45:24.711+06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-10T15:45:24.711+06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tech" /><category scheme="http://www.blogger.com/atom/ns#" term="stuff" /><title>Blog, blog, blog it all!</title><content type="html">Incredibly fun video. I especially liked: "first you need a buzzword, ... find yourself an engineer...".&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/fi4fzvQ6I-o&amp;amp;rel=1&amp;amp;border=0"&gt;&lt;param name="wmode" value="transparent"&gt;&lt;embed src="http://www.youtube.com/v/fi4fzvQ6I-o&amp;amp;rel=1&amp;amp;border=0" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Won't you blog about this song? :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6052529346117968387-4939312972030139739?l=fourdman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MikhailKaluginsBlog/~4/n2KK3c4R1ls" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fourdman.blogspot.com/feeds/4939312972030139739/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fourdman.blogspot.com/2007/12/blog-blog-blog-it-all.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/4939312972030139739?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6052529346117968387/posts/default/4939312972030139739?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MikhailKaluginsBlog/~3/n2KK3c4R1ls/blog-blog-blog-it-all.html" title="Blog, blog, blog it all!" /><author><name>Mikhail Kalugin</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="21" src="http://bp1.blogger.com/_P2VtTJwX2TA/R4iutE4jpoI/AAAAAAAACEE/Aw7vk4haZBs/S220/x_d2fc89b6.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://fourdman.blogspot.com/2007/12/blog-blog-blog-it-all.html</feedburner:origLink></entry></feed>

