When passing data to a web site, especially via "GET" requests (e.g. calling + stringWithContentsOfURL:encoding:error:) it's important to ensure content is properly escaped. This is also true on the iPhone when you are attempting to use a "mailto:" URL to invoke the native e-mail client from your app.
One obvious way to do this is by calling NSString's "- (NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)encoding" method. While this does a good job, it is not perfect and will miss things like "/", which may make some web services cry. The best way to do this encoding is to use:
CFStringRef CFURLCreateStringByAddingPercentEscapes (
CFAllocatorRef allocator,
CFStringRef originalString,
CFStringRef charactersToLeaveUnescaped,
CFStringRef legalURLCharactersToBeEscaped,
CFStringEncoding encoding
);This method lets you specify what you want encoded and what you want left raw. I threw together a really quick sample command line tool to show you the difference. Here are the salient lies:
NSString *url = @"<b>some HTML content</b> <a href=\"http://theresurgence.com/search/node/bible\">study materials</a>" ;
NSLog(@"Original text: [%@]", url) ;
NSLog(@"NSString percent escapes: [%@]",
[ url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]) ;
NSLog(@"CFURL percent escapes: [%@]",
CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)url, NULL, CFSTR("!*'();:@&=+$,/?%#[]"), kCFStringEncodingUTF8));
And, here is the output:
Original text: [<b>some HTML content</b> <a href="http://theresurgence.com/search/node/bible">study materials</a>] NSString percent escapes: [%3Cb%3Esome%20HTML%20content%3C/b%3E%20%3Ca%20href=%22http://theresurgence.com/search/node/bible%22%3Estudy%20materials%3C/a%3E] CFURL percent escapes: [%3Cb%3Esome%20HTML%20content%3C%2Fb%3E%20%3Ca%20href%3D%22http%3A%2F%2Ftheresurgence.com%2Fsearch%2Fnode%2Fbible%22%3Estudy%20materials%3C%2Fa%3E]
Big difference without tons of additional code. Plus, you can use CFURLCreateStringByReplacingPercentEscapesUsingEncoding just as easily to unescape any string.
UITableViewCells with just three UILabels and the second has static-height UITableViewCells three UILabels and one UIImageView. For those two, the following settings are pretty important (translate Interface Builder settings to iPhone SDK calls if you are working – as I am – purely in code):

tableView:cellForRowAtIndexPath:. When I was prototyping, I had a good portion of the transformation code in that method and have since moved it to the XML parsing routines. Since I was not able to set my cells to be opaque, limiting the number of "inner" UIViews was also high on the priority list. I did not need to background load the images in the cells, so I did not have to resort to using a subclass of UITableViewCell but I *did* implement a very rudimentary caching system which helped to speed things up a bit:
NSMutableDictionary called "heights" (the key is the row number) which caches the row heights of each cell since one of the UILabels can drastically vary in height. You need to do something like the following in tableView:heightForRowAtIndexPath::
UILabel's frame size each time in tableView:cellForRowAtIndexPath: and also retrieve said hight and calculate the number of rows in tableView:cellForRowAtIndexPath::
UITableView. Rather than go through the effort of parsing HTML on the iPhone (as I already parsed the XML file) I built this simple method from some half-finished snippets I found. It has worked in all of the cases I have needed, but your mileage may vary. It is at least a working method (which cannot be said about most of the other examples). It works on the iPhone and in standard OS X coding.
- (NSString *)flattenHTML:(NSString *)html {
NSScanner *theScanner;
NSString *text = nil;
theScanner = [NSScanner scannerWithString:html];
while ([theScanner isAtEnd] == NO) {
// find start of tag
[theScanner scanUpToString:@"<" intoString:NULL] ;
// find end of tag
[theScanner scanUpToString:@">" intoString:&text] ;
// replace the found tag with a space
//(you can filter multi-spaces out later if you wish)
html = [html stringByReplacingOccurrencesOfString:
[ NSString stringWithFormat:@"%@>", text]
withString:@" "];
} // while //
return html;
}
Python on the Mac is a mixed blessing. On one hand, it makes app development much easier. On the other hand, it limits the deployment to OX X 10.5 (Leopard) unless you do some wrangling.
I made an Objective-C version of the "desktop widget" which is available for download now. Most likely, I will not update this version and I have not tested on Tiger yet. If you do test it and it does work (or fails miserably), please drop a note in the comments.
Cocoa is cool and Objective-C is a great language, but I like/prefer Python and the PyObjC bridge makes my life easier and programming actually interesting/fun for me.
This Xcode project is an example of how easy it is to create useful custom views in PyObjC with an example of a graph view that displays a circular queue/buffer. Everything is done starting with an Xcode project which is available for download (76KB compressed archive) and modification. Here is a preview of what you can use out of the box:


The easiest and smallest part of the project is the RingBuffer class that implements a very simple circular queue/buffer and provides direct access to the list that stores the information:
# # RingBuffer.py class RingBuffer: def __init__(self, size): """ init with # of elements in the queue """ self.data = [ None for i in xrange(size) ] def append(self, x): """ take away one and put one in """ self.data.pop(0) self.data.append(x) def get(self): """ return the list so we can manipulate it """ return self.data
There's not a lot of rocket science there, but it's amazing how much code you can eliminate by taking advantage of Python's inherent capabilities. In this case, list initialization is a breeze and removal/insertion of new elements could not be easier.
Next up is the CBGraphView class itself:
| Location: | Berwick, ME, US |
| Updated: | 08 Mar 04:15 EST |
| Temp: | |
| Pressure: | |
| Dewpoint: | |
| Humidity: | 42% |
| Wind: | |
| Gusts: |