Wednesday, July 1, 2009

Monday, June 29, 2009
I read about this online someplace, and this will get 2.x available again.
- Select your project file and Get Info.
- Under the General tab, you'll see a drop down for Base SDK for All Configurations and choose your SDK there.
- You're done. You'll see all the SDKs listed now in the normal drop down you're used to using.
Labels: Xcode

When I was a child (not too much older than the age my own son is right now), my father had a pretty extensive collection of classical LPs and some 8-tracks. He had a large home system with huge BA wooden speakers, tube-powered amplifiers, the best needle in the business, etc.
We used to make fun of his collection of music as being old fogey-type stuff, but we were really just trying to act cool. Some of it was amazing and fun. I've apologized several times in the past about how we used to make fun of this stuff. In many ways, classical and ethnic music is more powerful than any "spirit of the decade" music could dream of being.
My sister and I used to play the 8-track of James Last's Russia. A few of the tracks any way. You'd have to click through spots on the tape and wait for your song to start, I remember four rectangular green lights that would tell you which approximate spot the tape was currently in. I don't remember if you could flip the tape upside down or not, I think so.
Anyway... we used to play song two: "Kalinka" (an example only video link) which slowly builds up with choir to result in ripping horns and a thunderous beat with some Russian chanting (well, perhaps not chanting but we didn't know what they were singing). We used to bounce off the walls laughing and having a good time.
Another favorite was "Russian Folk Dance" (Russischer Volkstanz) - which has a similar pattern to Kalinka. Mad fun.
A few years ago my father gave me that 8-track from his collection in the hopes to transfer it to CD. I never got around to it, I'd have to go to a place with the capability, pay cash, etc. But it always burned there in the back of my mind. For a few years whenever I remembered that album, I'd take a spin around the internet looking for it.
Now that I actually have this album, you might want to look it up, it's extremely hard to find (I don't do torrents or anything like that so I can't help you there), but if you're up for some really awesome ethnic music with true power behind it (I'm not talking about Polkas here, I'm taking about great horns, moving compositions, a big symphony sound with some modern instrumentation, and a great choir) then you should look into it. It's different.
It's not on iTunes, unfortunately. Get the LP if you can (if you can play those anymore).
Perhaps my father, my sister and myself will be the only ones who really enjoy this album and that's fine with me, I just wanted to put it out there. I am going to soak in "Nicht der Wind" (Not the Wind) for the fifth time now. Headphones up.
Ahhh.
Labels: James Last, Music, Russia
It's mainly targeted at Twitter at the moment, but many more services are under development and you can add extend support for others (ie. extend Twitter support for use with it's Search API). Using it is actually fairly easy... build the next great Twitter client!
Here is a quick screen-shot taken of Tweetie running beneath the included example OS X desktop application:

Check this library out if you're at all interested in using it. It rocks.
It costs me only a few minutes time, but I wish it was something that would magically go away in the near future. It's monday, my caffeine quotient has not been met, it's rainy in Boston, and perhaps I'm a little gray at the moment.
Thursday, June 25, 2009
totalCount = 0;Update 2. Since the file structure normally gets flattened out within your iPhone application (I guess there are some compiler tricks you can do), you'll always be targeting the root of the app directory. With that in mind, you'll want to probably use some kind of naming convention to separate any special files you'd like to collect from the bundle. You can also use extension. Say collect up and get the count of all images in your bundle that are JPGs and contain "image_" in the title:
NSArray *d = [[NSBundle mainBundle] pathsForResourcesOfType:@"jpg" inDirectory:nil];
for(NSString *s in d){
if([[s lastPathComponent] hasPrefix:@"image_"]){
totalCount++;
}
}
totalCount = 0;Boom.
NSArray *d = [[NSBundle mainBundle] pathsForResourcesOfType:@"jpg" inDirectory:nil];
for( int i=0;i<[d count];i++){
NSString *searchForMe = @"image_";
NSString *s = [[NSString alloc] initWithString:[d objectAtIndex:i]];
NSRange range = [s rangeOfString:searchForMe];
if( range.location != NSNotFound ){
totalCount++;
}
}
Update. I'm a moron. I should have just looked into NSBundle.h.
NSUInteger jpegCount = [[[NSBundle mainBundle] pathsForResourcesOfType:@"jpg" inDirectory:subDirName] count];
You can get the number of a type of item in your bundle on the iPhone, and this can come in very handy. No magic numbers. This code example doesn't look in a resource directory, but you could supply the inDirectory with something like @"backgrounds" and thus build up arrays of images of differing types, etc. There may be a better way of doing this (ie. if you only want to get the count of the items), but I don't know about it yet.
NSMutableArray * imageArray = [[NSMutableArray alloc] init];Tada. I hope to find some more examples.
NSEnumerator * imageBundlePathEnumerator = [[[NSBundle mainBundle] pathsForResourcesOfType: @"jpg" inDirectory: nil] objectEnumerator];
NSString * imageBundlePath = nil;
while (imageBundlePath = [imageBundlePathEnumerator nextObject])
{
[imageArray addObject: [[[NSImage alloc] initWithContentsOfFile: imageBundlePath] autorelease]];
}
NSLog(@"Number of images loaded : %d", [imageArray count]);
NSImage * anImage = nil;
NSEnumerator * imageEnumerator = [imageArray objectEnumerator];
while (anImage = [imageEnumerator nextObject])
{
NSLog(@"image = %@", anImage);
}
Labels: iPhone, Objective-C
Friday, June 12, 2009
Well done. Enjoy Pittsburgh... get to raise that banner in a new barn.
I ordered my gear a few minutes after the players skated around with the cup and it's all already backordered. Oh well, I can wait a little while.
"Lord Stanley, Lord Stanley, gimme the brandy!"
I personally think that there is no place for this kind of thing at a paid professional conference. If it was held in the corner of a bar with cigars, beers, a laptop & a projector, I wouldn't think it was appropriate either.
There, I said it. Let's just hope this kind of thing never happens again.
Thursday, June 11, 2009
2. I can't wait for Safari for Snow Leopard to allow plugins to crash without bringing the browser down with it.
Thread 14 Crashed:
0 com.apple.CoreFoundation 0x914663cb CFReadStreamGetStatus + 43
1 ...romedia.Flash Player.plugin 0x176939d1 0x173b8000 + 2996689
2 ...romedia.Flash Player.plugin 0x1768c43f 0x173b8000 + 2966591
3 ...romedia.Flash Player.plugin 0x1768c713 0x173b8000 + 2967315
4 ...romedia.Flash Player.plugin 0x1768c7c1 0x173b8000 + 2967489
5 ...romedia.Flash Player.plugin 0x1746b727 0x173b8000 + 735015
6 ...romedia.Flash Player.plugin 0x1746bab3 0x173b8000 + 735923
7 ...romedia.Flash Player.plugin 0x1746bf69 0x173b8000 + 737129
8 ...romedia.Flash Player.plugin 0x1746c362 0x173b8000 + 738146
9 ...romedia.Flash Player.plugin 0x1746c68d 0x173b8000 + 738957
10 ...romedia.Flash Player.plugin 0x176935ff 0x173b8000 + 2995711
11 libSystem.B.dylib 0x91fdc155 _pthread_start + 321
12 libSystem.B.dylib 0x91fdc012 thread_start + 34
Wednesday, June 10, 2009

Thursday, May 28, 2009
One thing I just discovered is that you can have Xcode automagically place a breakpoint where the exception occurs, thus showing you just where the exception was thrown. Paired with the information on why, this is a big help in debugging.
To set this up, open up your Breakpoints window (in my version of Xcode I double-click on the Breakpoints items in the editor window Groups & Files tree control. You'll see a breakpoint item "Double-Click for Symbol" - set the breakpoint to "objc_exception_throw" and you're done. It should look something like this:

Now when you get an exception, you should be able to click the exposed line in the debugger stack trace which will take you to the offending line of code in your project.
Labels: breakpoints, exceptions, Xcode
The texture's pixel format is the way the image is stored in GPU memory.
Possible pixel formats:
- RGBA8888 (32-bit) (kTexture2DPixelFormat_RGBA8888)
- RGBA4444 (16-bit) (kTexture2DPixelFormat_RGBA4444)
- RGB5_A1 (16-bit)(kTexture2DPixelFormat_RGB5A1)
- RGB565 (16-bit) (kTexture2DPixelFormat_RGB565)
- 8 bits are assigned to the red channel, 8 bits to the green channel, 8 bits to the blue channel and 8 bits to the alpha channel.
- Use this pixel format when you need the maximum possible quality for your image.
- But it will consume the double of memory compared to 16-bit textures. Memory is a precious resource on the iPhone
- Usually it is also slower to render.
- Useful for: background image of your intro scene, and for images with lots of gradient colors
- 4 bits are assigned to the red channel, 4 bits to the green channel, 4 bits to the blue channel, and 4 bits to the alpha channel
- It gives you good quality in all channels, good speed, good memory consumption.
- Useful for: sprites that have different values of transparency
- 5 bits are assigned to the red channel, 5 bits to the green channel, 5 bits to the blue channel, and only 1 bit to the alpha channel
- It gives you good quality in RGB channels but poor quality on the A channel. It also gives you good speed and good memory consumption.
- Useful for: sprites that have transparent parts, but the transparency is either On or Off
- 5 bits are assigned to the red channel, 6 bits to the green channel, and 5 bits to the blue channel. It has no alpha channel support
- It gives you the best possible quality for 16-bit textures, but without alpha channel support.
- Useful for: background images in your game.
How to use it:
// Set the pixel format before loading the image
// RGBA 8888 image (32-bit)
[Texture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGBA8888];
Sprite *sprite1 = [Sprite spriteWithFile:@"test-rgba1.png"];
// Set the pixel format before loading the image
// RGBA 4444 image (16-bit)
[Texture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGBA4444];
Sprite *sprite2 = [Sprite spriteWithFile:@"test-rgba2.png"];
// Set the pixel format before loading the image
// RGB5A1 image (16-bit)
[Texture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGB5A1];
Sprite *sprite3 = [Sprite spriteWithFile:@"test-rgba3.png"];
// Set the pixel format before loading the image
// RGB565 image (16-bit)
[Texture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGB565];
Sprite *sprite4 = [Sprite spriteWithFile:@"test-rgba4.png"];
// restore the default pixel format
[Texture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_Default];
Labels: cocos2d, iPhone, pixel format
Wednesday, May 13, 2009
For me this network detection thing was a bit of a Holy Grail item. I'd seen a few examples around from Apple that seemed like they used tons of code to get the job done (or maybe I just didn't understand their code well enough yet). Then I read online about a seismic XML tutorial from Apple that did network detection.
I popped open the project in the Xcode Documentation window and started checking out the .h and .m files. I saw the implementation they used, and it didn't involve tons of code. And after testing it, it works just fine for the moment.
I've since been told that I could use a separate thread and populate the initial UIImageViews with a stock image, and the threaded process would fetch and place the artwork as needed (to allow for initial smooth scrolling). I don't know enough about that yet though, so this will have to do.
Make sure you Add the SystemConfiguration.framework to your project, and include it in your .m (#import
In your .h file, define a BOOL, I called mine "availableNetwork" - you don't need to assign it as a property, just up in the interface block. Make sure you also define the method in the .h... -(BOOL)isDataSourceAvailable;
Here are the two methods I'm using to report back network status (in my .m):
- (BOOL)isDataSourceAvailable {
static BOOL checkNetwork = YES;
static BOOL _isDataSourceAvailable = NO;
if (checkNetwork) { // Since checking the reachability of a host can be expensive, cache the result and perform the reachability check once.
checkNetwork = NO;
Boolean success;
const char *host_name = "google.com"; //pretty reliable :)
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, host_name);
SCNetworkReachabilityFlags flags;
success = SCNetworkReachabilityGetFlags(reachability, &flags);
_isDataSourceAvailable = success && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired);
CFRelease(reachability);
}
return _isDataSourceAvailable;
}That's the method we'll call when we load our view, and set our "availableNetwork" value to. loadView is triggered before viewDidLoad.- (void)loadView {
availableNetwork = NO;
BOOL returnVal = [self isDataSourceAvailable];
availableNetwork = returnVal;
...And there you have it. It's a one shot deal here, if connectivity returns, the flag won't be reset. You could always run a NSTimer that checks every now and then, or I am sure there is some kind of notification of that kind of change one could listen for... I'm not far enough along with all of this to know yet.Labels: iPhone, Network Status, Objective-C
So image caching is required. Once a URL image has been downloaded and when it's going to be used again, instead of fetching the image from URL, use a stored version of it instead. Currently I am caching these images in a NSMutableDictionary (although they could be written to the iPhone disk or into a database on the iPhone as well - for offline use and also a retained cache between application launches). While the latter approach is the ultimate correct one, here is a method to provide in-memory image caching. The key for each UIImage is the URL of the image.
- (UIImage*)imageNamed:(NSString*)imageNamed cache:(BOOL)cacheThis works GREAT so far, you get a little initial stutter on long lists, but once the images are loaded up, you're good to go. Since I am not currently using tons of images, memory should be okay (to keep them all around like this). Of course using the disk is going to be the ultimate solution... one I will work up next. Even for small lists it might be okay to use (if you don't plan on the images changing much...)
{
UIImage* retImage = [staticImageDictionary objectForKey:imageNamed];
if (retImage == nil)
{
retImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageNamed]]];
if (cache)
{
if (staticImageDictionary == nil)
staticImageDictionary = [NSMutableDictionary new];
[staticImageDictionary setObject:retImage forKey:imageNamed];
}
}
return retImage;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
// Add a view for the image (this is in section if cell = nil)
NSString *tmp = [NSString stringWithFormat:@"%@", [[photoArray objectAtIndex:row] objectForKey:@"url"]];
holder = [[[UIImageView alloc] initWithFrame:CGRectMake( 13, 2, 48, 50)] autorelease];
holder.tag = 4;
holder.contentMode = UIViewContentModeScaleToFill;
// Here we either load from the web or we cache it...
UIImage *ret = [self imageNamed:tmp cache:YES];
holder.image = ret;
...
[cell.contentView addSubview:holder];
...
Tuesday, May 12, 2009
Not great.
Kevin Callahan has written a tool called Accessorizer that runs stand-alone from Xcode, but can work pretty harmoniously with it saving you oodles and oodles of coding time. It's very customizable and the site contains a few videos to show you how it works.



Postings Calendar
Close



