Saturday, March 30, 2013

Extracting Radio Format Information from Wikipedia

I have two radio station apps in the App Store, AM Towers USA which is free, and FM Towers USA which is not. They try to map all the active radio stations in the United States. The information comes from two places, the FCC and Wikipedia.
If my apps are missing a radio station, it's likely because I couldn't find a format for them on Wikipedia. Assuming the station has a Wikipedia page, which the vast majority do, then either the format is missing from the page's radio infobox or it's badly formatted. As a public service, I've reformatted dozens of these boxes like this one for a small station in Arkansas.
{{Infobox radio station
| name                 = KDQN
| image                = 
| city                 = [[De Queen, Arkansas|De Queen]], [[Arkansas]]
| area                 = 
| slogan               =
| branding             = 
| frequency            = 1390 [[kHz]]
| repeater             = 
| airdate              = 
| language             = Spanish
| power                = 500 [[watt]]s day
| class                = D
| facility_id          = 30600
| coordinates          = {{coord|34|1|57|N|94|19|43|W|region:US-AR_type:landmark|display=inline,title}}
| callsign_meaning     = 
| former_callsigns     = 
| owner                = Jay W. Bunyard & Anne W. Bunyard
| licensee             = 
| sister_stations      = 
| webcast              = 
| website              = 
| affiliations         = 
}}

It's missing a format field, so AM Towers didn't pick it up, but the text of the article says it broadcasts a Spanish Music format. Now, I don't know what specific kind of Spanish music this station broadcasts, so I can't in good faith edit this entry, but let's assume it's Spanish Contemporary. I'd insert a field, like so:
| format = [[Spanish Contemporary]]
The [[ ]] brackets are important as they will cause a link to be shown to the Wikipedia page on that radio format, or in this case to the page on the various regional styles of Mexican music.
But what if the station broadcasts in another format, like Spanish Oldies, well then I'd insert:
| format = [[Spanish Contemporary]]/[[Spanish Oldies]]

There isn't any consistency as to what people use to separate a list of formats. Some use semicolons, others slashes, or spaces or HTML breaks. I wish they were consistent, it'd make my job easier.
Then I make sure that all the [ are balanced by ], and that all the { are balanced by }. A stray } can ruin an otherwise parseable infobox.

Thursday, March 14, 2013

Objective-C Categories and Keeping Functionality Separate

Ever since spending months on a never finished project to tear the rendering code out of a large commercial application and into a QuickLook plugin, I've been hypersensitive to dependencies in my code. All of my code is on a need to know basis from the other objects in the project. There are a variety of techniques in Objective-C to aid you in decoupling your code, but the one I'm writing about today is the category.

Let's say I'm writing a document framework, something I'll be using in many apps, each with different needs. Some apps will need editing, most apps will need importing from documents, some will need writing to documents, most will need onscreen rendering, some will need conversion to export formats.

Naively, I could just add all that needed functionality into each of my class's source files. But the Objective-C category allows me to segregate my code by functional topic.

@interface DocumentNode : NSObject
@property(strong, nonatomic, readonly) NSString* type;
@property(strong, nonatomic, readonly) NSDictionary* attributes;
@property(strong, nonatomic, readonly) NSArray* children;
@property(strong, nonatomic, retain) NSObject* cache;
@property(strong, nonatomic, readonly) NSString* name; // an attribute

-(id) initWithAttributes:(NSDictionary*)startAttributes 
           children:(NSArray*)startChildren 
           type:(NSString*)startType 
           name:(NSString*)aName;
@end

and then if I need to have a method to edit the node because I'm writing an editor and not just a viewer, I can create a separate file with an 'Editing' category:
@interface DocumentNode(Editing)
-(DocumentNode*) cloneWithAttributes:(NSDictionary*)newAttributes;
-(DocumentNode*) cloneWithNewChildren:(NSArray*)newChildren;
@end

or if I need a place for my rendering code
@interface DocumentNode(Rendering)
-(BOOL) renderIntoContext:(CGContextRef)quartzContext  
           withDocumentVisitContext:(DocumentVisitContext*)visitContext;
@end

Now, categories are limited in that you cannot add new member variables to your classes via categories like you could by subclassing your objects. You could use objc_setAssociatedObject to implement the storage for a property, but that would probably be too over the top for just keeping implementation separate. When faced with this design problem, I punted and put the property in the main implementation file, as in the following case where my undo ad redo stacks are unused unless the document needs editing functionality.
@interface GHDocument : NSObject
@property(nonatomic, strong) NSMutableArray* undoStack; // only used if Editing is included
@property(nonatomic, strong) NSMutableArray* redoStack;
In practice, once the code is factored in this way, it can be reused modularly. If I have a project that just acts as a viewer, I just don't include the 'DocumentNode+Editing.h' in my other source files, and I don't compile the 'DocumentNode+Editing.m' file by unchecking it's inclusion in Xcode. For small projects this might not matter much, but when you are building up a large codebase or want to reuse just a small bit in another project, you'll regret not factoring things for modularity from the very beginning.
 
Google+