<?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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CUUHRnk8eyp7ImA9WxBbFEo.&quot;"><id>tag:blogger.com,1999:blog-1455593480232067247</id><updated>2010-03-13T11:40:37.773+02:00</updated><title>blog.zssz.me</title><subtitle type="html">My notes about iPhone development, Location Based Services and other things.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.zssz.me/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.zssz.me/" /><author><name>Zsombor Szabo</name><uri>http://www.blogger.com/profile/00755069551354049151</uri><email>zsombor@gmail.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>4</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/Zsszme" /><feedburner:info uri="zsszme" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CEUMSX07cCp7ImA9WxBQEkw.&quot;"><id>tag:blogger.com,1999:blog-1455593480232067247.post-5187089181234706600</id><published>2010-01-10T22:22:00.001+02:00</published><updated>2010-01-11T14:18:08.308+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-11T14:18:08.308+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="User interface" /><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Asynchronous" /><category scheme="http://www.blogger.com/atom/ns#" term="Cocoa" /><category scheme="http://www.blogger.com/atom/ns#" term="Core Data" /><category scheme="http://www.blogger.com/atom/ns#" term="OpenMaps" /><title>Asynchronous fetch in Core Data</title><content type="html">Who of you Cocoa devs likes &lt;a href="http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/CoreData/cdProgrammingGuide.html"&gt;Core Data&lt;/a&gt;? Hands up... Whoa, I can see many hands up there. I share the same sentiment. For those of you who don't know what Core Data is don't bother reading further but here is a short introduction taken out from the docs:&lt;br /&gt;
&lt;br /&gt;
The Core Data framework provides generalized and automated solutions to common tasks associated with object life-cycle and object graph management, including persistence. Its features include:t&lt;br /&gt;
- Built-in management of undo and redo beyond basic text editing&lt;br /&gt;
- Automatic validation of property values to ensure that individual values lie within acceptable ranges and that combinations of values make sense&lt;br /&gt;
- Change propagation, including maintaining the consistency of relationships among objects&lt;br /&gt;
- Grouping, filtering, and organizing data in memory and in the user interface&lt;br /&gt;
- Automatic support for storing objects in external data repositories&lt;br /&gt;
- Optional integration with Cocoa bindings to support automatic user interface synchronization&lt;br /&gt;
&lt;br /&gt;
Fetching objects from persistent stores! That sounds nice. How does a typical fetch look like? Again taken out &lt;a href="http://developer.apple.com/Mac/library/documentation/DataManagement/Conceptual/CoreDataSnippets/Articles/fetching.html#//apple_ref/doc/uid/TP40008284"&gt;from the docs&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
NSManagedObjectContext *context = &amp;lt;#Get the context#&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];&lt;br /&gt;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"&amp;lt;#Entity name#&amp;gt;" inManagedObjectContext:context];&lt;br /&gt;
[fetchRequest setEntity:entity];&lt;br /&gt;
&lt;br /&gt;
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"&amp;lt;#Sort key#&amp;gt;" ascending:YES];&lt;br /&gt;
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];&lt;br /&gt;
[fetchRequest setSortDescriptors:sortDescriptors];&lt;br /&gt;
&lt;br /&gt;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"&amp;lt;#Predicate string#&amp;gt;",&lt;br /&gt;
&amp;lt;#Predicate arguments#&amp;gt;];&lt;br /&gt;
[request setPredicate:predicate];&lt;br /&gt;
&lt;br /&gt;
NSError *error;&lt;br /&gt;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&amp;amp;error];&lt;br /&gt;
if (fetchedObjects == nil) {&lt;br /&gt;
// Handle error&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
[fetchRequest release];&lt;br /&gt;
[sortDescriptor release];&lt;br /&gt;
[sortDescriptors release];&lt;br /&gt;
&lt;br /&gt;
Unfortunately Core Data currently doesn't have asynchronous fetch support built in. So if you have a large data set and/or have a complicated fetch request it takes time until it fetches your objects from the persistent stores. But most importantly the current thread &lt;b&gt;blocks&lt;/b&gt; while the context executes the fetchRequest. If that thread is the main thread then your UI will hang and gives the impression to the user that the app has frozen. We don't want that, do we?&lt;br /&gt;
&lt;br /&gt;
I've created IZManagedObjectContext, a subclass of &lt;a href="http://developer.apple.com/Mac/library/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectContext_Class/NSManagedObjectContext.html#//apple_ref/occ/cl/NSManagedObjectContext"&gt;NSManagedObjectContext&lt;/a&gt;, that extends it with asynchronous fetch feature. Let me modify the above snippet and show you have to use it:&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;IZManagedObjectContext&lt;/i&gt; *context = &amp;lt;#Get the context#&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];&lt;br /&gt;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"&amp;lt;#Entity name#&amp;gt;" inManagedObjectContext:context];&lt;br /&gt;
[fetchRequest setEntity:entity];&lt;br /&gt;
&lt;br /&gt;
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"&amp;lt;#Sort key#&amp;gt;" ascending:YES];&lt;br /&gt;
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];&lt;br /&gt;
[fetchRequest setSortDescriptors:sortDescriptors];&lt;br /&gt;
&lt;br /&gt;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"&amp;lt;#Predicate string#&amp;gt;",&lt;br /&gt;
&amp;lt;#Predicate arguments#&amp;gt;];&lt;br /&gt;
[request setPredicate:predicate];&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;[context executeFetchRequestAsynchronously:fetchRequest delegate:delegate]; &lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
When the fetch is complete the the delegate will be notified with&lt;br /&gt;
- (void)managedObjectContext:(IZManagedObjectContext *)context fetchCompletedForRequest:(NSFetchRequest *)request withResults:(NSArray *)results error:(NSError *)error;&lt;br /&gt;
&lt;br /&gt;
Note that the difference between the two fetch methods is that the asynchronous one does NOT block the thread so your app looks snappy. That makes us happy.&lt;br /&gt;
&lt;br /&gt;
If you are anxious to try it out and don't want to know the juicy details how it gets the job done then just head over &lt;a href="http://github.com/zssz/IZManagedObjectContext"&gt;here&lt;/a&gt;. I have licensed it under the BSD license. &lt;br /&gt;
&lt;br /&gt;
How does it work, you ask? &lt;br /&gt;
&lt;br /&gt;
It follows &lt;a href="http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/CoreData/Articles/cdMultiThreading.html#//apple_ref/doc/uid/TP40003385"&gt;these&lt;/a&gt; guidelines. It fetches the objectIDs (which are immutable and safe to pass across thread boundaries) that satisfy the predicate of the fetch request on a separate thread using an NSOperation on a separate NSManagedObjectContext instance using the same persistentStoreCoordinator. Then it passes those objectIDs back the the main thread and issues a new fetch request with a predicate that asks for those specific objects with the objectIDs that we received. But I said it doesn't block the main thread? Well, I wasn't telling the truth. For my defense the second fetch should have only O(n) complexity if the executeFetchRequest:error: is optimized for fetching objectIDs. But in most of the cases this second fetch will execute faster than the original fetch request which had a more "complicated" predicate. And you really should be using a fetch limit when dealing with large data sets anyway.&lt;br /&gt;
&lt;br /&gt;
I haven't included any example project that shows &lt;a href="http://github.com/zssz/IZManagedObjectContext"&gt;IZManagedObjectContext&lt;/a&gt; in action. You just have to take my word for it that it works. I use it in the latest alpha build of OpenMaps and haven't encountered any problems, yet. If you find bugs in it then please do notify me.&lt;br /&gt;
&lt;div class="zemanta-pixie" style="height: 15px; margin-top: 10px;"&gt;&lt;a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/cdb39923-e501-46cc-8f20-4565cffa8271/" title="Reblog this post [with Zemanta]"&gt;&lt;img alt="Reblog this post [with Zemanta]" class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=cdb39923-e501-46cc-8f20-4565cffa8271" style="border: medium none; float: right;" /&gt;&lt;/a&gt;&lt;script defer="defer" src="http://static.zemanta.com/readside/loader.js" type="text/javascript"&gt;
&lt;/script&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/1455593480232067247-5187089181234706600?l=blog.zssz.me' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/wjFWQaO-Vqy2H3ck5WcflwBuUAQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wjFWQaO-Vqy2H3ck5WcflwBuUAQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/wjFWQaO-Vqy2H3ck5WcflwBuUAQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wjFWQaO-Vqy2H3ck5WcflwBuUAQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Zsszme/~4/3Mw1NKPq848" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.zssz.me/feeds/5187089181234706600/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.zssz.me/2010/01/asynchronous-fetch-in-core-data.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1455593480232067247/posts/default/5187089181234706600?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1455593480232067247/posts/default/5187089181234706600?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Zsszme/~3/3Mw1NKPq848/asynchronous-fetch-in-core-data.html" title="Asynchronous fetch in Core Data" /><author><name>Zsombor Szabo</name><uri>http://www.blogger.com/profile/00755069551354049151</uri><email>zsombor@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="08386150749266453410" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://blog.zssz.me/2010/01/asynchronous-fetch-in-core-data.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YGQ38-cSp7ImA9WxNaGUs.&quot;"><id>tag:blogger.com,1999:blog-1455593480232067247.post-8577457441642446859</id><published>2009-12-04T23:12:00.000+02:00</published><updated>2009-12-04T23:12:02.159+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-04T23:12:02.159+02:00</app:edited><title>Is 8.8.8.8 Faster Than What You Are Using?</title><content type="html">Nerds and bloggers had a huge geekgasm yesterday as&amp;nbsp;&lt;a href="http://googleblog.blogspot.com/2009/12/introducing-google-public-dns.html"&gt;Google introduced its Public DNS&lt;/a&gt;. Coming from Google, with a very sexy IP I must add, you are by religion obliged to switch over, right? It depends...&lt;br /&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;Let's experiment with the&amp;nbsp;&lt;i&gt;&lt;a href="http://en.wikipedia.org/wiki/Domain_Information_Groper"&gt;dig&lt;/a&gt;&lt;/i&gt;&amp;nbsp;(with one g) command line utility. With help of&amp;nbsp;&lt;i&gt;dig&lt;/i&gt;&amp;nbsp;you can query any DNS server for a specific domain. Just fire up your terminal and type for e.g.&amp;nbsp;&lt;i&gt;dig @8.8.8.8 google.com&lt;/i&gt;. That command queries the DNS server with IP 8.8.8.8 (the Google DNS server) to resolve google.com to an IP address.&amp;nbsp;You should get something like this as output:&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
$ dig @8.8.8.8 google.com&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.6.0-APPLE-P2 &amp;lt;&amp;lt;&amp;gt;&amp;gt; @8.8.8.8 google.com&lt;br /&gt;
; (1 server found)&lt;br /&gt;
;; global options: +cmd&lt;br /&gt;
;; Got answer:&lt;br /&gt;
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 44616&lt;br /&gt;
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0&lt;br /&gt;
&lt;br /&gt;
;; QUESTION SECTION:&lt;br /&gt;
;google.com.&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;IN&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;A&lt;br /&gt;
&lt;br /&gt;
;; ANSWER SECTION:&lt;br /&gt;
google.com.&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;300&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;IN&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;A&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;74.125.53.100&lt;br /&gt;
google.com.&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;300&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;IN&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;A&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;74.125.67.100&lt;br /&gt;
google.com.&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;300&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;IN&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;A&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;74.125.45.100&lt;br /&gt;
&lt;br /&gt;
;; Query time: 39 msec&lt;br /&gt;
;; SERVER: 8.8.8.8#53(8.8.8.8)&lt;br /&gt;
;; WHEN: Fri Dec &amp;nbsp;4 22:57:35 2009&lt;br /&gt;
;; MSG SIZE &amp;nbsp;rcvd: 76&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;So google.com has&amp;nbsp;74.125.45.100&amp;nbsp;74.125.67.100 and 74.125.53.100&amp;nbsp;as IPs. But most importantly what we are after is the&amp;nbsp;query time:&amp;nbsp;39&amp;nbsp;msec. Is that fast? Let's compare it with other DNS servers.&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;In my tests I used two DNS servers from the&amp;nbsp;&lt;a href="http://www.romtelecom.ro/"&gt;two&lt;/a&gt;&amp;nbsp;&lt;a href="http://www.rdslink.ro/"&gt;major&lt;/a&gt;&amp;nbsp;ISPs from Romania, the sexy DNS server 8.8.8.8 and one of the DNS servers of&amp;nbsp;&lt;a href="http://www.opendns.com/"&gt;OpenDNS&lt;/a&gt;. I looked up 3 different domains 100 times. Between the lookups I waited 30 seconds for the DNS servers' caches to clear a bit. For each domain lookup test I wrote a separate shell script. The shell script testing the DNS servers for wikipedia.org looks like:&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;#!/bin/bash&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;domain="wikipedia.org"&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;nameservers[0]="193.231.236.17" &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # RDS&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;nameservers[1]="193.231.100.130" &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# Romtelecom&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;nameservers[2]="8.8.8.8" &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# Google&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;nameservers[3]="208.67.220.220" &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # OpenDNS&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;iterations=100&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;sleeptimesecons=30&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;rm DNSQueryResults$domain.txt&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;for (( i=0;i&amp;lt;$iterations;i++ )); do&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;echo "iteration count: $i"&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;for (( j=0;j&amp;lt;4;j++ )); do&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;echo -ne "`dig @${nameservers[$j]} $domain | grep ';; Query time:' | cut -d" " -f4`\t" &amp;gt;&amp;gt; DNSQueryResults$domain.txt&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;done&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;echo &amp;gt;&amp;gt; DNSQueryResults$domain.txt # newline&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;sleep $sleeptimesecons&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;done&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;After formatting the data into a human readable format in&amp;nbsp;an OpenOffice spreadsheet the charts are (my&amp;nbsp;apologies&amp;nbsp;for the&amp;nbsp;colorblind):&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_PHlCn60ls0c/Sxl0718JVyI/AAAAAAAABp8/qZgo930__FM/s1600-h/Screen+shot+2009-12-04+at+10.34.33+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_PHlCn60ls0c/Sxl0718JVyI/AAAAAAAABp8/qZgo930__FM/s640/Screen+shot+2009-12-04+at+10.34.33+PM.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;a href="http://1.bp.blogspot.com/_PHlCn60ls0c/Sxl0-xDWiqI/AAAAAAAABqE/2sxtkNhoqkU/s1600-h/Screen+shot+2009-12-04+at+10.34.45+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_PHlCn60ls0c/Sxl0-xDWiqI/AAAAAAAABqE/2sxtkNhoqkU/s640/Screen+shot+2009-12-04+at+10.34.45+PM.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;a href="http://4.bp.blogspot.com/_PHlCn60ls0c/Sxl1AmHuSTI/AAAAAAAABqM/R7laGgjWJK8/s1600-h/Screen+shot+2009-12-04+at+10.35.00+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_PHlCn60ls0c/Sxl1AmHuSTI/AAAAAAAABqM/R7laGgjWJK8/s640/Screen+shot+2009-12-04+at+10.35.00+PM.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Conclusion&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Is it worth switching to Google's DNS servers?&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&amp;nbsp;- yes IF your ISP provides you a very slow DNS server. Just look at RDS's DNS server response times in the charts. In case you were wondering I was on RDS's network during the testing.&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;- no IF your ISP provides you a decent DNS server that has a good cache policy because it will always have a better response time since you are physically closer to the DNS server (less hops till your IP packet reaches it) unless it is overladed&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Bonus question: Is it worth switching over from OpenDNS to Google?&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Currently OpenDNS provides a ton of extra features that Google currently doesn't e.g. content filtering at DNS level, botnet/malware protection, network shortcuts, etc. From the tests on average OpenDNS's DNS server response was a bit slower (by ~17 msec) than of Google's. Until Google coughs up some neat features for it's DNS service or it will be considerably faster than of OpenDNS my answer would be NO.&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Want to reproduce the test at your machine? Just use the shell script and don't forget to post&amp;nbsp;here your results in the comments.&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/1455593480232067247-8577457441642446859?l=blog.zssz.me' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kbSIrA8999JyDa7m0LsU6kSHOM8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kbSIrA8999JyDa7m0LsU6kSHOM8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kbSIrA8999JyDa7m0LsU6kSHOM8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kbSIrA8999JyDa7m0LsU6kSHOM8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Zsszme/~4/FYqSE7_YEzU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.zssz.me/feeds/8577457441642446859/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.zssz.me/2009/12/is-8888-faster-than-what-you-are-using.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1455593480232067247/posts/default/8577457441642446859?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1455593480232067247/posts/default/8577457441642446859?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Zsszme/~3/FYqSE7_YEzU/is-8888-faster-than-what-you-are-using.html" title="Is 8.8.8.8 Faster Than What You Are Using?" /><author><name>Zsombor Szabo</name><uri>http://www.blogger.com/profile/00755069551354049151</uri><email>zsombor@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="08386150749266453410" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_PHlCn60ls0c/Sxl0718JVyI/AAAAAAAABp8/qZgo930__FM/s72-c/Screen+shot+2009-12-04+at+10.34.33+PM.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.zssz.me/2009/12/is-8888-faster-than-what-you-are-using.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEECRHczcCp7ImA9WxNbGE8.&quot;"><id>tag:blogger.com,1999:blog-1455593480232067247.post-1226873549626193863</id><published>2009-11-21T17:17:00.012+02:00</published><updated>2009-11-21T18:57:45.988+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-21T18:57:45.988+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NSURLConnection" /><category scheme="http://www.blogger.com/atom/ns#" term="Reachability" /><category scheme="http://www.blogger.com/atom/ns#" term="Network Activity" /><category scheme="http://www.blogger.com/atom/ns#" term="iphone" /><title>Meet IZURLConnection, the NSURLConnection with Reachability and easy Network Activity monitoring</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;This is my 2nd blog post on the topic of iPhone development and I am happy to share with you yet an another open source project of mine: &lt;a href="http://github.com/zssz/IZURLConnection"&gt;IZURLConnection&lt;/a&gt;  &lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;Basically it mimics &lt;a href="http://developer.apple.com/Mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html"&gt;NSURLConnection&lt;/a&gt;, has the same delegate callbacks, and heck it uses NSURLConnection as it's back-end, BUT it has 2 nifty features:&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;1. Robust (uses &lt;a href="http://devworld.apple.com/iphone/library/samplecode/Reachability/index.html"&gt;Reachability&lt;/a&gt; v2.0)&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;Network connections on a mobile device are terrible. Or worse. Connection is spotty and if you happen to issue an NSURLConnection when the device is/goes dark (e.g. enters into a tunnel or a stargate wormhole) then you'll end up with a delegate call with an error like (all &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Constants/Reference/reference.html#//apple_ref/doc/c_ref/NSURLErrorCancelled"&gt;NSURLErrorDomain&lt;/a&gt; domain error codes): NSURLErrorNotConnectedToInternet, NSURLErrorCannotFindHost, NSURLErrorCannotConnectToHost, NSURLErrorTimedOut  &lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;In my real life experiments NSURLErrorNotConnectedToInternet is an error that is permanent and lasts longer while the others are transient. They are usually present when there's a glitch e.g. switching between network connection types (3G, EDGE, WiFi). IZURLConnection does not notify the delegate with NSURLErrorNotConnectedToInternet. It uses the Reachability class provided by Apple and waits until the host provided in the request will be reachable again and automatically retries. In the other (transient) error cases it retries by default 2 times before notifying the delegate of the error.  &lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;This takes a little bit of error handling off of your shoulders. But wait, there is more. Continue reading.&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;2. Simple and easy way to notify the user of network activity&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;When it starts or finishes loading it posts a NSNotification instance. If there are network connections out there then you are safe to assume that your network indicator on the device should be spinning and you should switch it on. Take a look at the following code snippet in the appdelegate:&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
&lt;pre class="textmate-source"&gt;- (void)applicationDidFinishLaunching:(UIApplication *)application {
    
    networkConnections = 0;
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(IZURLConnectionDidStart:) 
                                                 name:IZURLConnectionConnectionDidStartNotification 
                                               object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(IZURLConnectionDidFinish:) 
                                                 name:IZURLConnectionConnectionDidFinishNotification 
                                               object:nil];     
    
    // Override point for customization after app launch    
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
}

- (void)updateNetworkActivityIndicator
{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = (networkConnections != 0);
}

- (void)IZURLConnectionDidStart:(NSNotification *)notification
{
    // Only increment networkConnections if the request is a network protocol
    // Assuming that NSURLConnection handles the following protocols: ftp, http, https, file
    // Assuming that file is the only protocol that is not a network protocol
    IZURLConnection *connection = (IZURLConnection *)[notification object];
    if ([connection.request.URL.scheme isEqualToString:@"file"] == NO)
    {
        networkConnections++;
        [self updateNetworkActivityIndicator];
    }
}

- (void)IZURLConnectionDidFinish:(NSNotification *)notification
{
    // Only decrement networkConnections if the request is a network protocol
    // Assuming that NSURLConnection handles the following protocols: ftp, http, https, file
    // Assuming that file is the only protocol that is not a network protocol
    IZURLConnection *connection = (IZURLConnection *)[notification object];
    if ([connection.request.URL.scheme isEqualToString:@"file"] == NO)
    {
        networkConnections--;
        [self updateNetworkActivityIndicator];
    }
}&lt;/pre&gt;&lt;br /&gt;
&lt;div style="text-align: left;"&gt;3. All your current NSURLConnection code will work if you refactor to IZURLConnection&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;Well, this isn't entirely true. IZURLConnection currently doesn't implement NSURLConnection's Runloop Scheduling methods:&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;pre class="textmate-source"&gt;- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode
- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode
&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;
If you wish to extend it though, go ahead. At the current state it gets the job done. I've never used runloop scheduling with NSURLConnection anyway.&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;Important note: Be prepared to receive multiple delegate messages as IZURLConnection may retry multiple times.&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
That's it. &lt;a href="http://github.com/zssz/IZURLConnection"&gt;Take it away&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1455593480232067247-1226873549626193863?l=blog.zssz.me' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/d7Fmqxxu4OW_KXXgMI6apaSqC3k/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/d7Fmqxxu4OW_KXXgMI6apaSqC3k/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/d7Fmqxxu4OW_KXXgMI6apaSqC3k/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/d7Fmqxxu4OW_KXXgMI6apaSqC3k/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Zsszme/~4/WNEj2kJ0C90" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.zssz.me/feeds/1226873549626193863/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.zssz.me/2009/11/this-is-my-2nd-blog-post-on-topic-of.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1455593480232067247/posts/default/1226873549626193863?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1455593480232067247/posts/default/1226873549626193863?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Zsszme/~3/WNEj2kJ0C90/this-is-my-2nd-blog-post-on-topic-of.html" title="Meet IZURLConnection, the NSURLConnection with Reachability and easy Network Activity monitoring" /><author><name>Zsombor Szabo</name><uri>http://www.blogger.com/profile/00755069551354049151</uri><email>zsombor@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="08386150749266453410" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.zssz.me/2009/11/this-is-my-2nd-blog-post-on-topic-of.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEABQ3k7fyp7ImA9WxNbGEw.&quot;"><id>tag:blogger.com,1999:blog-1455593480232067247.post-7109312302490500260</id><published>2009-11-21T11:02:00.001+02:00</published><updated>2009-11-21T17:19:12.707+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-21T17:19:12.707+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Growl" /><category scheme="http://www.blogger.com/atom/ns#" term="iphone" /><category scheme="http://www.blogger.com/atom/ns#" term="OpenMaps" /><title>iPhone &amp; "Growl" Notifications</title><content type="html">Probably this is not a a good way to start a blog since I haven't introduced myself. And the short bio under my profile picture hardly says anything about me. Anyway, I have more important things to share with you right now and I can promise you that the mandatory introduction post will follow.&lt;br /&gt;
&lt;br /&gt;
Ever wanted to notify the user of your iPhone application of certain events gracefully, like the desktop Growl does? &lt;a href="http://www.tweetdeck.com/iphone/"&gt;Tweetdeck for the iPhone&lt;/a&gt; does it, in a way. Well, now you can too. Hereby I release the source code for &lt;a href="http://github.com/zssz/IZGrowlManager"&gt;IZGrowlManager&lt;/a&gt; under BSD license which allows you to do that.&lt;br /&gt;
&lt;br /&gt;
So how does it look like? Here's a screenshot of it in action:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_PHlCn60ls0c/Swc7Qumj9kI/AAAAAAAABpY/vAGWkUAhP-w/s1600/img_9034.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_PHlCn60ls0c/Swc7Qumj9kI/AAAAAAAABpY/vAGWkUAhP-w/s400/img_9034.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
Pretty neat, huh?&lt;br /&gt;
&lt;br /&gt;
You may ask why would someone use something like this to notify the user, there's UIAlertView for this. Growl project leader @boredzo &lt;a href="http://twitter.com/boredzo/status/5375228270"&gt;was thinking the same&lt;/a&gt; when I asked him if there was a Growl framework for the iPhone which I could use. I must disagree. The main difference between the 2 notification approaches is that the UIAlertView disrupts completely the user's workflow because it doesn't let him/her continue until he/she pushes a button while the Growl approach can be dismissed very quickly also without any user interaction since the bubbles disappear after a while.&lt;br /&gt;
&lt;br /&gt;
I'm sure he misunderstood me.&lt;br /&gt;
&lt;br /&gt;
So, how can you use &lt;a href="http://github.com/zssz/IZGrowlManager"&gt;IZGrowlManager&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
When you reach to a point where you want to notify the user of an event then create an IZGrowlNotification instance and pass it to the shared IZGrowlManager instance which takes care of the rest.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"&gt;IZGrowlNotification *notification = [[IZGrowlNotification alloc] initWithTitle:@"Tip" description:@"Shake the device to reset the route" image:[UIImage imageNamed:@"information-symbol.png"] context:nil delegate:nil];&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"&gt;[[IZGrowlManager sharedManager] postNotification:notification];&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"&gt;[notification release];&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to track if the user tapped on the bubble belonging to the notification then set a delegate for the IZGrowlNotification object and implement the (only) delegate method&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"&gt;- (void)didSingleTapOnNotification:(IZGrowlNotification *)notification;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
That's it. There are a few tweeks, just read the header file for more info.&lt;br /&gt;
&lt;br /&gt;
Some constraints:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;it's not a framework to interact with any other application on the device or on the desktop. It's a simple notification framework for you to notify the user of your app as if Growl would magically run in the background&lt;/li&gt;
&lt;li&gt;currently there is only this 'Smoke' style available with no ability to modify it via the framework.&lt;/li&gt;
&lt;li&gt;fixed sized notification bubbles only&lt;/li&gt;
&lt;li&gt;3 notification bubbles at a time. If new notification will come in they will be enqueued and posted when there will be a free spot available&lt;/li&gt;
&lt;li&gt;bubbles will be appearing starting from the bottom right corner&lt;/li&gt;
&lt;li&gt;image will be resized to 30x30&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Here's the &lt;a href="http://github.com/zssz/IZGrowlManager"&gt;link&lt;/a&gt; again to the source on GitHub if you missed it in the first paragraph.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1455593480232067247-7109312302490500260?l=blog.zssz.me' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5QtBh5jfwwbfSj-ryH37JsFXLhY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5QtBh5jfwwbfSj-ryH37JsFXLhY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5QtBh5jfwwbfSj-ryH37JsFXLhY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5QtBh5jfwwbfSj-ryH37JsFXLhY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Zsszme/~4/fY-S8oMzFjM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.zssz.me/feeds/7109312302490500260/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.zssz.me/2009/11/iphone-growl-notifications.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1455593480232067247/posts/default/7109312302490500260?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1455593480232067247/posts/default/7109312302490500260?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Zsszme/~3/fY-S8oMzFjM/iphone-growl-notifications.html" title="iPhone &amp; &quot;Growl&quot; Notifications" /><author><name>Zsombor Szabo</name><uri>http://www.blogger.com/profile/00755069551354049151</uri><email>zsombor@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="08386150749266453410" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_PHlCn60ls0c/Swc7Qumj9kI/AAAAAAAABpY/vAGWkUAhP-w/s72-c/img_9034.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.zssz.me/2009/11/iphone-growl-notifications.html</feedburner:origLink></entry></feed>
