diff --git a/Classes/AttendeeListViewController.h b/Classes/AttendeeListViewController.h index 444077a..a7b4f3a 100644 --- a/Classes/AttendeeListViewController.h +++ b/Classes/AttendeeListViewController.h @@ -8,15 +8,21 @@ #import +extern NSString *AppUserRegistrantIDKey; @interface AttendeeListViewController : UITableViewController { NSMutableArray *attendees; NSDictionary *dictRegistrant; NSMutableData *responseData; UIImage *presenterIcon; + UIActivityIndicatorView *progressInd; } @property (nonatomic, retain) NSDictionary *dictRegistrant; +@property (nonatomic, retain) UIActivityIndicatorView *progressInd; @property (nonatomic, retain) NSMutableData *responseData; @property (nonatomic, retain) NSMutableArray *attendees; + + + @end diff --git a/Classes/AttendeeListViewController.m b/Classes/AttendeeListViewController.m index fb8061e..0c43367 100644 --- a/Classes/AttendeeListViewController.m +++ b/Classes/AttendeeListViewController.m @@ -11,21 +11,43 @@ #import #import "JSON.h" + + @implementation AttendeeListViewController -@synthesize attendees, responseData, dictRegistrant; +@synthesize attendees, responseData, dictRegistrant, progressInd; #pragma mark - #pragma mark Initialization -/* -- (id)initWithStyle:(UITableViewStyle)style { - // Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad. - if ((self = [super initWithStyle:style])) { - } - return self; +-(id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle { + if (self = [super initWithNibName:nibName bundle:bundle]){ + self.title = @"Hi! And you are...?"; + UIImage* image = [UIImage imageNamed:@"group.png"]; + self.tabBarItem = [[[UITabBarItem alloc] initWithTitle:@"People" image:image tag:0] autorelease]; + UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Not you?" style:UIBarButtonItemStylePlain target:nil action:nil]; + self.navigationItem.backBarButtonItem = backButton; + [backButton release]; + } + return self; } -*/ +- (UIActivityIndicatorView *)progressInd { + if (progressInd == nil) + { + CGRect frame = CGRectMake(self.view.frame.size.width/2-15, self.view.frame.size.height/2-15, 30, 30); + progressInd = [[UIActivityIndicatorView alloc] initWithFrame:frame]; + [progressInd startAnimating]; + progressInd.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray; + [progressInd sizeToFit]; + progressInd.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | + UIViewAutoresizingFlexibleRightMargin | + UIViewAutoresizingFlexibleTopMargin | + UIViewAutoresizingFlexibleBottomMargin); + + progressInd.tag = 1; // tag this view for later so we can remove it from recycled table cells + } + return progressInd; +} #pragma mark - #pragma mark View lifecycle @@ -44,9 +66,12 @@ - (void)viewDidLoad { // fields with URLs that will be visited when the row is selected //Initialize the array. - responseData = [[NSMutableData data] retain]; - NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://cocoa:camp@cocoacamp.org/registers/json?user_name=cocoa&password=camp"]]; - [[NSURLConnection alloc] initWithRequest:request delegate:self ]; + if (responseData == nil){ + responseData = [[NSMutableData data] retain]; + NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://cocoa:camp@cocoacamp.org/registers/json?user_name=cocoa&password=camp"]]; + [[NSURLConnection alloc] initWithRequest:request delegate:self ]; + [self.view addSubview: self.progressInd]; + } presenterIcon = [UIImage imageNamed:@"keynote-icon.png"]; [self.tableView reloadData]; // Uncomment the following line to display an Edit button in the navigation bar for this view controller. @@ -55,36 +80,11 @@ - (void)viewDidLoad { -- (void)viewWillAppear:(BOOL)animated { +- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - //Set the title - self.navigationItem.title = @"CocoaCamp Attendees"; [self.tableView reloadData]; } -/* -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; -} -*/ -/* -- (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; -} -*/ -/* -- (void)viewDidDisappear:(BOOL)animated { - [super viewDidDisappear:animated]; -} -*/ -/* -// Override to allow orientations other than the default portrait orientation. -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { - // Return YES for supported orientations - return (interfaceOrientation == UIInterfaceOrientationPortrait); -} -*/ - #pragma mark - #pragma mark WebService - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { @@ -101,7 +101,7 @@ - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)err - (void)connectionDidFinishLoading:(NSURLConnection *)connection { //[connection release]; - + [self.progressInd removeFromSuperview]; NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; [responseData release]; @@ -145,8 +145,6 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)connection { } - - #pragma mark - #pragma mark Table view data source @@ -256,14 +254,17 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath reg.company = [currentReg objectForKey:@"company"]; reg.twitter = [currentReg objectForKey:@"twitter"]; reg.industry = [currentReg objectForKey:@"industry"]; + reg.email = [currentReg objectForKey:@"email"]; + reg.rid = [NSNumber numberWithInt:[[currentReg objectForKey:@"id"] integerValue]]; NSLog(@"Attendee selected: %@ %@", reg.firstName, reg.lastName); detailViewController.currRegistrant = reg; - // Pass the selected object to the new view controller. - [self.navigationController pushViewController:detailViewController animated:YES]; - [detailViewController release]; + // Pass the selected object to the new view controller. + [self.navigationController pushViewController:detailViewController animated:YES]; + [detailViewController release]; + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; } @@ -287,9 +288,13 @@ - (void)dealloc { [responseData release]; [dictRegistrant release]; [attendees release]; + [progressInd release]; [super dealloc]; } +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{ + return YES; +} @end diff --git a/Classes/CocoaCampAppDelegate.m b/Classes/CocoaCampAppDelegate.m index 2bde8d0..9f95535 100644 --- a/Classes/CocoaCampAppDelegate.m +++ b/Classes/CocoaCampAppDelegate.m @@ -10,7 +10,8 @@ #import "ContactManager.h" #import "SessionViewController.h" #import "FlickrThumbnailView.h" -#import "ContactExchangeViewController.h" +#import "AttendeeListViewController.h" +#import "TwitterFeedTableViewController.h" #import "TabController.h" @implementation CocoaCampAppDelegate @@ -28,7 +29,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( [map from:@"tt://tabs" toViewController:[TabController class]]; [map from:@"tt://schedule" toViewController:[SessionViewController class]]; [map from:@"tt://flickr" toViewController:[FlickrThumbnailView class]]; - [map from:@"tt://people" toViewController:[ContactExchangeViewController class]]; + [map from:@"tt://people" toViewController:[AttendeeListViewController class]]; + [map from:@"tt://twitter" toViewController:[TwitterFeedTableViewController class]]; //if (![navigator restoreViewControllers]) { [navigator openURLAction:[TTURLAction actionWithURLPath:@"tt://tabs"]]; diff --git a/Classes/ContactExchangeViewController.h b/Classes/ContactExchangeViewController.h deleted file mode 100644 index d980850..0000000 --- a/Classes/ContactExchangeViewController.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// FirstViewController.h -// CocoaCamp -// -// Created by Jonathan Freeman on 7/12/10. -// Copyright __MyCompanyName__ 2010. All rights reserved. -// - -#import -#import - -@interface ContactExchangeViewController : UIViewController { - ABRecordRef ownerContact; -} - -- (IBAction)initiateContactExchange:(id)sender; -- (void)performContactExchange; - -@end diff --git a/Classes/ContactExchangeViewController.m b/Classes/ContactExchangeViewController.m deleted file mode 100644 index 2d8e7f1..0000000 --- a/Classes/ContactExchangeViewController.m +++ /dev/null @@ -1,90 +0,0 @@ -// -// FirstViewController.m -// CocoaCamp -// -// Created by Jonathan Freeman on 7/12/10. -// Copyright __MyCompanyName__ 2010. All rights reserved. -// - -#import "ContactExchangeViewController.h" -#import "CocoaCampAppDelegate.h" -#import "ContactManager.h" - -@implementation ContactExchangeViewController - -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - if ((self = [super initWithNibName:@"ContactExchangeView" bundle:nibBundleOrNil])) { - self.title = @"Contacts"; - UIImage* image = [UIImage imageNamed:@"group.png"]; - self.tabBarItem = [[[UITabBarItem alloc] initWithTitle:self.title image:image tag:0] autorelease]; - } - return self; -} - -- (void)viewDidLoad { - [super viewDidLoad]; -} - -- (void)viewWillAppear:(BOOL)animated { - [self.navigationController setNavigationBarHidden:YES animated:NO]; -} - -- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{ - return YES; -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -- (void)viewDidUnload { -} - -- (void)dealloc { - [super dealloc]; -} - -- (IBAction)initiateContactExchange:(id)sender { - if(ownerContact) - { - [self performContactExchange]; - } - else - { - ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init]; - picker.peoplePickerDelegate = self; - [self presentModalViewController:picker animated:YES]; - [picker release]; - } -} - -- (void)performContactExchange { - BumpContact *bumpContact = BumpContactForAddressBookRecord(ownerContact); - Bump *bump = [(CocoaCampAppDelegate *)[[UIApplication sharedApplication] delegate] bump]; - [bump configParentView:self.view]; - [bump connectToDoContactExchange:bumpContact]; -} - -- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker -{ - [self dismissModalViewControllerAnimated:YES]; -} - -- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker - shouldContinueAfterSelectingPerson:(ABRecordRef)person -{ - ownerContact = CFRetain(person); - [self dismissModalViewControllerAnimated:YES]; - [self performContactExchange]; - return NO; -} - -- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker - shouldContinueAfterSelectingPerson:(ABRecordRef)person - property:(ABPropertyID)property - identifier:(ABMultiValueIdentifier)identifier -{ - return NO; -} - -@end diff --git a/Classes/ContactManager.h b/Classes/ContactManager.h index 8a992d9..5f7dcdb 100644 --- a/Classes/ContactManager.h +++ b/Classes/ContactManager.h @@ -9,6 +9,7 @@ #import #import #import "BumpContact.h" +#import "Registrant.h" @interface ContactManager : NSObject { ABAddressBookRef addressBook; @@ -16,7 +17,7 @@ + (ContactManager *)sharedInstance; - (NSError *)addContactForBumpContact:(BumpContact *)contact; - +- (BumpContact *)bumpContactForRegistrant:(Registrant *)registrant; @end @interface BumpContact (AddressBook) diff --git a/Classes/ContactManager.m b/Classes/ContactManager.m index 6ad9009..7465c4a 100644 --- a/Classes/ContactManager.m +++ b/Classes/ContactManager.m @@ -8,6 +8,7 @@ #import "ContactManager.h" #import "BumpContact.h" +#import "Registrant.h" static ContactManager *sharedInstance; @@ -38,6 +39,22 @@ - (NSError *)addContactForBumpContact:(BumpContact *)contact { return (NSError *)error; } +- (BumpContact *)bumpContactForRegistrant:(Registrant *)registrant +{ + if(!registrant) + { + NSLog(@"Received nil registration in bumpContactForRegistrant - for shame!"); + return nil; + } + + BumpContact *contact = [[BumpContact alloc] init]; + contact.firstName = registrant.firstName; + contact.lastName = registrant.lastName; + contact.companyName = registrant.company; + + return [contact autorelease]; +} + @end @implementation BumpContact (AddressBook) diff --git a/Classes/NSString+XMLEntities.h b/Classes/NSString+XMLEntities.h new file mode 100644 index 0000000..c124e8c --- /dev/null +++ b/Classes/NSString+XMLEntities.h @@ -0,0 +1,20 @@ +// +// NSString+XMLEntities.h +// MWFeedParser +// +// Created by Michael Waterfall on 11/05/2010. +// Copyright 2010 d3i. All rights reserved. +// + +#import + +@interface NSString (XMLEntities) + +// Instance Methods +- (NSString *)stringByStrippingTags; +- (NSString *)stringByDecodingXMLEntities; +- (NSString *)stringByEncodingXMLEntities; +- (NSString *)stringWithNewLinesAsBRs; +- (NSString *)stringByRemovingNewLinesAndWhitespace; + +@end diff --git a/Classes/NSString+XMLEntities.m b/Classes/NSString+XMLEntities.m new file mode 100644 index 0000000..f9dee2a --- /dev/null +++ b/Classes/NSString+XMLEntities.m @@ -0,0 +1,814 @@ +// +// NSString+XMLEntities.m +// MWFeedParser +// +// Created by Michael Waterfall on 11/05/2010. +// Copyright 2010 d3i. All rights reserved. +// + +#import "NSString+XMLEntities.h" + +@implementation NSString (XMLEntities) + +#pragma mark - +#pragma mark Class Methods + +#pragma mark - +#pragma mark Instance Methods + +// Partially adapted and extended from examples at: +// http://stackoverflow.com/questions/1105169/html-character-decoding-in-objective-c-cocoa-touch +- (NSString *)stringByDecodingXMLEntities { + + // Find first & and short-cut if we can + NSUInteger ampIndex = [self rangeOfString:@"&" options:NSLiteralSearch].location; + if (ampIndex == NSNotFound) { + return [NSString stringWithString:self]; // return copy of string as no & found + } + + // Make result string with some extra capacity. + NSMutableString *result = [[NSMutableString alloc] initWithCapacity:(self.length * 1.25)]; + + // First iteration doesn't need to scan to & since we did that already, but for code simplicity's sake we'll do it again with the scanner. + NSScanner *scanner = [NSScanner scannerWithString:self]; + [scanner setCharactersToBeSkipped:nil]; + [scanner setCaseSensitive:YES]; + + // Boundary characters for scanning unexpected &#... pattern + NSCharacterSet *boundaryCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@" \t\n\r;"]; + + // Scan + do { + + // Scan up to the next entity or the end of the string. + NSString *nonEntityString; + if ([scanner scanUpToString:@"&" intoString:&nonEntityString]) { + [result appendString:nonEntityString]; + } + if ([scanner isAtEnd]) break; + + // Common character entity references first + if ([scanner scanString:@"&" intoString:NULL]) + [result appendString:@"&"]; + else if ([scanner scanString:@"'" intoString:NULL]) + [result appendString:@"'"]; + else if ([scanner scanString:@""" intoString:NULL]) + [result appendString:@"\""]; + else if ([scanner scanString:@"<" intoString:NULL]) + [result appendString:@"<"]; + else if ([scanner scanString:@">" intoString:NULL]) + [result appendString:@">"]; + else if ([scanner scanString:@" " intoString:NULL]) + [result appendFormat:@"%C", 160]; + else if ([scanner scanString:@"«" intoString:NULL]) + [result appendFormat:@"%C", 171]; + else if ([scanner scanString:@"»" intoString:NULL]) + [result appendFormat:@"%C", 187]; + else if ([scanner scanString:@"–" intoString:NULL]) + [result appendFormat:@"%C", 8211]; + else if ([scanner scanString:@"—" intoString:NULL]) + [result appendFormat:@"%C", 8212]; + else if ([scanner scanString:@"‘" intoString:NULL]) + [result appendFormat:@"%C", 8216]; + else if ([scanner scanString:@"’" intoString:NULL]) + [result appendFormat:@"%C", 8217]; + else if ([scanner scanString:@"“" intoString:NULL]) + [result appendFormat:@"%C", 8220]; + else if ([scanner scanString:@"”" intoString:NULL]) + [result appendFormat:@"%C", 8221]; + else if ([scanner scanString:@"•" intoString:NULL]) + [result appendFormat:@"%C", 8226]; + else if ([scanner scanString:@"…" intoString:NULL]) + [result appendFormat:@"%C", 8230]; + + // Numeric character entity references + else if ([scanner scanString:@"&#" intoString:NULL]) { + + // Entity + BOOL gotNumber; + unsigned charCode; + NSString *xForHex = @""; + + // Is it hex or decimal? + if ([scanner scanString:@"x" intoString:&xForHex]) { + gotNumber = [scanner scanHexInt:&charCode]; + } else { + gotNumber = [scanner scanInt:(int*)&charCode]; + } + + // Process + if (gotNumber) { + + // Append character + [result appendFormat:@"%C", charCode]; + [scanner scanString:@";" intoString:NULL]; + + } else { + + // Failed to get a number so append to result and log error + NSString *unknownEntity = @""; + [scanner scanUpToCharactersFromSet:boundaryCharacterSet intoString:&unknownEntity]; + [result appendFormat:@"&#%@%@", xForHex, unknownEntity]; // Append exact same string + + } + + // Quick check for isolated & with a space after to speed up checks + } else if ([scanner scanString:@"& " intoString:NULL]) + [result appendString:@"& "]; + + // No so common character entity references + else if ([scanner scanString:@"¡" intoString:NULL]) + [result appendFormat:@"%C", 161]; + else if ([scanner scanString:@"¢" intoString:NULL]) + [result appendFormat:@"%C", 162]; + else if ([scanner scanString:@"£" intoString:NULL]) + [result appendFormat:@"%C", 163]; + else if ([scanner scanString:@"¤" intoString:NULL]) + [result appendFormat:@"%C", 164]; + else if ([scanner scanString:@"¥" intoString:NULL]) + [result appendFormat:@"%C", 165]; + else if ([scanner scanString:@"¦" intoString:NULL]) + [result appendFormat:@"%C", 166]; + else if ([scanner scanString:@"§" intoString:NULL]) + [result appendFormat:@"%C", 167]; + else if ([scanner scanString:@"¨" intoString:NULL]) + [result appendFormat:@"%C", 168]; + else if ([scanner scanString:@"©" intoString:NULL]) + [result appendFormat:@"%C", 169]; + else if ([scanner scanString:@"ª" intoString:NULL]) + [result appendFormat:@"%C", 170]; + else if ([scanner scanString:@"¬" intoString:NULL]) + [result appendFormat:@"%C", 172]; + else if ([scanner scanString:@"­" intoString:NULL]) + [result appendFormat:@"%C", 173]; + else if ([scanner scanString:@"®" intoString:NULL]) + [result appendFormat:@"%C", 174]; + else if ([scanner scanString:@"¯" intoString:NULL]) + [result appendFormat:@"%C", 175]; + else if ([scanner scanString:@"°" intoString:NULL]) + [result appendFormat:@"%C", 176]; + else if ([scanner scanString:@"±" intoString:NULL]) + [result appendFormat:@"%C", 177]; + else if ([scanner scanString:@"²" intoString:NULL]) + [result appendFormat:@"%C", 178]; + else if ([scanner scanString:@"³" intoString:NULL]) + [result appendFormat:@"%C", 179]; + else if ([scanner scanString:@"´" intoString:NULL]) + [result appendFormat:@"%C", 180]; + else if ([scanner scanString:@"µ" intoString:NULL]) + [result appendFormat:@"%C", 181]; + else if ([scanner scanString:@"¶" intoString:NULL]) + [result appendFormat:@"%C", 182]; + else if ([scanner scanString:@"·" intoString:NULL]) + [result appendFormat:@"%C", 183]; + else if ([scanner scanString:@"¸" intoString:NULL]) + [result appendFormat:@"%C", 184]; + else if ([scanner scanString:@"¹" intoString:NULL]) + [result appendFormat:@"%C", 185]; + else if ([scanner scanString:@"º" intoString:NULL]) + [result appendFormat:@"%C", 186]; + else if ([scanner scanString:@"¼" intoString:NULL]) + [result appendFormat:@"%C", 188]; + else if ([scanner scanString:@"½" intoString:NULL]) + [result appendFormat:@"%C", 189]; + else if ([scanner scanString:@"¾" intoString:NULL]) + [result appendFormat:@"%C", 190]; + else if ([scanner scanString:@"¿" intoString:NULL]) + [result appendFormat:@"%C", 191]; + else if ([scanner scanString:@"À" intoString:NULL]) + [result appendFormat:@"%C", 192]; + else if ([scanner scanString:@"Á" intoString:NULL]) + [result appendFormat:@"%C", 193]; + else if ([scanner scanString:@"Â" intoString:NULL]) + [result appendFormat:@"%C", 194]; + else if ([scanner scanString:@"Ã" intoString:NULL]) + [result appendFormat:@"%C", 195]; + else if ([scanner scanString:@"Ä" intoString:NULL]) + [result appendFormat:@"%C", 196]; + else if ([scanner scanString:@"Å" intoString:NULL]) + [result appendFormat:@"%C", 197]; + else if ([scanner scanString:@"Æ" intoString:NULL]) + [result appendFormat:@"%C", 198]; + else if ([scanner scanString:@"Ç" intoString:NULL]) + [result appendFormat:@"%C", 199]; + else if ([scanner scanString:@"È" intoString:NULL]) + [result appendFormat:@"%C", 200]; + else if ([scanner scanString:@"É" intoString:NULL]) + [result appendFormat:@"%C", 201]; + else if ([scanner scanString:@"Ê" intoString:NULL]) + [result appendFormat:@"%C", 202]; + else if ([scanner scanString:@"Ë" intoString:NULL]) + [result appendFormat:@"%C", 203]; + else if ([scanner scanString:@"Ì" intoString:NULL]) + [result appendFormat:@"%C", 204]; + else if ([scanner scanString:@"Í" intoString:NULL]) + [result appendFormat:@"%C", 205]; + else if ([scanner scanString:@"Î" intoString:NULL]) + [result appendFormat:@"%C", 206]; + else if ([scanner scanString:@"Ï" intoString:NULL]) + [result appendFormat:@"%C", 207]; + else if ([scanner scanString:@"Ð" intoString:NULL]) + [result appendFormat:@"%C", 208]; + else if ([scanner scanString:@"Ñ" intoString:NULL]) + [result appendFormat:@"%C", 209]; + else if ([scanner scanString:@"Ò" intoString:NULL]) + [result appendFormat:@"%C", 210]; + else if ([scanner scanString:@"Ó" intoString:NULL]) + [result appendFormat:@"%C", 211]; + else if ([scanner scanString:@"Ô" intoString:NULL]) + [result appendFormat:@"%C", 212]; + else if ([scanner scanString:@"Õ" intoString:NULL]) + [result appendFormat:@"%C", 213]; + else if ([scanner scanString:@"Ö" intoString:NULL]) + [result appendFormat:@"%C", 214]; + else if ([scanner scanString:@"×" intoString:NULL]) + [result appendFormat:@"%C", 215]; + else if ([scanner scanString:@"Ø" intoString:NULL]) + [result appendFormat:@"%C", 216]; + else if ([scanner scanString:@"Ù" intoString:NULL]) + [result appendFormat:@"%C", 217]; + else if ([scanner scanString:@"Ú" intoString:NULL]) + [result appendFormat:@"%C", 218]; + else if ([scanner scanString:@"Û" intoString:NULL]) + [result appendFormat:@"%C", 219]; + else if ([scanner scanString:@"Ü" intoString:NULL]) + [result appendFormat:@"%C", 220]; + else if ([scanner scanString:@"Ý" intoString:NULL]) + [result appendFormat:@"%C", 221]; + else if ([scanner scanString:@"Þ" intoString:NULL]) + [result appendFormat:@"%C", 222]; + else if ([scanner scanString:@"ß" intoString:NULL]) + [result appendFormat:@"%C", 223]; + else if ([scanner scanString:@"à" intoString:NULL]) + [result appendFormat:@"%C", 224]; + else if ([scanner scanString:@"á" intoString:NULL]) + [result appendFormat:@"%C", 225]; + else if ([scanner scanString:@"â" intoString:NULL]) + [result appendFormat:@"%C", 226]; + else if ([scanner scanString:@"ã" intoString:NULL]) + [result appendFormat:@"%C", 227]; + else if ([scanner scanString:@"ä" intoString:NULL]) + [result appendFormat:@"%C", 228]; + else if ([scanner scanString:@"å" intoString:NULL]) + [result appendFormat:@"%C", 229]; + else if ([scanner scanString:@"æ" intoString:NULL]) + [result appendFormat:@"%C", 230]; + else if ([scanner scanString:@"ç" intoString:NULL]) + [result appendFormat:@"%C", 231]; + else if ([scanner scanString:@"è" intoString:NULL]) + [result appendFormat:@"%C", 232]; + else if ([scanner scanString:@"é" intoString:NULL]) + [result appendFormat:@"%C", 233]; + else if ([scanner scanString:@"ê" intoString:NULL]) + [result appendFormat:@"%C", 234]; + else if ([scanner scanString:@"ë" intoString:NULL]) + [result appendFormat:@"%C", 235]; + else if ([scanner scanString:@"ì" intoString:NULL]) + [result appendFormat:@"%C", 236]; + else if ([scanner scanString:@"í" intoString:NULL]) + [result appendFormat:@"%C", 237]; + else if ([scanner scanString:@"î" intoString:NULL]) + [result appendFormat:@"%C", 238]; + else if ([scanner scanString:@"ï" intoString:NULL]) + [result appendFormat:@"%C", 239]; + else if ([scanner scanString:@"ð" intoString:NULL]) + [result appendFormat:@"%C", 240]; + else if ([scanner scanString:@"ñ" intoString:NULL]) + [result appendFormat:@"%C", 241]; + else if ([scanner scanString:@"ò" intoString:NULL]) + [result appendFormat:@"%C", 242]; + else if ([scanner scanString:@"ó" intoString:NULL]) + [result appendFormat:@"%C", 243]; + else if ([scanner scanString:@"ô" intoString:NULL]) + [result appendFormat:@"%C", 244]; + else if ([scanner scanString:@"õ" intoString:NULL]) + [result appendFormat:@"%C", 245]; + else if ([scanner scanString:@"ö" intoString:NULL]) + [result appendFormat:@"%C", 246]; + else if ([scanner scanString:@"÷" intoString:NULL]) + [result appendFormat:@"%C", 247]; + else if ([scanner scanString:@"ø" intoString:NULL]) + [result appendFormat:@"%C", 248]; + else if ([scanner scanString:@"ù" intoString:NULL]) + [result appendFormat:@"%C", 249]; + else if ([scanner scanString:@"ú" intoString:NULL]) + [result appendFormat:@"%C", 250]; + else if ([scanner scanString:@"û" intoString:NULL]) + [result appendFormat:@"%C", 251]; + else if ([scanner scanString:@"ü" intoString:NULL]) + [result appendFormat:@"%C", 252]; + else if ([scanner scanString:@"ý" intoString:NULL]) + [result appendFormat:@"%C", 253]; + else if ([scanner scanString:@"þ" intoString:NULL]) + [result appendFormat:@"%C", 254]; + else if ([scanner scanString:@"ÿ" intoString:NULL]) + [result appendFormat:@"%C", 255]; + else if ([scanner scanString:@"Œ" intoString:NULL]) + [result appendFormat:@"%C", 338]; + else if ([scanner scanString:@"œ" intoString:NULL]) + [result appendFormat:@"%C", 339]; + else if ([scanner scanString:@"Š" intoString:NULL]) + [result appendFormat:@"%C", 352]; + else if ([scanner scanString:@"š" intoString:NULL]) + [result appendFormat:@"%C", 353]; + else if ([scanner scanString:@"Ÿ" intoString:NULL]) + [result appendFormat:@"%C", 376]; + else if ([scanner scanString:@"ƒ" intoString:NULL]) + [result appendFormat:@"%C", 402]; + else if ([scanner scanString:@"ˆ" intoString:NULL]) + [result appendFormat:@"%C", 710]; + else if ([scanner scanString:@"˜" intoString:NULL]) + [result appendFormat:@"%C", 732]; + else if ([scanner scanString:@"Α" intoString:NULL]) + [result appendFormat:@"%C", 913]; + else if ([scanner scanString:@"Β" intoString:NULL]) + [result appendFormat:@"%C", 914]; + else if ([scanner scanString:@"Γ" intoString:NULL]) + [result appendFormat:@"%C", 915]; + else if ([scanner scanString:@"Δ" intoString:NULL]) + [result appendFormat:@"%C", 916]; + else if ([scanner scanString:@"Ε" intoString:NULL]) + [result appendFormat:@"%C", 917]; + else if ([scanner scanString:@"Ζ" intoString:NULL]) + [result appendFormat:@"%C", 918]; + else if ([scanner scanString:@"Η" intoString:NULL]) + [result appendFormat:@"%C", 919]; + else if ([scanner scanString:@"Θ" intoString:NULL]) + [result appendFormat:@"%C", 920]; + else if ([scanner scanString:@"Ι" intoString:NULL]) + [result appendFormat:@"%C", 921]; + else if ([scanner scanString:@"Κ" intoString:NULL]) + [result appendFormat:@"%C", 922]; + else if ([scanner scanString:@"Λ" intoString:NULL]) + [result appendFormat:@"%C", 923]; + else if ([scanner scanString:@"Μ" intoString:NULL]) + [result appendFormat:@"%C", 924]; + else if ([scanner scanString:@"Ν" intoString:NULL]) + [result appendFormat:@"%C", 925]; + else if ([scanner scanString:@"Ξ" intoString:NULL]) + [result appendFormat:@"%C", 926]; + else if ([scanner scanString:@"Ο" intoString:NULL]) + [result appendFormat:@"%C", 927]; + else if ([scanner scanString:@"Π" intoString:NULL]) + [result appendFormat:@"%C", 928]; + else if ([scanner scanString:@"Ρ" intoString:NULL]) + [result appendFormat:@"%C", 929]; + else if ([scanner scanString:@"Σ" intoString:NULL]) + [result appendFormat:@"%C", 931]; + else if ([scanner scanString:@"Τ" intoString:NULL]) + [result appendFormat:@"%C", 932]; + else if ([scanner scanString:@"Υ" intoString:NULL]) + [result appendFormat:@"%C", 933]; + else if ([scanner scanString:@"Φ" intoString:NULL]) + [result appendFormat:@"%C", 934]; + else if ([scanner scanString:@"Χ" intoString:NULL]) + [result appendFormat:@"%C", 935]; + else if ([scanner scanString:@"Ψ" intoString:NULL]) + [result appendFormat:@"%C", 936]; + else if ([scanner scanString:@"Ω" intoString:NULL]) + [result appendFormat:@"%C", 937]; + else if ([scanner scanString:@"α" intoString:NULL]) + [result appendFormat:@"%C", 945]; + else if ([scanner scanString:@"β" intoString:NULL]) + [result appendFormat:@"%C", 946]; + else if ([scanner scanString:@"γ" intoString:NULL]) + [result appendFormat:@"%C", 947]; + else if ([scanner scanString:@"δ" intoString:NULL]) + [result appendFormat:@"%C", 948]; + else if ([scanner scanString:@"ε" intoString:NULL]) + [result appendFormat:@"%C", 949]; + else if ([scanner scanString:@"ζ" intoString:NULL]) + [result appendFormat:@"%C", 950]; + else if ([scanner scanString:@"η" intoString:NULL]) + [result appendFormat:@"%C", 951]; + else if ([scanner scanString:@"θ" intoString:NULL]) + [result appendFormat:@"%C", 952]; + else if ([scanner scanString:@"ι" intoString:NULL]) + [result appendFormat:@"%C", 953]; + else if ([scanner scanString:@"κ" intoString:NULL]) + [result appendFormat:@"%C", 954]; + else if ([scanner scanString:@"λ" intoString:NULL]) + [result appendFormat:@"%C", 955]; + else if ([scanner scanString:@"μ" intoString:NULL]) + [result appendFormat:@"%C", 956]; + else if ([scanner scanString:@"ν" intoString:NULL]) + [result appendFormat:@"%C", 957]; + else if ([scanner scanString:@"ξ" intoString:NULL]) + [result appendFormat:@"%C", 958]; + else if ([scanner scanString:@"ο" intoString:NULL]) + [result appendFormat:@"%C", 959]; + else if ([scanner scanString:@"π" intoString:NULL]) + [result appendFormat:@"%C", 960]; + else if ([scanner scanString:@"ρ" intoString:NULL]) + [result appendFormat:@"%C", 961]; + else if ([scanner scanString:@"ς" intoString:NULL]) + [result appendFormat:@"%C", 962]; + else if ([scanner scanString:@"σ" intoString:NULL]) + [result appendFormat:@"%C", 963]; + else if ([scanner scanString:@"τ" intoString:NULL]) + [result appendFormat:@"%C", 964]; + else if ([scanner scanString:@"υ" intoString:NULL]) + [result appendFormat:@"%C", 965]; + else if ([scanner scanString:@"φ" intoString:NULL]) + [result appendFormat:@"%C", 966]; + else if ([scanner scanString:@"χ" intoString:NULL]) + [result appendFormat:@"%C", 967]; + else if ([scanner scanString:@"ψ" intoString:NULL]) + [result appendFormat:@"%C", 968]; + else if ([scanner scanString:@"ω" intoString:NULL]) + [result appendFormat:@"%C", 969]; + else if ([scanner scanString:@"ϑ" intoString:NULL]) + [result appendFormat:@"%C", 977]; + else if ([scanner scanString:@"ϒ" intoString:NULL]) + [result appendFormat:@"%C", 978]; + else if ([scanner scanString:@"ϖ" intoString:NULL]) + [result appendFormat:@"%C", 982]; + else if ([scanner scanString:@" " intoString:NULL]) + [result appendFormat:@"%C", 8194]; + else if ([scanner scanString:@" " intoString:NULL]) + [result appendFormat:@"%C", 8195]; + else if ([scanner scanString:@" " intoString:NULL]) + [result appendFormat:@"%C", 8201]; + else if ([scanner scanString:@"‌" intoString:NULL]) + [result appendFormat:@"%C", 8204]; + else if ([scanner scanString:@"‍" intoString:NULL]) + [result appendFormat:@"%C", 8205]; + else if ([scanner scanString:@"‎" intoString:NULL]) + [result appendFormat:@"%C", 8206]; + else if ([scanner scanString:@"‏" intoString:NULL]) + [result appendFormat:@"%C", 8207]; + else if ([scanner scanString:@"‚" intoString:NULL]) + [result appendFormat:@"%C", 8218]; + else if ([scanner scanString:@"„" intoString:NULL]) + [result appendFormat:@"%C", 8222]; + else if ([scanner scanString:@"†" intoString:NULL]) + [result appendFormat:@"%C", 8224]; + else if ([scanner scanString:@"‡" intoString:NULL]) + [result appendFormat:@"%C", 8225]; + else if ([scanner scanString:@"‰" intoString:NULL]) + [result appendFormat:@"%C", 8240]; + else if ([scanner scanString:@"′" intoString:NULL]) + [result appendFormat:@"%C", 8242]; + else if ([scanner scanString:@"″" intoString:NULL]) + [result appendFormat:@"%C", 8243]; + else if ([scanner scanString:@"‹" intoString:NULL]) + [result appendFormat:@"%C", 8249]; + else if ([scanner scanString:@"›" intoString:NULL]) + [result appendFormat:@"%C", 8250]; + else if ([scanner scanString:@"‾" intoString:NULL]) + [result appendFormat:@"%C", 8254]; + else if ([scanner scanString:@"⁄" intoString:NULL]) + [result appendFormat:@"%C", 8260]; + else if ([scanner scanString:@"€" intoString:NULL]) + [result appendFormat:@"%C", 8364]; + else if ([scanner scanString:@"ℑ" intoString:NULL]) + [result appendFormat:@"%C", 8465]; + else if ([scanner scanString:@"℘" intoString:NULL]) + [result appendFormat:@"%C", 8472]; + else if ([scanner scanString:@"ℜ" intoString:NULL]) + [result appendFormat:@"%C", 8476]; + else if ([scanner scanString:@"™" intoString:NULL]) + [result appendFormat:@"%C", 8482]; + else if ([scanner scanString:@"ℵ" intoString:NULL]) + [result appendFormat:@"%C", 8501]; + else if ([scanner scanString:@"←" intoString:NULL]) + [result appendFormat:@"%C", 8592]; + else if ([scanner scanString:@"↑" intoString:NULL]) + [result appendFormat:@"%C", 8593]; + else if ([scanner scanString:@"→" intoString:NULL]) + [result appendFormat:@"%C", 8594]; + else if ([scanner scanString:@"↓" intoString:NULL]) + [result appendFormat:@"%C", 8595]; + else if ([scanner scanString:@"↔" intoString:NULL]) + [result appendFormat:@"%C", 8596]; + else if ([scanner scanString:@"↵" intoString:NULL]) + [result appendFormat:@"%C", 8629]; + else if ([scanner scanString:@"⇐" intoString:NULL]) + [result appendFormat:@"%C", 8656]; + else if ([scanner scanString:@"⇑" intoString:NULL]) + [result appendFormat:@"%C", 8657]; + else if ([scanner scanString:@"⇒" intoString:NULL]) + [result appendFormat:@"%C", 8658]; + else if ([scanner scanString:@"⇓" intoString:NULL]) + [result appendFormat:@"%C", 8659]; + else if ([scanner scanString:@"⇔" intoString:NULL]) + [result appendFormat:@"%C", 8660]; + else if ([scanner scanString:@"∀" intoString:NULL]) + [result appendFormat:@"%C", 8704]; + else if ([scanner scanString:@"∂" intoString:NULL]) + [result appendFormat:@"%C", 8706]; + else if ([scanner scanString:@"∃" intoString:NULL]) + [result appendFormat:@"%C", 8707]; + else if ([scanner scanString:@"∅" intoString:NULL]) + [result appendFormat:@"%C", 8709]; + else if ([scanner scanString:@"∇" intoString:NULL]) + [result appendFormat:@"%C", 8711]; + else if ([scanner scanString:@"∈" intoString:NULL]) + [result appendFormat:@"%C", 8712]; + else if ([scanner scanString:@"∉" intoString:NULL]) + [result appendFormat:@"%C", 8713]; + else if ([scanner scanString:@"∋" intoString:NULL]) + [result appendFormat:@"%C", 8715]; + else if ([scanner scanString:@"∏" intoString:NULL]) + [result appendFormat:@"%C", 8719]; + else if ([scanner scanString:@"∑" intoString:NULL]) + [result appendFormat:@"%C", 8721]; + else if ([scanner scanString:@"−" intoString:NULL]) + [result appendFormat:@"%C", 8722]; + else if ([scanner scanString:@"∗" intoString:NULL]) + [result appendFormat:@"%C", 8727]; + else if ([scanner scanString:@"√" intoString:NULL]) + [result appendFormat:@"%C", 8730]; + else if ([scanner scanString:@"∝" intoString:NULL]) + [result appendFormat:@"%C", 8733]; + else if ([scanner scanString:@"∞" intoString:NULL]) + [result appendFormat:@"%C", 8734]; + else if ([scanner scanString:@"∠" intoString:NULL]) + [result appendFormat:@"%C", 8736]; + else if ([scanner scanString:@"∧" intoString:NULL]) + [result appendFormat:@"%C", 8743]; + else if ([scanner scanString:@"∨" intoString:NULL]) + [result appendFormat:@"%C", 8744]; + else if ([scanner scanString:@"∩" intoString:NULL]) + [result appendFormat:@"%C", 8745]; + else if ([scanner scanString:@"∪" intoString:NULL]) + [result appendFormat:@"%C", 8746]; + else if ([scanner scanString:@"∫" intoString:NULL]) + [result appendFormat:@"%C", 8747]; + else if ([scanner scanString:@"∴" intoString:NULL]) + [result appendFormat:@"%C", 8756]; + else if ([scanner scanString:@"∼" intoString:NULL]) + [result appendFormat:@"%C", 8764]; + else if ([scanner scanString:@"≅" intoString:NULL]) + [result appendFormat:@"%C", 8773]; + else if ([scanner scanString:@"≈" intoString:NULL]) + [result appendFormat:@"%C", 8776]; + else if ([scanner scanString:@"≠" intoString:NULL]) + [result appendFormat:@"%C", 8800]; + else if ([scanner scanString:@"≡" intoString:NULL]) + [result appendFormat:@"%C", 8801]; + else if ([scanner scanString:@"≤" intoString:NULL]) + [result appendFormat:@"%C", 8804]; + else if ([scanner scanString:@"≥" intoString:NULL]) + [result appendFormat:@"%C", 8805]; + else if ([scanner scanString:@"⊂" intoString:NULL]) + [result appendFormat:@"%C", 8834]; + else if ([scanner scanString:@"⊃" intoString:NULL]) + [result appendFormat:@"%C", 8835]; + else if ([scanner scanString:@"⊄" intoString:NULL]) + [result appendFormat:@"%C", 8836]; + else if ([scanner scanString:@"⊆" intoString:NULL]) + [result appendFormat:@"%C", 8838]; + else if ([scanner scanString:@"⊇" intoString:NULL]) + [result appendFormat:@"%C", 8839]; + else if ([scanner scanString:@"⊕" intoString:NULL]) + [result appendFormat:@"%C", 8853]; + else if ([scanner scanString:@"⊗" intoString:NULL]) + [result appendFormat:@"%C", 8855]; + else if ([scanner scanString:@"⊥" intoString:NULL]) + [result appendFormat:@"%C", 8869]; + else if ([scanner scanString:@"⋅" intoString:NULL]) + [result appendFormat:@"%C", 8901]; + else if ([scanner scanString:@"⌈" intoString:NULL]) + [result appendFormat:@"%C", 8968]; + else if ([scanner scanString:@"⌉" intoString:NULL]) + [result appendFormat:@"%C", 8969]; + else if ([scanner scanString:@"⌊" intoString:NULL]) + [result appendFormat:@"%C", 8970]; + else if ([scanner scanString:@"⌋" intoString:NULL]) + [result appendFormat:@"%C", 8971]; + else if ([scanner scanString:@"⟨" intoString:NULL]) + [result appendFormat:@"%C", 9001]; + else if ([scanner scanString:@"⟩" intoString:NULL]) + [result appendFormat:@"%C", 9002]; + else if ([scanner scanString:@"◊" intoString:NULL]) + [result appendFormat:@"%C", 9674]; + else if ([scanner scanString:@"♠" intoString:NULL]) + [result appendFormat:@"%C", 9824]; + else if ([scanner scanString:@"♣" intoString:NULL]) + [result appendFormat:@"%C", 9827]; + else if ([scanner scanString:@"♥" intoString:NULL]) + [result appendFormat:@"%C", 9829]; + else if ([scanner scanString:@"♦" intoString:NULL]) + [result appendFormat:@"%C", 9830]; + else { + + // Must be an isolated & with no space after + NSString *amp; + [scanner scanString:@"&" intoString:&]; // isolated & symbol + [result appendString:amp]; + + } + + } while (![scanner isAtEnd]); + + // Finish + NSString *resultingString = [NSString stringWithString:result]; + [result release]; + return resultingString; + +} + +// Needs more work to encode more entities +- (NSString *)stringByEncodingXMLEntities { + + // Scanner + NSScanner *scanner = [[NSScanner alloc] initWithString:self]; + [scanner setCharactersToBeSkipped:nil]; + NSMutableString *result = [[NSMutableString alloc] init]; + NSString *temp; + NSCharacterSet *characters = [NSCharacterSet characterSetWithCharactersInString:@"&\"'<>"]; + [scanner setCharactersToBeSkipped:nil]; + + // Scan + while (![scanner isAtEnd]) { + + // Get non new line or whitespace characters + temp = nil; + [scanner scanUpToCharactersFromSet:characters intoString:&temp]; + if (temp) [result appendString:temp]; + + // Replace with encoded entities + if ([scanner scanString:@"&" intoString:NULL]) + [result appendString:@"&"]; + else if ([scanner scanString:@"'" intoString:NULL]) + [result appendString:@"'"]; + else if ([scanner scanString:@"\"" intoString:NULL]) + [result appendString:@"""]; + else if ([scanner scanString:@"<" intoString:NULL]) + [result appendString:@"<"]; + else if ([scanner scanString:@">" intoString:NULL]) + [result appendString:@">"]; + + } + + // Cleanup + [scanner release]; + + // Return + NSString *retString = [NSString stringWithString:result]; + [result release]; + return retString; + +} + +- (NSString *)stringByStrippingTags { + + // Find first & and short-cut if we can + NSUInteger ampIndex = [self rangeOfString:@"<" options:NSLiteralSearch].location; + if (ampIndex == NSNotFound) { + return [NSString stringWithString:self]; // return copy of string as no tags found + } + + // Scan and find all tags + NSScanner *scanner = [NSScanner scannerWithString:self]; + [scanner setCharactersToBeSkipped:nil]; + NSMutableSet *tags = [[NSMutableSet alloc] init]; + NSString *tag; + do { + + // Scan up to < + tag = nil; + [scanner scanUpToString:@"<" intoString:NULL]; + [scanner scanUpToString:@">" intoString:&tag]; + + // Add to set + if (tag) { + NSString *t = [[NSString alloc] initWithFormat:@"%@>", tag]; + [tags addObject:t]; + [t release]; + } + + } while (![scanner isAtEnd]); + + // Strings + NSMutableString *result = [[NSMutableString alloc] initWithString:self]; + NSString *finalString; + + // Replace tags + NSString *replacement; + for (NSString *t in tags) { + + // Replace tag with space unless it's an inline element + replacement = @" "; + if ([t isEqualToString:@""] || + [t isEqualToString:@""] || + [t isEqualToString:@""] || + [t isEqualToString:@""] || + [t isEqualToString:@""] || + [t isEqualToString:@""] || + [t isEqualToString:@""] || + [t isEqualToString:@""]) { + replacement = @""; + } + + // Replace + [result replaceOccurrencesOfString:t + withString:replacement + options:NSLiteralSearch + range:NSMakeRange(0, result.length)]; + } + + // Remove multi-spaces and line breaks + finalString = [result stringByRemovingNewLinesAndWhitespace]; + + // Cleanup & return + [result release]; + [tags release]; + return finalString; + +} + +- (NSString *)stringWithNewLinesAsBRs { + + // Strange New lines: + // Next Line, U+0085 + // Form Feed, U+000C + // Line Separator, U+2028 + // Paragraph Separator, U+2029 + + // Scanner + NSScanner *scanner = [[NSScanner alloc] initWithString:self]; + [scanner setCharactersToBeSkipped:nil]; + NSMutableString *result = [[NSMutableString alloc] init]; + NSString *temp; + NSCharacterSet *newLineCharacters = [NSCharacterSet characterSetWithCharactersInString: + [NSString stringWithFormat:@"\n\r%C%C%C%C", 0x0085, 0x000C, 0x2028, 0x2029]]; + // Scan + do { + + // Get non new line characters + temp = nil; + [scanner scanUpToCharactersFromSet:newLineCharacters intoString:&temp]; + if (temp) [result appendString:temp]; + temp = nil; + + // Add
s + if ([scanner scanString:@"\r\n" intoString:nil]) { + + // Combine \r\n into just 1
+ [result appendString:@"
"]; + + } else if ([scanner scanCharactersFromSet:newLineCharacters intoString:&temp]) { + + // Scan other new line characters and add
s + if (temp) { + for (int i = 0; i < temp.length; i++) { + [result appendString:@"
"]; + } + } + + } + + } while (![scanner isAtEnd]); + + // Cleanup & return + [scanner release]; + NSString *retString = [NSString stringWithString:result]; + [result release]; + return retString; + +} + +- (NSString *)stringByRemovingNewLinesAndWhitespace { + + // Strange New lines: + // Next Line, U+0085 + // Form Feed, U+000C + // Line Separator, U+2028 + // Paragraph Separator, U+2029 + + // Scanner + NSScanner *scanner = [[NSScanner alloc] initWithString:self]; + [scanner setCharactersToBeSkipped:nil]; + NSMutableString *result = [[NSMutableString alloc] init]; + NSString *temp; + NSCharacterSet *newLineAndWhitespaceCharacters = [NSCharacterSet characterSetWithCharactersInString: + [NSString stringWithFormat:@" \t\n\r%C%C%C%C", 0x0085, 0x000C, 0x2028, 0x2029]]; + // Scan + while (![scanner isAtEnd]) { + + // Get non new line or whitespace characters + temp = nil; + [scanner scanUpToCharactersFromSet:newLineAndWhitespaceCharacters intoString:&temp]; + if (temp) [result appendString:temp]; + + // Replace with a space + if ([scanner scanCharactersFromSet:newLineAndWhitespaceCharacters intoString:NULL]) { + if (result.length > 0 && ![scanner isAtEnd]) // Dont append space to beginning or end of result + [result appendString:@" "]; + } + + } + + // Cleanup + [scanner release]; + + // Return + NSString *retString = [NSString stringWithString:result]; + [result release]; + return retString; + +} + +@end diff --git a/Classes/RegistrantDetailView.xib b/Classes/RegistrantDetailView.xib index 3328e46..c37b5de 100644 --- a/Classes/RegistrantDetailView.xib +++ b/Classes/RegistrantDetailView.xib @@ -42,17 +42,17 @@ 292 YES - + 292 - {{33, 6}, {236, 36}} + {{111, 50}, {149, 21}} NO YES 7 NO IBCocoaTouchFramework - Attendee Name + 1 MCAwIDAAA @@ -60,150 +60,112 @@ 1 10 - 1 - - - - 292 - {{20, 50}, {83, 21}} - - NO - YES - 7 - NO - IBCocoaTouchFramework - Company: - - - 1 - 10 - - - - 292 - {{20, 79}, {71, 21}} - - NO - YES - 7 - NO - IBCocoaTouchFramework - Industry: - - - 1 - 10 - + 292 - {{20, 121}, {48, 21}} + {{20, 149}, {280, 110}} NO - YES - 7 - NO IBCocoaTouchFramework - Email: - - - 1 - 10 - - - - 292 - {{20, 156}, {56, 21}} - - NO - YES - 7 - NO - IBCocoaTouchFramework - Twitter: - - - 1 - 10 - - - - 292 - {{111, 50}, {149, 21}} - - NO - YES - 7 - NO - IBCocoaTouchFramework - - - - 1 - 10 + 0 + 0 + + Futura-CondensedExtraBold + 30 + 16 + + 1 + Bump'em! + + 3 + MQA + + + + 3 + MC41AA + + + NSImage + bump_lefthand.png + - + 292 - {{111, 73}, {173, 32}} + {{20, 79}, {280, 62}} NO YES 7 NO IBCocoaTouchFramework - < Industries > - + Made a new friend? + + Futura-Medium + 30 + 16 + + + 1 + MC41MDE5NjA4MTQgMCAwAA + 1 10 - + 292 - {{111, 121}, {173, 21}} + {{20, 270}, {280, 72}} - NO + + 1 + MSAxIDEAA + YES - 7 - NO + YES IBCocoaTouchFramework - < Email > - - - 1 - 10 + Use bump to exchange your contact with new friends. + + 3 + MC4zMzMzMzMzMzMzAA + + + 2 + IBCocoaTouchFramework + - + 292 - {{111, 156}, {173, 21}} + {{20, 20}, {280, 62}} NO YES 7 NO IBCocoaTouchFramework - < Twitter > - + Hi, John Joe! + + + 1 + MC41MDE5NjA4MTQgMCAwAA + 1 10 - {320, 416} + {320, 367} - - 3 - MQA - - 2 - - + NO + IBCocoaTouchFramework @@ -212,51 +174,28 @@ YES - emailLabel + view - + - 22 + 29 - - industryLabel - - + + initiateContactExchange: + + + 7 - 23 + 33 nameLabel - - - 24 - - - - twitterLabel - - - - 25 - - - - companyLabel - - + - 26 - - - - view - - - - 29 + 37 @@ -284,61 +223,37 @@ YES - - - - - - - - + + + + - 10 - - - - - 11 - - - - - 12 - - - - - 13 - - - - - 14 - + 16 + - 16 - + 30 + - 17 - + 34 + - 19 - + 32 + - 18 - + 36 + @@ -349,15 +264,11 @@ YES -1.CustomClassName -2.CustomClassName - 10.IBPluginDependency - 11.IBPluginDependency - 12.IBPluginDependency - 13.IBPluginDependency - 14.IBPluginDependency 16.IBPluginDependency - 17.IBPluginDependency - 18.IBPluginDependency - 19.IBPluginDependency + 30.IBPluginDependency + 32.IBPluginDependency + 34.IBPluginDependency + 36.IBPluginDependency 8.IBEditorWindowLastContentRect 8.IBPluginDependency @@ -370,11 +281,7 @@ com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - {{660, 408}, {320, 480}} + {{542, 40}, {320, 480}} com.apple.InterfaceBuilder.IBCocoaTouchPlugin @@ -394,7 +301,7 @@ - 29 + 37 @@ -416,59 +323,49 @@ RegistrantDetailViewController UIViewController - + YES YES - companyLabel - emailLabel - industryLabel - nameLabel - twitterLabel + initiateContactExchange: + storeCurrentProfileAsIdentity YES - UILabel - UILabel - UILabel - UILabel - UILabel + id + id - + YES YES - companyLabel - emailLabel - industryLabel - nameLabel - twitterLabel + initiateContactExchange: + storeCurrentProfileAsIdentity YES - - companyLabel - UILabel - - - emailLabel - UILabel - - - industryLabel - UILabel + + initiateContactExchange: + id - - nameLabel - UILabel - - - twitterLabel - UILabel + + storeCurrentProfileAsIdentity + id + + nameLabel + UILabel + + + nameLabel + + nameLabel + UILabel + + IBProjectSource Classes/RegistrantDetailViewController.h @@ -582,6 +479,22 @@ UIKit.framework/Headers/UIResponder.h + + UIButton + UIControl + + IBFrameworkSource + UIKit.framework/Headers/UIButton.h + + + + UIControl + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIControl.h + + UILabel UIView @@ -595,6 +508,14 @@ NSObject + + UIScrollView + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIScrollView.h + + UISearchBar UIView @@ -611,6 +532,14 @@ UIKit.framework/Headers/UISearchDisplayController.h + + UITextView + UIScrollView + + IBFrameworkSource + UIKit.framework/Headers/UITextView.h + + UIView @@ -677,6 +606,10 @@ YES ../CocoaCamp.xcodeproj 3 + + bump_lefthand.png + {70, 70} + 117 diff --git a/Classes/RegistrantDetailViewController.h b/Classes/RegistrantDetailViewController.h index aa998c6..e11027d 100644 --- a/Classes/RegistrantDetailViewController.h +++ b/Classes/RegistrantDetailViewController.h @@ -11,21 +11,17 @@ @class Registrant; +extern NSString *AppUserRegistrantIDKey; + @interface RegistrantDetailViewController : UIViewController { - Registrant *currRegistrant; - IBOutlet UILabel *industryLabel; - IBOutlet UILabel *emailLabel; - IBOutlet UILabel *twitterLabel; + Registrant *currRegistrant; IBOutlet UILabel *nameLabel; - IBOutlet UILabel *companyLabel; } @property (nonatomic, retain) Registrant *currRegistrant; -@property (nonatomic, retain) UILabel *companyLabel; -@property (nonatomic, retain) UILabel *industryLabel; -@property (nonatomic, retain) UILabel *emailLabel; -@property (nonatomic, retain) UILabel *twitterLabel; @property (nonatomic, retain) UILabel *nameLabel; - +- (IBAction)storeCurrentProfileAsIdentity; +- (IBAction)initiateContactExchange:(id)sender; +- (void)performContactExchange; @end diff --git a/Classes/RegistrantDetailViewController.m b/Classes/RegistrantDetailViewController.m index f260157..220fc65 100644 --- a/Classes/RegistrantDetailViewController.m +++ b/Classes/RegistrantDetailViewController.m @@ -8,32 +8,41 @@ #import "RegistrantDetailViewController.h" #import "Registrant.h" +#import "ContactManager.h" +#import "Bump.h" +#import "CocoaCampAppDelegate.h" + @implementation RegistrantDetailViewController -@synthesize currRegistrant, companyLabel, industryLabel, emailLabel, twitterLabel, nameLabel; +@synthesize currRegistrant, nameLabel; + + +NSString *AppUserRegistrantIDKey = @"AppUserRegistrantIDKey"; #pragma mark - #pragma mark View lifecycle - + + + - (void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; + - NSString *regName = currRegistrant.firstName; - regName = [regName stringByAppendingString:@" "]; - regName = [regName stringByAppendingString: currRegistrant.lastName]; + NSString *regName = [NSString stringWithFormat: @"Hi, %@ %@!", currRegistrant.firstName, currRegistrant.lastName]; nameLabel.text = regName; - NSLog(@"Name = %@ %@ %@", currRegistrant.firstName, currRegistrant.lastName, currRegistrant.company); - companyLabel.text = currRegistrant.company; - industryLabel.text = currRegistrant.industry; - emailLabel.text = currRegistrant.email; - twitterLabel.text = currRegistrant.twitter; -} + self.navigationItem.title = [NSString stringWithFormat: @"Hi, %@ %@!", currRegistrant.firstName, currRegistrant.lastName]; + [self storeCurrentProfileAsIdentity]; +} +- (void)storeCurrentProfileAsIdentity { + [[NSUserDefaults standardUserDefaults] setObject:currRegistrant.rid forKey:AppUserRegistrantIDKey]; + NSLog(@"Wrote %@ to defaults as registrant ID for current user.", currRegistrant.rid); +} #pragma mark - #pragma mark Memory management @@ -53,14 +62,59 @@ - (void)viewDidUnload { - (void)dealloc { [currRegistrant release]; - [companyLabel release]; - [industryLabel release]; - [emailLabel release]; - [twitterLabel release]; [nameLabel release]; [super dealloc]; } + +#pragma mark - +#pragma mark Contact exchange methods + +- (IBAction)initiateContactExchange:(id)sender { + NSNumber *appUserRegistrantID = [[NSUserDefaults standardUserDefaults] objectForKey:AppUserRegistrantIDKey]; + if(appUserRegistrantID) + { + [self performContactExchange]; + } + else + { + UIAlertView *noIdentityAlertView = [[UIAlertView alloc] initWithTitle:@"No User Identity" + message:@"Please set your identity by tapping \"This Is Me!\" in your attendee profile" + delegate:self + cancelButtonTitle:@"Got it" + otherButtonTitles:nil]; + [noIdentityAlertView show]; + [noIdentityAlertView release]; + } +} + +- (void)performContactExchange { + NSNumber *appUserRegistrantID = [[NSUserDefaults standardUserDefaults] objectForKey:AppUserRegistrantIDKey]; + + if(!appUserRegistrantID) + { + NSLog(@"Did not receive a valid registrant id in performContactExchange. Bailing..."); + return; + } + Registrant *appUser = self.currRegistrant; + /* + appUser.firstName = [appUserDictionary objectForKey:@"first_name"]; + appUser.lastName = [appUserDictionary objectForKey:@"last_name"]; + appUser.company = [appUserDictionary objectForKey:@"company"]; + appUser.twitter = [appUserDictionary objectForKey:@"twitter"]; + appUser.industry = [appUserDictionary objectForKey:@"industry"]; + appUser.email = [appUserDictionary objectForKey:@"email"]; + appUser.rid = [NSNumber numberWithInt:[[appUserDictionary objectForKey:@"id"] integerValue]]; + */ + BumpContact *bumpContact = [[ContactManager sharedInstance] bumpContactForRegistrant:appUser]; + Bump *bump = [(CocoaCampAppDelegate *)[[UIApplication sharedApplication] delegate] bump]; + [bump configParentView:self.view]; + [bump connectToDoContactExchange:bumpContact]; + + [appUser release]; + +} + @end diff --git a/Classes/SessionViewController.m b/Classes/SessionViewController.m index 3971ff1..91bcd03 100644 --- a/Classes/SessionViewController.m +++ b/Classes/SessionViewController.m @@ -122,6 +122,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N if (cell == nil) { cell = [[[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, 250, 60) reuseIdentifier:CellIdentifier] autorelease]; titleLabel = [[UILabel alloc] initWithFrame: CGRectMake(70, 5, 250, 25)]; + titleLabel.highlightedTextColor = [UIColor whiteColor]; titleLabel.tag = 3; [cell.contentView addSubview:titleLabel]; [titleLabel release]; @@ -177,6 +178,17 @@ - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NS return indexPath; } +/* +- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{ + NSDictionary *schedule = [self.schedules objectAtIndex:indexPath.section]; + NSArray *talksArray = [schedule objectForKey:@"Talk"]; + if ([talksArray count] == 0) + return nil; + else + return indexPath; +} +*/ + #pragma mark - #pragma mark Table view delegate diff --git a/Classes/TabController.m b/Classes/TabController.m index 9393ac2..d1fdb0b 100644 --- a/Classes/TabController.m +++ b/Classes/TabController.m @@ -7,17 +7,15 @@ // #import "TabController.h" -#import "SessionViewController.h" -#import "FlickrThumbnailView.h" -#import "ContactExchangeViewController.h" @implementation TabController - (void)viewDidLoad { [self setTabURLs:[NSArray arrayWithObjects: + @"tt://people", @"tt://schedule", @"tt://flickr", - @"tt://people", + @"tt://twitter", nil]]; } diff --git a/Classes/TwitterFeedTableView.xib b/Classes/TwitterFeedTableView.xib new file mode 100644 index 0000000..4a0211d --- /dev/null +++ b/Classes/TwitterFeedTableView.xib @@ -0,0 +1,399 @@ + + + + 1024 + 10F569 + 804 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 123 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + {320, 460} + + + 3 + MQA + + NO + YES + NO + + IBCocoaTouchFramework + NO + 1 + 0 + YES + 44 + 22 + 22 + + + + + YES + + + view + + + + 5 + + + + dataSource + + + + 6 + + + + delegate + + + + 7 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 4 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 4.IBEditorWindowLastContentRect + 4.IBPluginDependency + + + YES + TwitterFeedTableViewController + UIResponder + {{329, 504}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 8 + + + + YES + + NSObject + + IBProjectSource + Classes/JSON/NSObject+SBJSON.h + + + + NSObject + + IBProjectSource + Classes/JSON/SBJsonWriter.h + + + + TwitterFeedTableViewController + UITableViewController + + IBProjectSource + Classes/TwitterFeedTableViewController.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CAAnimation.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CALayer.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIResponder + NSObject + + + + UIScrollView + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIScrollView.h + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UITableView + UIScrollView + + IBFrameworkSource + UIKit.framework/Headers/UITableView.h + + + + UITableViewController + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITableViewController.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UIPopoverController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UISplitViewController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + + 3 + 123 + + diff --git a/Classes/TwitterFeedTableViewCell.xib b/Classes/TwitterFeedTableViewCell.xib new file mode 100644 index 0000000..e627c64 --- /dev/null +++ b/Classes/TwitterFeedTableViewCell.xib @@ -0,0 +1,472 @@ + + + + 1024 + 10F569 + 788 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 117 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 292 + + YES + + + 256 + + YES + + + 292 + {{6, 6}, {48, 48}} + + 1 + NO + IBCocoaTouchFramework + + + + 290 + {{60, 20}, {240, 35}} + + + 1 + MSAxIDEgMAA + + NO + YES + YES + 4 + IBCocoaTouchFramework + -8 + -8 + -8 + -8 + NO + NO + NO + NO + NO + NO + NO + NO + Tweet contents. This can be several lines, and this view will be resized programmatically as necessary. + + Helvetica + 12 + 16 + + + 2 + IBCocoaTouchFramework + + 2 + + + + 292 + {{60, 0}, {130, 20}} + + + 1 + MSAxIDEAA + + YES + 7 + 2 + NO + IBCocoaTouchFramework + @verylongtwittername + + Helvetica-Bold + 12 + 16 + + + 1 + MC4zNTIwNDA4MTYzIDAuMzUyMDQwODE2MyAwLjM1MjA0MDgxNjMAA + + + 1 + MSAxIDEAA + + 1 + NO + 10 + 2 + + + + 291 + {{195, 0}, {105, 20}} + + + YES + 7 + 3 + NO + IBCocoaTouchFramework + 10/31/2010 12:01 PM + + Helvetica + 10 + 16 + + + + 1 + NO + 10 + 2 + 2 + + + {320, 60} + + + 3 + MCAwAA + + NO + YES + 4 + YES + IBCocoaTouchFramework + + + {320, 60} + + + IBCocoaTouchFramework + 1 + + + + + + YES + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 2 + + + YES + + + + + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + + + YES + + YES + -2.CustomClassName + 2.IBEditorWindowLastContentRect + 2.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + 4.IBPluginDependency + 5.IBPluginDependency + 6.IBPluginDependency + + + YES + UIResponder + {{813, 547}, {320, 60}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + TTImageView + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 7 + + + + YES + + NSObject + + IBProjectSource + Classes/JSON/NSObject+SBJSON.h + + + + NSObject + + IBProjectSource + Classes/JSON/SBJsonWriter.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CAAnimation.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CALayer.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UILabel + UIView + + IBFrameworkSource + UIKit.framework/Headers/UILabel.h + + + + UIResponder + NSObject + + + + UIScrollView + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIScrollView.h + + + + UITableViewCell + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITableViewCell.h + + + + UITextView + UIScrollView + + IBFrameworkSource + UIKit.framework/Headers/UITextView.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + ../CocoaCamp.xcodeproj + 3 + 117 + + diff --git a/Classes/TwitterFeedTableViewController.h b/Classes/TwitterFeedTableViewController.h new file mode 100644 index 0000000..e08dc4e --- /dev/null +++ b/Classes/TwitterFeedTableViewController.h @@ -0,0 +1,26 @@ +// +// TwitterFeedTableViewController.h +// CocoaCamp +// +// Created by Warren Moore on 9/1/10. +// Copyright 2010 Auerhaus Development, LLC. All rights reserved. +// + +#import + + +@interface TwitterFeedTableViewController : UITableViewController { + NSMutableData *tweetData; + NSArray *tweets; + NSDateFormatter *dateParser; + NSString *tweetSearchURLSuffix; + UIActivityIndicatorView *activityIndicator; +} + +- (void)refreshTweets; + +@end + +@interface NSDate(PrettyDate) +- (NSString *)prettyStringRelativeToDate:(NSDate *)priorDate; +@end \ No newline at end of file diff --git a/Classes/TwitterFeedTableViewController.m b/Classes/TwitterFeedTableViewController.m new file mode 100644 index 0000000..bd69f5a --- /dev/null +++ b/Classes/TwitterFeedTableViewController.m @@ -0,0 +1,273 @@ +// +// TwitterFeedTableViewController.m +// CocoaCamp +// +// Created by Warren Moore on 9/1/10. +// Copyright 2010 Auerhaus Development, LLC. All rights reserved. +// + +#import "TwitterFeedTableViewController.h" +#import "SBJSON.h" +#import "NSString+XMLEntities.h" + +@implementation TwitterFeedTableViewController + +static NSString *TweetSearchURL = @"http://search.twitter.com/search.json"; +static NSString *RFC822DateFormat = @"EEE, dd MMM yyyy HH:mm:ss z"; + +-(id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle { + if (self = [super initWithNibName:nibName bundle:bundle]){ + self.title = @"Twitter"; + UIImage* image = [UIImage imageNamed:@"bird.png"]; + self.tabBarItem = [[[UITabBarItem alloc] initWithTitle:@"Twitter" image:image tag:0] autorelease]; + } + return self; +} + + +#pragma mark - +#pragma mark View lifecycle + +- (void)viewDidLoad { + [super viewDidLoad]; + + tweets = [[NSMutableArray alloc] init]; + tweetSearchURLSuffix = @"?q=cocoacamp"; + + dateParser = [[NSDateFormatter alloc] init]; + [dateParser setDateFormat:RFC822DateFormat]; + + CGRect frame = CGRectMake(self.view.frame.size.width/2-15, self.view.frame.size.height/2-15-30, 30, 30); + activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:frame]; + [activityIndicator startAnimating]; + activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray; + [activityIndicator sizeToFit]; + activityIndicator.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | + UIViewAutoresizingFlexibleRightMargin | + UIViewAutoresizingFlexibleTopMargin | + UIViewAutoresizingFlexibleBottomMargin); + + self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh + target:self + action:@selector(refreshTweets)] autorelease]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self refreshTweets]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + return UIInterfaceOrientationIsPortrait(interfaceOrientation); +} + +- (void)refreshTweets { + [self.view addSubview:activityIndicator]; + tweetData = [[NSMutableData alloc] init]; + NSURL *searchURL = [NSURL URLWithString:[TweetSearchURL stringByAppendingString:tweetSearchURLSuffix]]; + + NSLog(@"Issuing request for tweets to URL: %@", searchURL); + + NSURLRequest *request = [[NSURLRequest alloc] initWithURL:searchURL]; + [[NSURLConnection alloc] initWithRequest:request delegate:self]; + [request release]; +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + [tweetData appendData:data]; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { + SBJSON *jsonParser = [[SBJSON alloc] init]; + + NSString *twitterJSON = [[NSString alloc] initWithData:tweetData encoding:NSUTF8StringEncoding]; + NSDictionary *twitterAssoc = [jsonParser objectWithString:twitterJSON error:nil]; + + NSArray *newTweets = [[twitterAssoc objectForKey:@"results"] retain]; + + // do some preprocessing on tweets to make our lives easier later + for(NSDictionary *tweet in newTweets) + { + NSString *tweetText = [[tweet objectForKey:@"text"] stringByDecodingXMLEntities]; + + CGSize tweetSize = [tweetText sizeWithFont:[UIFont systemFontOfSize:12.0] + constrainedToSize:CGSizeMake(225.0, 1000.0) + lineBreakMode:UILineBreakModeWordWrap]; + + // risky business. + [(NSMutableDictionary *)tweet setObject:tweetText forKey:@"text"]; + [(NSMutableDictionary *)tweet setObject:[NSNumber numberWithFloat:tweetSize.height] forKey:@"display_height"]; + } + + NSLog(@"Will add an additional %d tweets to the existing %d tweets.", [newTweets count], [tweets count]); + + NSArray *oldTweets = tweets; + tweets = [[newTweets arrayByAddingObjectsFromArray:tweets] retain]; // add new tweets to beginning of timeline + [oldTweets release]; + [newTweets release]; + + [tweetSearchURLSuffix release]; + tweetSearchURLSuffix = [[twitterAssoc objectForKey:@"refresh_url"] retain]; // cache refresh URL in case we refresh before being dismissed + + [twitterJSON release]; + [tweetData release]; + [connection release]; + + [self.tableView reloadData]; + [activityIndicator removeFromSuperview]; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + [tweetData release]; + [connection release]; + + [activityIndicator removeFromSuperview]; +} + +#pragma mark - +#pragma mark Table view data source + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [tweets count]; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + NSDictionary *tweet = [tweets objectAtIndex:indexPath.row]; + CGFloat height = [[tweet objectForKey:@"display_height"] floatValue] + 24.0; // compensate for text area insets and y-position + return MAX(60.0, height); // clamp to minimum height +} + + +// Customize the appearance of table view cells. +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + static NSString *CellIdentifier = @"TweetCell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + + UILabel *senderLabel; + UILabel *dateLabel; + UITextView *contentText; + TTImageView *avatarImageView; + + if (cell == nil) { + + NSArray *bundleObjects = [[NSBundle mainBundle] loadNibNamed:@"TwitterFeedTableViewCell" owner:nil options:nil]; + + cell = [bundleObjects objectAtIndex:0]; + + avatarImageView = (TTImageView *)[cell viewWithTag:1]; + avatarImageView.defaultImage = [UIImage imageNamed:@"loading.png"]; + } + + senderLabel = (UILabel *)[cell viewWithTag:2]; + dateLabel = (UILabel *)[cell viewWithTag:3]; + contentText = (UITextView *)[cell viewWithTag:4]; + avatarImageView = (TTImageView *)[cell viewWithTag:1]; + + NSDictionary *tweet = [tweets objectAtIndex:indexPath.row]; + + NSDate *tweetDate = [dateParser dateFromString:[tweet objectForKey:@"created_at"]]; + + senderLabel.text = [tweet objectForKey:@"from_user"]; + dateLabel.text = [tweetDate prettyStringRelativeToDate:[NSDate date]]; + + contentText.text = [tweet objectForKey:@"text"]; + CGFloat height = [[tweet objectForKey:@"display_height"] floatValue]; + [contentText setFrame:CGRectMake(60.0, 20.0, 240.0, height)]; + + avatarImageView.urlPath = [tweet objectForKey:@"profile_image_url"]; + + return cell; +} + + +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + return NO; +} + +- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { + return NO; +} + +#pragma mark - +#pragma mark Table view delegate + +- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { + return nil; // No selection allowed +} + +#pragma mark - +#pragma mark Memory management + +- (void)didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Relinquish ownership any cached data, images, etc that aren't in use. +} + +- (void)viewDidUnload { + // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand. + [dateParser release]; + [tweets release]; + [activityIndicator release]; +} + + +- (void)dealloc { + [super dealloc]; +} + +@end + +/* Logic taken from JavaScript Pretty Date by John Resig + * + */ +@implementation NSDate (PrettyDate) +- (NSString *)prettyStringRelativeToDate:(NSDate *)priorDate { + NSTimeInterval secondDiff = [priorDate timeIntervalSinceDate:self]; + NSInteger dayDiff = (NSInteger)floor(secondDiff / 86400); + + if(dayDiff < 0) + { + return @"In the future"; + } + else if(dayDiff == 0) + { + if(secondDiff < 60) + return @"Just now"; + else if(secondDiff < 120) + return @"1 minute ago"; + else if(secondDiff < 3600) + return [NSString stringWithFormat:@"%d minutes ago", (NSInteger)floor(secondDiff/60)]; + else if(secondDiff < 7200) + return @"1 hour ago"; + else if(secondDiff < 86400) + return [NSString stringWithFormat:@"%d hours ago", (NSInteger)floor(secondDiff/3600)]; + } + else if(dayDiff == 1) + return @"Yesterday"; + else if(dayDiff < 7) + return [NSString stringWithFormat:@"%d days ago", dayDiff]; + else if(dayDiff == 7) + return @"1 week ago"; + else + return [NSString stringWithFormat:@"%d weeks ago", ((dayDiff + 3) / 7)]; // Resig uses ceil; this seems smoother + + return @"Sometime"; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{ + return YES; +} +@end diff --git a/CocoaCamp.xcodeproj/project.pbxproj b/CocoaCamp.xcodeproj/project.pbxproj index 57cf572..79abe6a 100644 --- a/CocoaCamp.xcodeproj/project.pbxproj +++ b/CocoaCamp.xcodeproj/project.pbxproj @@ -75,6 +75,11 @@ 03D540BD122FE001004DBF63 /* FlickrThumbnailView.m in Sources */ = {isa = PBXBuildFile; fileRef = 03D540BC122FE001004DBF63 /* FlickrThumbnailView.m */; }; 03D54117122FEC87004DBF63 /* FlickrAddPhotoController.m in Sources */ = {isa = PBXBuildFile; fileRef = 03D54115122FEC87004DBF63 /* FlickrAddPhotoController.m */; }; 03D54118122FEC87004DBF63 /* FlickrAddPhotoController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03D54116122FEC87004DBF63 /* FlickrAddPhotoController.xib */; }; + 03F7D4A212326E1B007FE8C7 /* TwitterFeedTableView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03F7D49E12326E1B007FE8C7 /* TwitterFeedTableView.xib */; }; + 03F7D4A312326E1B007FE8C7 /* TwitterFeedTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03F7D49F12326E1B007FE8C7 /* TwitterFeedTableViewCell.xib */; }; + 03F7D4A412326E1B007FE8C7 /* TwitterFeedTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 03F7D4A112326E1B007FE8C7 /* TwitterFeedTableViewController.m */; }; + 03F7D4D41232713C007FE8C7 /* bird.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F7D4D31232713C007FE8C7 /* bird.png */; }; + 03F7D4D912327248007FE8C7 /* NSString+XMLEntities.m in Sources */ = {isa = PBXBuildFile; fileRef = 03F7D4D812327248007FE8C7 /* NSString+XMLEntities.m */; }; 1D3623260D0F684500981E51 /* CocoaCampAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* CocoaCampAppDelegate.m */; }; 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; @@ -84,7 +89,6 @@ 80C1A8BF1221CCCD007F7D7A /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80C1A8BE1221CCCD007F7D7A /* CoreLocation.framework */; }; 80C1A8C31221CCD9007F7D7A /* libBump.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 80C1A8C21221CCD9007F7D7A /* libBump.a */; }; 80C1A8C81221CCEB007F7D7A /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80C1A8C71221CCEB007F7D7A /* AudioToolbox.framework */; }; - 80C1A8D11221CD02007F7D7A /* ContactExchangeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 80C1A8CE1221CD02007F7D7A /* ContactExchangeViewController.m */; }; 80C1A8D21221CD02007F7D7A /* ContactManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 80C1A8D01221CD02007F7D7A /* ContactManager.m */; }; 80C1A8D71221CD17007F7D7A /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80C1A8D61221CD17007F7D7A /* AddressBook.framework */; }; 80C1A8D91221CD17007F7D7A /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80C1A8D81221CD17007F7D7A /* AddressBookUI.framework */; }; @@ -353,6 +357,13 @@ 03D54114122FEC87004DBF63 /* FlickrAddPhotoController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlickrAddPhotoController.h; sourceTree = ""; }; 03D54115122FEC87004DBF63 /* FlickrAddPhotoController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlickrAddPhotoController.m; sourceTree = ""; }; 03D54116122FEC87004DBF63 /* FlickrAddPhotoController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FlickrAddPhotoController.xib; sourceTree = ""; }; + 03F7D49E12326E1B007FE8C7 /* TwitterFeedTableView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TwitterFeedTableView.xib; sourceTree = ""; }; + 03F7D49F12326E1B007FE8C7 /* TwitterFeedTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TwitterFeedTableViewCell.xib; sourceTree = ""; }; + 03F7D4A012326E1B007FE8C7 /* TwitterFeedTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TwitterFeedTableViewController.h; sourceTree = ""; }; + 03F7D4A112326E1B007FE8C7 /* TwitterFeedTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TwitterFeedTableViewController.m; sourceTree = ""; }; + 03F7D4D31232713C007FE8C7 /* bird.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = bird.png; path = Resources/bird.png; sourceTree = ""; }; + 03F7D4D712327248007FE8C7 /* NSString+XMLEntities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+XMLEntities.h"; sourceTree = ""; }; + 03F7D4D812327248007FE8C7 /* NSString+XMLEntities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+XMLEntities.m"; sourceTree = ""; }; 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 1D3623240D0F684500981E51 /* CocoaCampAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CocoaCampAppDelegate.h; sourceTree = ""; }; 1D3623250D0F684500981E51 /* CocoaCampAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CocoaCampAppDelegate.m; sourceTree = ""; }; @@ -365,8 +376,6 @@ 80C1A8BE1221CCCD007F7D7A /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; 80C1A8C21221CCD9007F7D7A /* libBump.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libBump.a; sourceTree = ""; }; 80C1A8C71221CCEB007F7D7A /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; - 80C1A8CD1221CD02007F7D7A /* ContactExchangeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactExchangeViewController.h; sourceTree = ""; }; - 80C1A8CE1221CD02007F7D7A /* ContactExchangeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactExchangeViewController.m; sourceTree = ""; }; 80C1A8CF1221CD02007F7D7A /* ContactManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactManager.h; sourceTree = ""; }; 80C1A8D01221CD02007F7D7A /* ContactManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactManager.m; sourceTree = ""; }; 80C1A8D61221CD17007F7D7A /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; @@ -531,8 +540,6 @@ 030894901226F2CA0088A584 /* AttendeeListViewController.m */, 80C1A8F81221CDF4007F7D7A /* Bump.h */, 80C1A8F91221CDF4007F7D7A /* BumpContact.h */, - 80C1A8CD1221CD02007F7D7A /* ContactExchangeViewController.h */, - 80C1A8CE1221CD02007F7D7A /* ContactExchangeViewController.m */, 80C1A8CF1221CD02007F7D7A /* ContactManager.h */, 80C1A8D01221CD02007F7D7A /* ContactManager.m */, 03AF412612120F8D0061D5DD /* FlickrController.h */, @@ -557,6 +564,12 @@ 03D54116122FEC87004DBF63 /* FlickrAddPhotoController.xib */, 03AE932212309B6200C188E9 /* TabController.h */, 03AE932312309B6200C188E9 /* TabController.m */, + 03F7D49E12326E1B007FE8C7 /* TwitterFeedTableView.xib */, + 03F7D49F12326E1B007FE8C7 /* TwitterFeedTableViewCell.xib */, + 03F7D4A012326E1B007FE8C7 /* TwitterFeedTableViewController.h */, + 03F7D4A112326E1B007FE8C7 /* TwitterFeedTableViewController.m */, + 03F7D4D712327248007FE8C7 /* NSString+XMLEntities.h */, + 03F7D4D812327248007FE8C7 /* NSString+XMLEntities.m */, ); path = Classes; sourceTree = ""; @@ -626,6 +639,7 @@ AB2AE44A11EBAA8500015C01 /* images */ = { isa = PBXGroup; children = ( + 03F7D4D31232713C007FE8C7 /* bird.png */, FBF7E8211227E55000B7A710 /* keynote-icon.png */, FBF7E8221227E55000B7A710 /* keynote-icon@2x.png */, 035B9D45122693520038129A /* loading.png */, @@ -955,6 +969,9 @@ FBF7E8231227E55000B7A710 /* keynote-icon.png in Resources */, FBF7E8241227E55000B7A710 /* keynote-icon@2x.png in Resources */, 03D54118122FEC87004DBF63 /* FlickrAddPhotoController.xib in Resources */, + 03F7D4A212326E1B007FE8C7 /* TwitterFeedTableView.xib in Resources */, + 03F7D4A312326E1B007FE8C7 /* TwitterFeedTableViewCell.xib in Resources */, + 03F7D4D41232713C007FE8C7 /* bird.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -977,7 +994,6 @@ 03AF412B12120F8D0061D5DD /* FlickrController.m in Sources */, 03AF412D12120F8D0061D5DD /* FlickrPageViewController.m in Sources */, 0341222E12148A3400B376F7 /* SessionDetailViewController.m in Sources */, - 80C1A8D11221CD02007F7D7A /* ContactExchangeViewController.m in Sources */, 80C1A8D21221CD02007F7D7A /* ContactManager.m in Sources */, 030894911226F2CA0088A584 /* AttendeeListViewController.m in Sources */, 030894971226F2DB0088A584 /* Registrant.m in Sources */, @@ -996,6 +1012,8 @@ 03D540BD122FE001004DBF63 /* FlickrThumbnailView.m in Sources */, 03D54117122FEC87004DBF63 /* FlickrAddPhotoController.m in Sources */, 03AE932412309B6200C188E9 /* TabController.m in Sources */, + 03F7D4A412326E1B007FE8C7 /* TwitterFeedTableViewController.m in Sources */, + 03F7D4D912327248007FE8C7 /* NSString+XMLEntities.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/RegistrantListView.xib b/RegistrantListView.xib index aafa5ef..35cd232 100644 --- a/RegistrantListView.xib +++ b/RegistrantListView.xib @@ -12,8 +12,8 @@ YES + - YES @@ -53,37 +53,31 @@ IBCocoaTouchFramework - - + 1 IBCocoaTouchFramework NO - - - Attendees - IBCocoaTouchFramework - - - - - 1 - + + + 256 + {0, 0} + NO + YES + YES IBCocoaTouchFramework - NO YES - - - - Presenters + + + + Root View Controller IBCocoaTouchFramework - - + 1 @@ -91,16 +85,6 @@ NO - - - 266 - {{129, 330}, {163, 49}} - - 3 - MCAwAA - - IBCocoaTouchFramework - @@ -133,48 +117,33 @@ - 3 - + 9 + YES - - - + + - 4 - - - - - 5 - + 10 + YES - + - + - 6 - - - YES - - - - - - 7 - - + 11 + + - 8 - - + 12 + + @@ -186,30 +155,22 @@ -2.CustomClassName 1.IBEditorWindowLastContentRect 1.IBPluginDependency - 3.IBEditorWindowLastContentRect - 3.IBPluginDependency - 4.IBPluginDependency - 5.CustomClassName - 5.IBPluginDependency - 6.CustomClassName - 6.IBPluginDependency - 7.IBPluginDependency - 8.IBPluginDependency + 10.IBPluginDependency + 11.IBPluginDependency + 12.IBPluginDependency + 9.IBEditorWindowLastContentRect + 9.IBPluginDependency YES RegistrantListViewController UIResponder - {{239, 382}, {320, 480}} + {{330, 382}, {320, 480}} com.apple.InterfaceBuilder.IBCocoaTouchPlugin - {{692, 119}, {320, 480}} com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin - AttendeeListViewController - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - PresenterListViewController - com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{330, 665}, {320, 480}} com.apple.InterfaceBuilder.IBCocoaTouchPlugin @@ -229,19 +190,11 @@ - 8 + 12 YES - - AttendeeListViewController - UITableViewController - - IBProjectSource - Classes/AttendeeListViewController.h - - NSObject @@ -256,22 +209,6 @@ Classes/JSON/SBJsonWriter.h - - PresenterListViewController - UITableViewController - - IBProjectSource - Classes/PresenterListViewController.h - - - - RegistrantListViewController - UITableViewController - - IBProjectSource - Classes/RegistrantListViewController.h - - YES @@ -381,64 +318,61 @@ - UIBarItem - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIBarItem.h - - - - UIResponder - NSObject - - - - UISearchBar - UIView + UIBarButtonItem + UIBarItem IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h + UIKit.framework/Headers/UIBarButtonItem.h - UISearchDisplayController + UIBarItem NSObject IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h + UIKit.framework/Headers/UIBarItem.h - UITabBar + UINavigationBar UIView - + IBFrameworkSource - UIKit.framework/Headers/UITabBar.h + UIKit.framework/Headers/UINavigationBar.h - UITabBarController + UINavigationController UIViewController - + IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h + UIKit.framework/Headers/UINavigationController.h - UITabBarItem - UIBarItem + UINavigationItem + NSObject + + + + UIResponder + NSObject + + + + UISearchBar + UIView IBFrameworkSource - UIKit.framework/Headers/UITabBarItem.h + UIKit.framework/Headers/UISearchBar.h - UITableViewController - UIViewController + UISearchDisplayController + NSObject IBFrameworkSource - UIKit.framework/Headers/UITableViewController.h + UIKit.framework/Headers/UISearchDisplayController.h @@ -458,10 +392,7 @@ UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - + UIViewController @@ -479,7 +410,10 @@ UIViewController - + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + UIViewController