Using the power of WebGL and some JavaScript Chris Milk, the US music video producer and some smart friends of his at Google have created some impressive visuals that play in real-time within a web browser without needing any plugins. These stunning graphics use the next round of HTML5 features that are sweeping across browsers now.
Programming
There are 31 posts filed in Programming (this is page 5 of 7).
Impressive JavaScript PC Emulator
Fabrice Bellard has written an impressive PC emulator that actually emulates a PC with a 32 bit x86 compatible CPU. This is some really imaginative use of pure JavaScript which I’m sure no-one would have every dreamed of as it allows you to run a virtual instance of Linux inside a browser window!
It currently only works in Google Chrome 11 or Firefox 4 as it uses part of the WebGL HTML5 spec that Safari hasn’t implemented yet but is definitely worth playing around with. You can even compile C files!
Core Data Objects in Wrong Sections
NSFetchedResultsController is a really handy class. Use one of the default Core Data templates in Xcode and you’ll very quickly have a nice list of managed objects in a table view. With a few more lines of code you can get the NSFetchedResultsController to group your objects by sections. You do this by specifying a key-path in the class’s constructor method but there is another step that if overlooked will cause some confusion.
In a sample app I’ve created a food table that lists food in categories.
FetchedResultsController method grouping sections using a key-path:
Objective-C:
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
// Create and configure a fetch request with the food entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"RWFood" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
// Create the sort descriptors array.
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:nameDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Create and initialize the fetch results controller.
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"category" cacheName:@"Food"];
self.fetchedResultsController = aFetchedResultsController;
fetchedResultsController.delegate = self;
// Memory management.
[aFetchedResultsController release];
[fetchRequest release];
[nameDescriptor release];
[sortDescriptors release];
return fetchedResultsController;
}
Swift:
lazy var fetchedResultsController: NSFetchedResultsController<rwfood> = {
let fetchRequest: NSFetchRequest<rwfood> = RWFood.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: "category", cacheName: "Food")
aFetchedResultsController.delegate = self
do {
try aFetchedResultsController.performFetch()
} catch let error {
print("Unable to perform fetch: \(error)")
}
return aFetchedResultsController
}()
Specify a key-path
Save and quit the app a few times and you’ll see the objects seem to be in the wrong sections. If you look closer you’ll see that the objects are actually sorted in ascending name order. On looking at the code, it seems this is exactly what we asked the program to do! After some testing it also seems to show up more often if the table is a grouped one.
As per the docs, after you specify a key-path to group each section with you also need to make sure the first sort descriptor is sorting this key-path. Add a sort descriptor and everything will work as expected.
Revised fetchedResultsController method with missing sort descriptor:
Objective-C:
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
// Create and configure a fetch request with the plant entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"RWPlant" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
// Create the sort descriptors array.
NSSortDescriptor *typeDescriptor = [[NSSortDescriptor alloc] initWithKey:@"type" ascending:YES];
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:typeDescriptor, nameDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Create and initialize the fetch results controller.
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"type" cacheName:@"Plants"];
self.fetchedResultsController = aFetchedResultsController;
fetchedResultsController.delegate = self;
// Memory management.
[aFetchedResultsController release];
[fetchRequest release];
[categoryDescriptor release];
[nameDescriptor release];
[sortDescriptors release];
return fetchedResultsController;
}
Swift:
lazy var fetchedResultsController: NSFetchedResultsController = {
let fetchRequest: NSFetchRequest<rwplant> = RWPlant.fetchRequest()
let typeDescriptor = NSSortDescriptor(key: "type", ascending: true)
let nameDescriptor = NSSortDescriptor(key: "name", ascending: true)
fetchRequest.sortDescriptors = [typeDescriptor, nameDescriptor]
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: "type", cacheName: "Plants")
aFetchedResultsController.delegate = self
do {
try aFetchedResultsController.performFetch()
} catch let error {
print("Unable to perform fetch: \(error)")
}
return aFetchedResultsController
}()
Quick Spreadsheet to plist Technique
Imagine you have a huge list of names in a spreadsheet and you’d like to get this data into an Apple plist file to use in your iPhone/Mac app or import into a Core Data model. Such a long list of data would take forever to cut and paste so here is a really quick way to build that plist.
Continue reading
Get emailed when uploads complete
Sometimes I have to send a client a really large file or app that’s too large to post to Basecamp. The solution is to upload to a web server over night and email the client a link when it’s done. Not wanting to tie my laptop down overnight here is a great solution that emails you when it’s done.
Lets say your file is called NinjaApp-1.0.ipa and you use SSH/SFTP on your server to copy everything…
1. Drop your file onto a spare Mac or server.
2. Type the following into a terminal window:
scp NinjaApp-1.0.ipa [email protected]:/var/www/downloads/.
&& echo "Upload done" | mail -s "Upload Complete" [email protected]
That’s it! You’ll get an email when it’s done.