Support 
RB
 Solipsism Gradient 
Support Forums
Rainer Brockerhoff
Solipsism Gradient   XML (RSS 2.0)
Goto page Previous  1, 2, 3, 4, 5, 6 ... 107, 108, 109  Next Copy this: Trackback Ping URL for this topic
   Support Forum Index -> Rainer Brockerhoff's Weblog
My latest photos [RSS 2.0]
www.flickr.com
Links & subscriptions
Your mileage may vary. Some names have been shortened. [*]s link to RSS feeds.

My Technorati profile

Comics
Dilbert [*]
Doctor Fun [*]
Liberty Meadows [*]
Medium Large [*]
PvPonline [*]

Weblogs
43 Folders [*]
Aaron Swartz [*]
Adventures of AccordionGuy [*]
Advogato [*]
Alastair's Place [*]
all noise all the time [*]
ambiguous [*]
Andy Ihnatko's YellowText [*]
andymatuschak.org [*]
Anil Dash [*]
Armed and Dangerous [*]
aurgasm [*]
Backup Brain [*]
Bag and Baggage [*]
BarlowFriendz [*]
bbum's weblog-o-mat [*]
Ben Hammersley.com [*]
Benjamen Walker's Theory Of Everything [*]
Betalogue [*]
Beyond the Beyond [*]
Big Nerd Ranch Weblog [*]
Blake Ross on Firefox and Beyond [*]
blakeseely.com - Blog [*]
Boing Boing Blog [*]
bramcohen [*]
Brilliant Corners [*]
Burningbird [*]
cabel.name [*]
Call Me Fishmeal. [*]
carpeaqua [*]
chaotic intransient prose bursts [*]
Chief Blogging Officer [*]
Chris Hanson [*]
codepoetry [*]
Cognitive Daily [*]
The Comics Curmudgeon [*]
Cool Tools [*]
Corante: Copyfight [*]
Corbin's Treehouse Blog [*]
Critical Section [*]
Cult of Mac [*]
Culture Hack [*]
Daring Fireball [*]
The Daily WTF [*]
0xDECAFBAD [*]
DeepFUN [*]
devixstudio's Photos [*]
Different Thinker [*]
The Dilbert Blog [*]
Ditchnet.org [*]
Doc Searls [*]
Don Box's Spoutlet [*]
Dowbrigade News [*]
DrunkenBlog [*]
Due Diligence [*]
Epeus' epigone [*]
Eric.Weblog() [*]
Ernie the Attorney [*]
Escapable Logic [*]
evhead [*]
FatBits: John Siracusa's Journal [*]
figby.com [*]
flow|state [*]
Folklore.org [*]
Forwarding Address: OS X [*]
Freedom To Tinker [*]
Fritz Anderson's Weblog [*]
F-Secure Antivirus Research Weblog [*]
FurdLog [*]
GlennLog [*]
Glorified Typist [*]
Godwin's Law [*]
Google Blog [*]
Google Earth Blog [*]
Google Weblog [*]
growabrain [*]
[GusMueller blog] [*]
Guy Kawasaki [*]
h4ck3r+=boi [*]
Halley's Comment [*]
Helpful Tiger [*]
How to Save the World [*]
HyperJeff Blog [*]
iClub RSS Feed [*]
Inessential [*]
Interconnected [*]
James Duncan Davidson [*]
Jeffrey Veen [*]
Jeffrey Zeldman Presents [*]
Jeremy Zawodny's blog [*]
jnd.org [*]
Joel on Software [*]
Joho the Blog [*]
Joi Ito's Web [*]
Jonathon Delacour [*]
Jon's Radio [*]
Jorgen Thelin's weblog [*]
just like heaven [*]
The J-Walk Blog [*]
Karelia Software [*]
Karelia's Cocoa Open Source [*]
kottke.org [*]
Language Log [*]
Lessig Blog [*]
Lockergnome Bytes [*]
Loic Le Meur Blog [*]
MacBlog [*]
Mac Geekery - Get your geek on. [*]
Mad Professor [*]
Making Light [*]
Matt Croydon::postneo [*]
Matt Gemmell [*]
Membranophonist's Ramblings [*]
Memepool [*]
michael-mccracken.net [*]
Michael Tsai's Weblog [*]
Mind Hacks [*]
MoCoLoco [*]
Modern Geekery [*]
Musings From the Software Underground [*]
Neil Gaiman's Journal [*]
the [non]billable hour [*]
NSBlog [*]
NSLog(); [*]
ongoing [*]
On the Thought [*]
Out of Cheese [*]
Paolo Valdemarin [*]
Paul Graham [*]
Peak Oil Optimist [*]
Philip Greenspun Weblog [*]
C:\PIRILLO.EXE [*]
Plastic Bag [*]
PragDave [*]
Presentation Zen [*]
The Presurfer [*]
Rainer Brockerhoff's Photos [*]
raoli.com [*]
Ranchero [*]
Rands in Repose [*]
Reality and Rhetoric [*]
Recycled Knowledge [*]
Red Sweater Blog [*]
Reflex›es de um c‹o com pulgas... [*]
rentzsch.com [*]
ridiculous_fish [*]
Ross Mayfield's Weblog [*]
Russ Nelson [*]
Russell Beattie Notebook [*]
Sam Ruby [*]
SATN [*]
Der Schockwellenreiter [*]
Scobleizer Weblog [*]
Sci-Fi Hi-Fi [*]
scribble, scribble, scribble... [*]
Scripting News [*]
Seb's Open Research [*]
A Shareware Life [*]
Shirt Pocket Watch [*]
Untitled Source [*]
Sifry's Alerts [*]
SIGPIPE 13 [*]
Simon Willison's Weblog [*]
Solipsism Gradient [*]
Squawks of the Parrot [*]
stanforth.org :: geekview [*]
Stefan Tilkov's Random Stuff [*]
stevenberlinjohnson.com [*]
~stevenf [*]
Superf’cie Reflexiva [*]
Surfin' Safari [*]
talblog [*]
taliesin's log [*]
Teal Sunglasses [*]
Technorati Tag: Apple [*]
Technorati Tag: cocoa [*]
Tesugen.com [*]
Theobroma Cacao [*]
The Tao of Mac [*]
ThinkMac Blog [*]
This is not your practice blog [*]
tima thinking outloud. [*]
Untitled Source [*]
TooMuchSexy.blog [*]
Toxic Software (Blog) [*]
The Trademark Blog [*]
Trader Mike [*]
The Unofficial Apple Weblog [*]
The Unofficial Photoshop Weblog [*]
Unsanity.org [*]
Urbanape : [*]
VenChar [*]
viridiandesign [*]
Webpropaganda [*]
What Do I Know [*]
Who Cares? [*]
whytheluckystiff.net [*]
Words [*]
Writers Block Live [*]
XCode Experiences [*]
Ztuff [*]

News sites
80211b News [*]
ADC Reference Library Updates [*]
Amazon SF&Fantasy [*]
Ananova: Quirkies [*]
Apple Developer Connection Headlines [*]
Apple Knowledge Base [*]
Apple Hot News [*]
Apple Press Releases [*]
Ars Technica [*]
BBC News | Technology [*]
CocoaDev RecentChanges [*]
Computerworld Shark Tank [*]
CNET News.com [*]
CNN.com [*]
CNN.com - Offbeat [*]
Digital Photography [*]
Download Squad [*]
DreamHost Blog [*]
EurekAlert! [*]
FlickrBlog [*]
Folha Online - Brasil [*]
Folha Online - Cotidiano [*]
Folha Online - Dinheiro [*]
Folha Online - Ilustrada [*]
Forbes.com News [*]
Forbes.com Technology News [*]
Gizmo Emerging Technology Magazine [*]
Gizmodo [*]
INFO Online [*]
kuro5hin.org [*]
MacBetaGroup [*]
MacDevCenter [*]
MacInTouch [*]
MacMegasite [*]
MacMerc [*]
MacNN [*]
MacUpdate - Mac OS X [*]
MacSlash [*]
Moreover Science [*]
Museum of Hoaxes [*]
Nature Science Update [*]
New Scientist [*]
NewsFactor Network [*]
NYT: Health [*]
NYT: International [*]
NYT: National [*]
NYT: Science [*]
NYT: Technology [*]
NYT: Travel [*]
Open Source Applications Foundation Blog [*]
O'Reilly Network Articles [*]
Salon.com [*]
Science Blog [*]
Scientific American [*]
Slashdot [*]
Techdirt [*]
The Register [*]
ThinkGeek: What's New [*]
TidBITS [*]
Treehugger [*]
Versiontracker [*]
Wired News [*]
View previous topic :: View next topic  
Author Message
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 29 Apr 2009 22:42:23    Cocoa musings pt.6 Reply with quote

Also, yikes. 26 days without posting! I plead temporary insanity brought on by tax filing time, and Twitter - the latter being a more convenient outlet for short links and thoughts.

Anyway, taxes are filed and we're now having a short working vacation in the hills of Petrópolis, an old town north of Rio de Janeiro. Dorinha is taking a short English immersion course (excellent BTW), and I'm coding again, yay!

I'm patching up some loose ends in Klicko in preparation to cloning its preference panel for the next version of Quay, as I've mentioned before. While doing that, I'm also trying to refactor my code into a tighter and more readable form. Some of that might be interesting...

For instance, the automatic update checker has a dialog button to "Open System Preferences" and this should go to the Klicko preference panel. Now, System Preferences may already be running but with another panel selected; in any event, the Klicko panel should be opened and ready for the user to see update details. There are several ways to accomplish this.

Most people probably will consider, at first, writing an AppleScript to open System Preferences and then select the Klicko preferences panel. This is unnecessarily complex, and I've looked at several solutions. The simplest one-liner to do so from Cocoa would be:
Code:
[[NSWorkspace sharedWorkspace] openFile:@"/full/path/to/my.prefPane"];
There's a non-obvious down-side to that: NSPreferencePane is generic and may be implemented by other apps for their preference plug-ins. Someone's application might use it and declare .prefPane in its Info.plist. This would in my opinion be a mistake, in that double-clicking or running the code above might (or not) open that other app instead of System Preferences!

The solution I finally hit upon uses Launch Services to open the correct application with the preference panel, like this:
Code:
   FSRef ref;
if (LSFindApplicationForInfo(0, CFSTR("com.apple.systempreferences"), NULL, &ref, NULL)==noErr) {
   LSApplicationParameters parms = {0,kLSLaunchDefaults,&ref,NULL,NULL,NULL,NULL};
   NSArray* args = [NSArray arrayWithObject:[NSURL fileURLWithPath:@"/full/path/to/my.prefPane"]];
   if (LSOpenURLsWithRole((CFArrayRef)args, kLSRolesAll, NULL, &parms, NULL, 0)==noErr) {
      // success!
   }
}
This code first finds the System Preferences app by its bundle ID, and makes a FSRef for it. The FSRef is then pointed to from the LSApplicationParameters structure, and passed to LSOpenURLsWithRole; this will run System Preferences if it's not already running, and tell it to open the panel.

It's tempting to pass the panel's path as an argument inside of LSApplicationParameters. This does indeed work if System Preferences is not already running, but unfortunately it's ignored if it is.
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 03 Apr 2009 09:42:41    WWDC 2009 Reply with quote

At first I thought I wouldn't make it, but now I'm very happy to announce that I'm going to WWDC 2009.

I'll arrive in San Francisco around noon on June 4th (Thursday), and will leave, also around noon, on June 16th (Tuesday). I'll be glad to meet with anyone who's interested...

More as it happens!
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 01 Apr 2009 09:52:52    Virtual fungus attacks! Reply with quote

This just in:
Quote:
Virtual fungus is the new threat to computers

Scientists confirmed the existence of a new type of virtual plague, which is neither a virus nor a Trojan Horse. U. S. Computer Science researchers are calling their discovery a "computer fungus". The lead researcher is Antonio de Marco, associate professor at West California University.

Just like fungi and mold, which attack photos and cassette tapes from past century, the virtual fungus degrades image, sound, and video files stored on computers. "The problem occurs even with backup files that are rarely accessed", says de Marco. Scientists found out an average quality loss of about 7% a year for JPEG images, 15% a year for TIFF images and 4% a year for MP3 files. Other infected files are QuickTime videos, followed by AVI files, with 9% a year.

Arjun Radhakrishnan, Ph.D. in Applied Computer Science at Stanford, explains that this virtual fungus has not yet been detected because its effects are gradual and insidious. "The typical PC user never thinks about this, because performance loss of the operating system itself is trivial". According to him, people consider it understandable that pirated music from Napster in 2000 sounds a little bit degraded with time, as well as porn images downloaded from the web get smaller and fuzzy. Photoshop files are opened with unexplainable wrong colors, get dark and fade. Movies open in progressively tinier windows. Even texts may deteriorate, having their accented characters mixed up.

These would be some symptoms of the digital fungus. The effects are visible when comparing a digital photo to its printed copy from when it was brand new. "There was a progressive degradation of almost all these materials, and many may not resist until the next decade", says Radhakrishnan.

Transmission of the disease does not appear to be caused by hackers. Environmental factors may be involved. Houses with more than one computer also have more chances. Using cell phones or having plasma TVs and air conditioning may also be risk factors.

While there is no commercial software solution to it, the researchers recommend making daily backups of your files and keeping them on older and durable medias, like CD-R or floppy disks; transcribe ripped videos from DVD to VHS; send all photos to a lab to be printed on paper. "This is the only way to ensure longevity of your digital data", points out de Marco.
Thanks to the folks at geek.com.br and MAC+.

Update: original text was translated from Portuguese by Julio Cesar Silva Santos (jcsantos@me.com), at first I thought it was a group effort. Thanks Julio!


Last edited by Rainer Brockerhoff on 05 Apr 2009 22:10:04; edited 1 time in total
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 14 Mar 2009 13:23:39    Cocoa musings, pt.5 Reply with quote

One feature of Klicko which is approaching buglessness asymptotically is auto-update.

I frequently get asked why I'm not just using Sparkle. There are two main reasons: first, it's somewhat bulky and generic. Look at the latest version of ClickToFlash: it's 1.4MB, of which 1.1MB are used by Sparkle. (Why this matters to me may best be explained in another post; the same goes for my generic dislike of in-app frameworks.)

Second, Sparkle does not have automatic updating as such; it normally checks when its application (or plug-in, or whatever) is run. Klicko, as a System Preferences panel, is mostly a set-it-and-forget-it piece of software; my experience was that few users remember to check for updates regularly, or re-open the panel at all. So I need periodic checking in the background process; however, Klicko's background process is constrained to not use AppKit or show any UI, so it can't use Sparkle either.

That said, updating applications or preference panels is in many ways a tricky business. One of the problems is that, unlike Classic applications, Mac OS X applications or bundles are composed of a folder hierarchy, and finding items in that hierarchy is usually done by APIs that turn out to be path-based. If you move (or, worse, substitute) a running application or plug-in, it may fail in interesting ways: things like images or executable code may be cached from the old version, and others will be pulled in from the new version.

In other words, it's not advisable to have a running app delete itself and replace its bundle by a freshly-downloaded one. In the case of a preferences panel, System Preferences (at least in Leopard) doesn't properly unload and uncache a panel when installing a new one. The solution is to quit the application and have a different process do the swap-in and immediate re-execution of the updated application.

The swap-in part is easily handled by FSReplaceObject() or its cousin, FSPathReplaceObject(); just make sure of passing kFSReplaceObjectDoNotCheckObjectWriteAccess|kFSReplaceObjectPreservePermissionInfo in the options argument, and everything will work. (However, this may require user authorization for replacing bundles in, say, /Library/PreferencePanes.)

For simplicity, let's show only the re-execution part. Sparkle uses a shell script to do so. Slightly simplified, it looks like this:
Code:
   setenv ("Executable_PATH", path, 1);
   system ("/bin/bash -c '{ for (( i = 0; i < 3000 && $(echo $(/bin/ps -xp $PPID|/usr/bin/wc -l))-1; i++ )); do\n"
         "    /bin/sleep .2;\n"
         "  done\n"
         "  if [[ $(/bin/ps -xp $PPID|/usr/bin/wc -l) -ne 2 ]]; then\n"
         "    /usr/bin/open \"${Executable_PATH}\"\n"
         "  fi\n"
         "} &>/dev/null &'");

Don't expect me to explain line-for-line what this does; I'm not a shell scripting guru. From what I understand, it runs the ps utility to wait until the parent process quits, then opens the path passed in. This solution has the advantage of not requiring a separate tool to do its work. The disadvantage is that spawns several auxiliary processes; a shell, the ps tool, and so forth; often it also logs some cryptic errors to the system log.

In Klicko, since I already had to write an auxiliary tool for other purposes, like installing and uninstalling, it was easy to just add another function to it. But, for simplicity, let's assume the tool just does wait for its parent process to quit and opens its argument path. There's a simple way of doing so, by using a pipe. Pipes are already used for communicating between parent and child processes, anyway. Here's how you could launch the tool using NSTask:
Code:
   NSTask* task = [[NSTask alloc] init];
   [task setLaunchPath:@"/path/to/tool"];
   [task setArguments:[NSArray arrayWithObject:[[NSBundle mainBundle] bundlePath]]];
   [task setStandardInput:[NSPipe pipe]];
   [task launch];
   [NSApp terminate:nil];
and the tool would look like this:
Code:
int main(int argc, char **argv) {
   char dummy;
   read(STDIN_FILENO, &dummy, 1);
   CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8*)argv[1], strlen(argv[1]), FALSE);
   LSOpenCFURLRef(url, NULL);
}

Notice that we launch the NSTask with a dummy NSPipe, and terminate immediately afterwards without waiting for the tool to complete. This means that the sending end of the pipe is shut down when the application terminates. On the tool side, we have a read() call trying to get a single byte from the pipe. The parent application never sends anything, so it hangs there until the application terminates and the pipe is shut down; the read statement will return an error (which is ignored) and the tool then calls LaunchServices to re-launch the application.

If you already have all the paths in C string format, and don't want to use Cocoa for calling the tool, here's an alternative solution on the application side:
Code:
   int fildes[2] = {0,0};
   if (!pipe(fildes)) {
      if (!vfork()) {
         close(fildes[1]);
         if (dup2(fildes[0],STDIN_FILENO)!=STDIN_FILENO) {
            close(fildes[0]);
         }
         err = execl(pathToTool,pathToTool,pathToApplication,NULL);
         _exit(EXIT_FAILURE);
      }
      close(fildes[0]);
   }
   [NSApp terminate:nil];
which does essentially the same thing using BSD APIs.

Many thanks to Mike Ash for explaining the pipe trick to me, and correcting my misunderstanding about child process lifetimes; I originally thought that a child process wouldn't survive the termination of its parent. Apparently this is true only for shell processes.
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 11 Mar 2009 11:12:17    Re: Cocoa musings pt.4, and Klicko updates Reply with quote

Klicko 1.1 (201) is up, with the aforementioned full keyboard access/VoiceOver support...
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 10 Mar 2009 09:48:27    Re: Cocoa musings pt.4, and Klicko updates Reply with quote

An hours-long outage somewhere inside my ISP made me re-evaluate the idea about a reachability transition callback. It seems to be reliable enough when the local network is involved, but when the clogged pipe is several routers away, it can go down - and never go up again.

So what I'm doing now is, while the network is down, retry with a direct reachability test every half hour or so; of course if the callback says it's back up, I tear that timer down again. Seems to work OK.

Several interim builds of Klicko went up in the meantime, implementing this and other small changes. The latest one is now in testing; build 1.1 (201) will implement full keyboard accessibility and VoiceOver support. At least in the preferences panel part; the background process is still mouse-oriented, and I don't foresee disabled people needing any of the Klicko functions. Still, it's good practice since nearly all of the Klicko panel code will be re-used in the upcoming rewrite of Quay, and there it will certainly be useful.
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 24 Feb 2009 18:54:44    Re: Klicko 1.1 Reply with quote

And, the reachability check explained below is now also present in Klicko 1.1 (189).
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 23 Feb 2009 15:50:13    Re: Cocoa musings pt.4 Reply with quote

M. Uli Kusterer emailed me to say I'd forgotten that some people still have non-broadband connections. I had supposed that NSURLConnection would simply return an immediate error if the internet link is down - it turns out that it may autoconnect if the user has a dialup connection, for instance.

The way around that is to use the network reachability APIs. Here's one way to insert that into the example below:
Code:

#include <SystemConfiguration/SCNetworkReachability.h>
...
- (id)initWithURL:(NSURL*)theURL delegate:(id)theDelegate {
   if ((self = [super init])) {
      SCNetworkConnectionFlags flags = 0;
      if (SCNetworkCheckReachabilityByName([[theURL host] UTF8String], &flags)) {
         const SCNetworkConnectionFlags mask =
            kSCNetworkFlagsReachable|
            kSCNetworkFlagsConnectionRequired|
            kSCNetworkFlagsConnectionAutomatic|
            kSCNetworkFlagsInterventionRequired;
         if ((flags&mask)==kSCNetworkFlagsReachable) {
            delegate = theDelegate;
            data = nil;
            conn = [[NSURLConnection alloc]
               initWithRequest:[NSURLRequest requestWithURL:theURL]
               cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
               timeoutInterval:60.0]
               delegate:self];
            return self;
         }
      }
      [self autorelease];
      self = nil;
   }
   return self;
}

This changes the alloc/init pair to return nil whenever the URL host is unreachable... you'll have to test for that of course.

Update: the downside to the above approach is that the SCNetworkCheckReachabilityByName() function will block until it gets the information - which may take several seconds, perhaps more on some systems. The solution I'm actually using is more complex, installing a reachability transition callback, which sets a global flag that is tested before activating the NSURLConnection.
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 21 Feb 2009 17:26:33    Cocoa musings pt.4 Reply with quote

One thing I had to do very recently was to download a relatively short block of data from my server. There are some nice Cocoa shortcuts for such a thing, like:
Code:
NSError* error = nil;
NSData* data = [NSData dataWithContentsOfURL:theURL options: NSUncachedRead error:&error];

which accesses that URL from the server, presents it to you as NSData and/or gives you an error object. The problem, however, is that it's synchronous; if your server is down, it may take some time to time-out, and all that time your UI is inactive.

The initial impulse to get around this problem would be to simply spin those two lines off into a secondary thread. It's easy to underestimate the subtleties of that, however, and there are good alternatives available. Here's a simplified version of what I eventually elected to use. First the .h file:
Code:
@interface AsynchDownload : NSObject {
   NSURLConnection* conn;
   NSMutableData* data;
   id delegate;
}
- (id)initWithURL:(NSURL*)theURL delegate:(id)theDelegate;
- (void)cancel;
@end

and here the .m file:
Code:
@implementation AsynchDownload

- (id)initWithURL:(NSURL*)theURL delegate:(id)theDelegate {
   if ((self = [super init])) {
      delegate = theDelegate;
      data = nil;
      conn = [[NSURLConnection alloc]
         initWithRequest:[NSURLRequest requestWithURL:theURL]
         cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0]                            
         delegate:self];
   }
   return self;
}

- (void)cancel {
   [conn cancel];
}

- (void)dealloc {
   [conn release];
   [data release];
   [super dealloc];
}

- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error {
   [delegate performSelectorOnMainThread:@selector(failure:)
      withObject:[error localizedDescription] waitUntilDone:NO];
}

- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response {
   [data release];
   data = nil;
}

- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)theData {
   if (!data) {
      data = [[NSMutableData alloc] init];
   }
   [data appendData:theData];
}

- (void)connectionDidFinishLoading:(NSURLConnection*)connection {
   [delegate performSelectorOnMainThread:@selector(success:)
      withObject:data waitUntilDone:NO];
}
@end

and, finally, here's how to call it:
Code:
   AsynchDownload* download = [[AsynchDownload alloc] initWithURL:theURL delegate:self];

... and in the same class, two methods:
Code:
- (void)failure:(NSString*)failure {
   [download release];
   //.. complain and show the failure string
}

- (void)success:(NSData*)data {
   [download release];
   // do something with data
}

... and finally, you might call
Code:
   [download cancel];

somewhere inside, say, a cancel button's action.

This takes care of nearly all common cases. The only non-obvious part is the connection:didReceiveResponse: method; according to the docs, you need to discard already-received data there, as it may be sent multiple times before you get the final data. In this method, you could also ask the NSURLResponse for the data size, to set a download progress indicator.

Finally, note the performSelectorOnMainThread: messages which pass the results back to your own code; they neatly insulate you from threading effects.
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 21 Feb 2009 12:13:25    Re: Klicko 1.1 Reply with quote

Rainer Brockerhoff wrote:
Maybe I should, after all, implement regular automatic version checking? I dislike such automatic processes myself, but I'll look into doing it less obtrusively.
So, it's done; Klicko 1.1 (187) has automatic version checking.

Details were trickier than I had anticipated, but I managed to do it while increasing download size by only 44K (23%). Most of that is accounted for by a new helper application. The background process checks for updates periodically. If an update is out, the process runs the helper app to display an alert; the user can then ask the app to run System Preferences to download and install the update. (If the Klicko panel is already open, the helper app isn't called.)
View user's profile AIM Address
Display posts from previous:   
   Support Forum Index -> Rainer Brockerhoff's Weblog All times are GMT - 3 Hours
Goto page Previous  1, 2, 3, 4, 5, 6 ... 107, 108, 109  Next
Page 5 of 109

 
Jump to:  
You cannot post new topics
You cannot reply to topics
You cannot edit your posts
You cannot delete your posts
You cannot vote in polls


t.gif

Page generated in 0.412 seconds, 12 queries executed