├── .gitignore ├── Screenshots ├── 1.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg └── 5.jpg ├── VELOPARISICON.psd ├── Shared ├── PNG │ ├── ICON.png │ ├── ICON-72.png │ ├── ICON@2x.png │ ├── pinRed.png │ ├── IconList.png │ ├── pinGreen.png │ ├── pinOrange.png │ ├── pinPurple.png │ ├── pinRed@2x.png │ ├── pinYellow.png │ ├── FavoriteOff.png │ ├── FavoriteOn.png │ ├── ICON-72@2x.png │ ├── ICON_SMALL.png │ ├── IconFavorite.png │ ├── IconList@2x.png │ ├── IconLocation.png │ ├── IconZoomIn.png │ ├── IconZoomOut.png │ ├── UserHeading.png │ ├── pinGreen@2x.png │ ├── pinOrange@2x.png │ ├── pinPurple@2x.png │ ├── pinYellow@2x.png │ ├── FavoriteOff@2x.png │ ├── FavoriteOn@2x.png │ ├── ICON_SMALL@2x.png │ ├── IconZoomIn@2x.png │ ├── IconZoomOut@2x.png │ ├── UserHeading@2x.png │ ├── pinYellowGreen.png │ ├── IconFavorite@2x.png │ ├── IconLocation@2x.png │ └── pinYellowGreen@2x.png ├── PinAnnotationView.h ├── PinAnnotationView.m ├── ParseStation.h ├── ParseStations.h ├── ConnectionDelegate.h ├── CustomizedTableCell.h ├── StationAnnotation.h ├── SynthesizeSingleton.h ├── ParseStations.m ├── ParseStation.m ├── StationAnnotation.m ├── CustomizedTableCell.m └── ConnectionDelegate.m ├── main.m ├── VeloParis_Prefix.pch ├── README.markdown ├── Info.plist ├── iPad ├── AppDelegate_iPad.h └── AppDelegate_iPad.m ├── iPhone ├── AppDelegate_iPhone.h └── AppDelegate_iPhone.m └── VeloParis.xcodeproj └── project.pbxproj /.gitignore: -------------------------------------------------------------------------------- 1 | *.pbxuser 2 | *.mode1v3 3 | *.xcscheme 4 | *.xcuserdatad 5 | *.xcworkspace -------------------------------------------------------------------------------- /Screenshots/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Screenshots/1.jpg -------------------------------------------------------------------------------- /Screenshots/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Screenshots/2.jpg -------------------------------------------------------------------------------- /Screenshots/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Screenshots/3.jpg -------------------------------------------------------------------------------- /Screenshots/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Screenshots/4.jpg -------------------------------------------------------------------------------- /Screenshots/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Screenshots/5.jpg -------------------------------------------------------------------------------- /VELOPARISICON.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/VELOPARISICON.psd -------------------------------------------------------------------------------- /Shared/PNG/ICON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/ICON.png -------------------------------------------------------------------------------- /Shared/PNG/ICON-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/ICON-72.png -------------------------------------------------------------------------------- /Shared/PNG/ICON@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/ICON@2x.png -------------------------------------------------------------------------------- /Shared/PNG/pinRed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/pinRed.png -------------------------------------------------------------------------------- /Shared/PNG/IconList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/IconList.png -------------------------------------------------------------------------------- /Shared/PNG/pinGreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/pinGreen.png -------------------------------------------------------------------------------- /Shared/PNG/pinOrange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/pinOrange.png -------------------------------------------------------------------------------- /Shared/PNG/pinPurple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/pinPurple.png -------------------------------------------------------------------------------- /Shared/PNG/pinRed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/pinRed@2x.png -------------------------------------------------------------------------------- /Shared/PNG/pinYellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/pinYellow.png -------------------------------------------------------------------------------- /Shared/PNG/FavoriteOff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/FavoriteOff.png -------------------------------------------------------------------------------- /Shared/PNG/FavoriteOn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/FavoriteOn.png -------------------------------------------------------------------------------- /Shared/PNG/ICON-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/ICON-72@2x.png -------------------------------------------------------------------------------- /Shared/PNG/ICON_SMALL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/ICON_SMALL.png -------------------------------------------------------------------------------- /Shared/PNG/IconFavorite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/IconFavorite.png -------------------------------------------------------------------------------- /Shared/PNG/IconList@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/IconList@2x.png -------------------------------------------------------------------------------- /Shared/PNG/IconLocation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/IconLocation.png -------------------------------------------------------------------------------- /Shared/PNG/IconZoomIn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/IconZoomIn.png -------------------------------------------------------------------------------- /Shared/PNG/IconZoomOut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/IconZoomOut.png -------------------------------------------------------------------------------- /Shared/PNG/UserHeading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/UserHeading.png -------------------------------------------------------------------------------- /Shared/PNG/pinGreen@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/pinGreen@2x.png -------------------------------------------------------------------------------- /Shared/PNG/pinOrange@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/pinOrange@2x.png -------------------------------------------------------------------------------- /Shared/PNG/pinPurple@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/pinPurple@2x.png -------------------------------------------------------------------------------- /Shared/PNG/pinYellow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/pinYellow@2x.png -------------------------------------------------------------------------------- /Shared/PNG/FavoriteOff@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/FavoriteOff@2x.png -------------------------------------------------------------------------------- /Shared/PNG/FavoriteOn@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/FavoriteOn@2x.png -------------------------------------------------------------------------------- /Shared/PNG/ICON_SMALL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/ICON_SMALL@2x.png -------------------------------------------------------------------------------- /Shared/PNG/IconZoomIn@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/IconZoomIn@2x.png -------------------------------------------------------------------------------- /Shared/PNG/IconZoomOut@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/IconZoomOut@2x.png -------------------------------------------------------------------------------- /Shared/PNG/UserHeading@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/UserHeading@2x.png -------------------------------------------------------------------------------- /Shared/PNG/pinYellowGreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/pinYellowGreen.png -------------------------------------------------------------------------------- /Shared/PNG/IconFavorite@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/IconFavorite@2x.png -------------------------------------------------------------------------------- /Shared/PNG/IconLocation@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/IconLocation@2x.png -------------------------------------------------------------------------------- /Shared/PNG/pinYellowGreen@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CocoaBob/VeloParis/HEAD/Shared/PNG/pinYellowGreen@2x.png -------------------------------------------------------------------------------- /Shared/PinAnnotationView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PinAnnotationView.h 3 | // VeloParis 4 | // 5 | // Created by CocoaBob on 10-4-3. 6 | // Copyright 2010 CocoaBob. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import "StationAnnotation.h" 13 | 14 | @interface PinAnnotationView : MKAnnotationView { 15 | } 16 | @end 17 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // VeloParis 4 | // 5 | // Created by CocoaBob on 10-8-17. 6 | // Copyright CocoaBob 2010. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) { 12 | 13 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 14 | int retVal = UIApplicationMain(argc, argv, nil, nil); 15 | [pool release]; 16 | return retVal; 17 | } 18 | -------------------------------------------------------------------------------- /Shared/PinAnnotationView.m: -------------------------------------------------------------------------------- 1 | // 2 | // PinAnnotationView.m 3 | // VeloParis 4 | // 5 | // Created by CocoaBob on 10-4-3. 6 | // Copyright 2010 CocoaBob. All rights reserved. 7 | // 8 | 9 | #import "PinAnnotationView.h" 10 | 11 | @implementation PinAnnotationView 12 | 13 | - (BOOL)canShowCallout{ 14 | return YES; 15 | } 16 | 17 | - (CGPoint)centerOffset{ 18 | return CGPointMake(5, -9); 19 | } 20 | 21 | -(CGPoint)calloutOffset{ 22 | return CGPointMake(-5, -1); 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /VeloParis_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'VeloParis' target in the 'VeloParis' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #endif 9 | 10 | #define kLastLocationLatitude @"kLastLocationLatitude" 11 | #define kLastLocationLongitude @"kLastLocationLongitude" 12 | #define kMapType @"kMapType" 13 | #define kIsNotFirstTimeLaunch @"kIsNotFirstTimeLaunch" 14 | #define kHasCheckedAvailablity @"kHasCheckedAvailablity" -------------------------------------------------------------------------------- /Shared/ParseStation.h: -------------------------------------------------------------------------------- 1 | // 2 | // ParseStation.h 3 | // VeloParis 4 | // 5 | // Created by Mengke WANG on 4/2/10. 6 | // Copyright 2010 CocoaBob. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ParseStation : NSObject { 12 | NSMutableDictionary *mStation; 13 | NSMutableString *mNodeName; 14 | NSString *mKey; 15 | NSString *mValue; 16 | } 17 | 18 | - (NSDictionary *)parseXMLFromData:(NSData *)data parseError:(NSError **)error; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Shared/ParseStations.h: -------------------------------------------------------------------------------- 1 | // 2 | // ParseStations.h 3 | // VeloParis 4 | // 5 | // Created by Mengke WANG on 4/2/10. 6 | // Copyright 2010 CocoaBob. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface ParseStations : NSObject { 13 | NSMutableArray *mStations; 14 | NSDictionary *mStation; 15 | NSMutableString *mNodeName; 16 | 17 | } 18 | - (NSArray *)parseXMLFromData:(NSData *)data parseError:(NSError **)error; 19 | + (ParseStations *)sharedParseStations; 20 | @end 21 | -------------------------------------------------------------------------------- /Shared/ConnectionDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ConnectionDelegate.h 3 | // VeloParis 4 | // 5 | // Created by Mengke WANG on 4/2/10. 6 | // Copyright 2010 CocoaBob. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ParseStation.h" 11 | #import "ParseStations.h" 12 | #import "StationAnnotation.h" 13 | 14 | @interface ConnectionDelegate : NSObject { 15 | NSMutableData *receivedData; 16 | } 17 | 18 | + (ConnectionDelegate *)sharedConnectionDelegate; 19 | - (void)getAllStations; 20 | - (void)threadParseAnnotations:(NSArray *)allStationsData; 21 | @end 22 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | An iOS app used to check Paris public bicycles status. You can find nearby stations and the number of bicycles left. 2 | 3 | ![Screenshot 1](https://github.com/CocoaBob/VeloParis/raw/master/Screenshots/1.jpg "Screenshot") 4 | 5 | ![Screenshot 2](https://github.com/CocoaBob/VeloParis/raw/master/Screenshots/2.jpg "Screenshot") 6 | 7 | ![Screenshot 3](https://github.com/CocoaBob/VeloParis/raw/master/Screenshots/3.jpg "Screenshot") 8 | 9 | ![Screenshot 4](https://github.com/CocoaBob/VeloParis/raw/master/Screenshots/4.jpg "Screenshot") 10 | 11 | ![Screenshot 5](https://github.com/CocoaBob/VeloParis/raw/master/Screenshots/5.jpg "Screenshot") 12 | -------------------------------------------------------------------------------- /Shared/CustomizedTableCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // CustomizedTableCell.h 3 | // VeloParis 4 | // 5 | // Created by CocoaBob on 10-4-6. 6 | // Copyright 2010 CocoaBob. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface CustomizedTableCell : UITableViewCell { 13 | UILabel *mLeftLabel; 14 | UILabel *mMiddleLabel; 15 | UILabel *mRightLabel; 16 | UILabel *mDistanceLabel; 17 | } 18 | 19 | @property (nonatomic, retain) UILabel *mLeftLabel; 20 | @property (nonatomic, retain) UILabel *mMiddleLabel; 21 | @property (nonatomic, retain) UILabel *mRightLabel; 22 | @property (nonatomic, retain) UILabel *mDistanceLabel; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Shared/StationAnnotation.h: -------------------------------------------------------------------------------- 1 | // 2 | // StationMark.h 3 | // VeloParis 4 | // 5 | // Created by Mengke WANG on 4/2/10. 6 | // Copyright 2010 CocoaBob. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | @interface StationAnnotation : NSObject { 14 | CLLocationCoordinate2D coordinate; 15 | NSString *subtitle; 16 | NSString *title; 17 | NSString *stationID; 18 | BOOL mIsRequested; 19 | BOOL mIsRunning; 20 | float mRatio; 21 | int mNumAvailable; 22 | } 23 | 24 | @property (nonatomic,readonly) CLLocationCoordinate2D coordinate; 25 | @property (nonatomic,retain) NSString *stationID; 26 | @property (nonatomic,retain) NSString *subtitle; 27 | @property (nonatomic,retain) NSString *title; 28 | 29 | - (id)initWithCoords:(CLLocationCoordinate2D)coords; 30 | - (BOOL)isRequested; 31 | - (void)setIsRequested:(BOOL)isRequested; 32 | - (BOOL)isRunning; 33 | - (void)setIsRunning:(BOOL)isRunning; 34 | - (void)setRatio:(float)ratio; 35 | - (float)ratio; 36 | - (void)setNumAvailable:(int)numAvailable; 37 | - (int)numAvailable; 38 | @end 39 | -------------------------------------------------------------------------------- /Shared/SynthesizeSingleton.h: -------------------------------------------------------------------------------- 1 | // 2 | // SynthesizeSingleton.h 3 | // CocoaWithLove 4 | // 5 | // Created by Matt Gallagher on 20/10/08. 6 | // Copyright 2009 Matt Gallagher. All rights reserved. 7 | // 8 | // Permission is given to use this source code file without charge in any 9 | // project, commercial or otherwise, entirely at your risk, with the condition 10 | // that any redistribution (in part or whole) of source code must retain 11 | // this copyright and permission notice. Attribution in compiled projects is 12 | // appreciated but not required. 13 | // 14 | 15 | #define SYNTHESIZE_SINGLETON_FOR_CLASS(classname) \ 16 | \ 17 | static classname *shared##classname = nil; \ 18 | \ 19 | + (classname *)shared##classname \ 20 | { \ 21 | @synchronized(self) \ 22 | { \ 23 | if (shared##classname == nil) \ 24 | { \ 25 | shared##classname = [[self alloc] init]; \ 26 | } \ 27 | } \ 28 | \ 29 | return shared##classname; \ 30 | } \ 31 | \ 32 | + (id)allocWithZone:(NSZone *)zone \ 33 | { \ 34 | @synchronized(self) \ 35 | { \ 36 | if (shared##classname == nil) \ 37 | { \ 38 | shared##classname = [super allocWithZone:zone]; \ 39 | return shared##classname; \ 40 | } \ 41 | } \ 42 | \ 43 | return nil; \ 44 | } \ 45 | \ 46 | - (id)copyWithZone:(NSZone *)zone \ 47 | { \ 48 | return self; \ 49 | } \ 50 | \ 51 | - (id)retain \ 52 | { \ 53 | return self; \ 54 | } \ 55 | \ 56 | - (NSUInteger)retainCount \ 57 | { \ 58 | return NSUIntegerMax; \ 59 | } \ 60 | \ 61 | - (void)release \ 62 | { \ 63 | } \ 64 | \ 65 | - (id)autorelease \ 66 | { \ 67 | return self; \ 68 | } 69 | -------------------------------------------------------------------------------- /Shared/ParseStations.m: -------------------------------------------------------------------------------- 1 | // 2 | // ParseStations.m 3 | // VeloParis 4 | // 5 | // Created by Mengke WANG on 4/2/10. 6 | // Copyright 2010 CocoaBob. All rights reserved. 7 | // 8 | 9 | #import "ParseStations.h" 10 | 11 | #import "SynthesizeSingleton.h" 12 | 13 | @implementation ParseStations 14 | 15 | SYNTHESIZE_SINGLETON_FOR_CLASS(ParseStations); 16 | 17 | - (NSArray *)parseXMLFromData:(NSData *)data parseError:(NSError **)error; 18 | { 19 | mStations = [[NSMutableArray alloc] init]; 20 | 21 | NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; 22 | [parser setDelegate:self]; 23 | 24 | [parser parse]; 25 | 26 | [parser release]; 27 | 28 | return mStations; 29 | } 30 | 31 | - (void)parser:(NSXMLParser *)parser 32 | didStartElement:(NSString *)elementName 33 | namespaceURI:(NSString *)namespaceURI 34 | qualifiedName:(NSString *)qName 35 | attributes:(NSDictionary *)attributeDict{ 36 | if([elementName isEqualToString:@"marker"]) { 37 | mStation = attributeDict; 38 | } 39 | } 40 | 41 | - (void)parser:(NSXMLParser *)parser 42 | didEndElement:(NSString *)elementName 43 | namespaceURI:(NSString *)namespaceURI 44 | qualifiedName:(NSString *)qName{ 45 | if([elementName isEqualToString:@"marker"]) { 46 | [mStations addObject:mStation]; 47 | } 48 | } 49 | 50 | - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError { 51 | /* 52 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Oops" message:[NSString stringWithFormat:@"%@\n%@",NSLocalizedString(@"ParseErrorMessage",nil),[parseError localizedDescription]] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; 53 | [alert show]; 54 | [alert release]; 55 | */ 56 | } 57 | 58 | - (void)dealloc 59 | { 60 | [mStations release]; 61 | [super dealloc]; 62 | } 63 | @end 64 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | ICON.png 13 | CFBundleIconFiles 14 | 15 | ICON.png 16 | ICON-72.png 17 | ICON@2x.png 18 | ICON-72@2x.png 19 | 20 | UIPrerenderedIcon 21 | 22 | CFBundleIdentifier 23 | CocoaBob.${PRODUCT_NAME:rfc1034identifier} 24 | CFBundleInfoDictionaryVersion 25 | 6.0 26 | CFBundleName 27 | ${PRODUCT_NAME} 28 | CFBundlePackageType 29 | APPL 30 | CFBundleSignature 31 | ???? 32 | CFBundleVersion 33 | 2.1 34 | LSRequiresIPhoneOS 35 | 36 | NSMainNibFile 37 | MainWindow_iPhone 38 | NSMainNibFile~ipad 39 | MainWindow_iPad 40 | UISupportedInterfaceOrientations 41 | 42 | UIInterfaceOrientationPortrait 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Shared/ParseStation.m: -------------------------------------------------------------------------------- 1 | // 2 | // ParseStation.m 3 | // VeloParis 4 | // 5 | // Created by Mengke WANG on 4/2/10. 6 | // Copyright 2010 CocoaBob. All rights reserved. 7 | // 8 | 9 | #import "ParseStation.h" 10 | 11 | @implementation ParseStation 12 | 13 | - (NSDictionary *)parseXMLFromData:(NSData *)data parseError:(NSError **)error; 14 | { 15 | NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; 16 | [parser setDelegate:self]; 17 | [parser parse]; 18 | [parser release]; 19 | 20 | return mStation; 21 | } 22 | 23 | - (void)parser:(NSXMLParser *)parser 24 | didStartElement:(NSString *)elementName 25 | namespaceURI:(NSString *)namespaceURI 26 | qualifiedName:(NSString *)qName 27 | attributes:(NSDictionary *)attributeDict{ 28 | if([elementName isEqualToString:@"station"]) { 29 | mStation = [[NSMutableDictionary alloc]init]; 30 | } 31 | 32 | } 33 | 34 | - (void)parser:(NSXMLParser *)parser 35 | didEndElement:(NSString *)elementName 36 | namespaceURI:(NSString *)namespaceURI 37 | qualifiedName:(NSString *)qName{ 38 | if([elementName isEqualToString:@"station"]) { 39 | } 40 | else { 41 | if ([mValue length]>0) { 42 | [mStation setValue:mValue forKey:elementName]; 43 | } 44 | [mValue release]; 45 | } 46 | } 47 | 48 | - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ 49 | mValue = [string retain]; 50 | } 51 | 52 | - (void)dealloc{ 53 | [mStation release]; 54 | [super dealloc]; 55 | } 56 | 57 | - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError { 58 | /* 59 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Oops" message:[NSString stringWithFormat:@"%@\n%@",NSLocalizedString(@"ParseErrorMessage",nil),[parseError localizedDescription]] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; 60 | [alert show]; 61 | [alert release]; 62 | */ 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Shared/StationAnnotation.m: -------------------------------------------------------------------------------- 1 | // 2 | // StationMark.m 3 | // VeloParis 4 | // 5 | // Created by Mengke WANG on 4/2/10. 6 | // Copyright 2010 CocoaBob. All rights reserved. 7 | // 8 | 9 | #import "StationAnnotation.h" 10 | 11 | 12 | @implementation StationAnnotation 13 | 14 | @synthesize coordinate,subtitle,title,stationID; 15 | 16 | -(id)initWithCoords:(CLLocationCoordinate2D)coords{ 17 | self = [super init]; 18 | 19 | coordinate = coords; 20 | 21 | return self; 22 | } 23 | 24 | - (id)initWithCoder:(NSCoder *)coder { 25 | self = [super init]; 26 | if (self) { 27 | coordinate.latitude = [coder decodeDoubleForKey:@"latitude"]; 28 | coordinate.longitude = [coder decodeDoubleForKey:@"longitude"]; 29 | title = [[coder decodeObjectForKey:@"title"] retain]; 30 | stationID = [[coder decodeObjectForKey:@"stationID"] retain]; 31 | } 32 | return self; 33 | } 34 | 35 | - (void)encodeWithCoder:(NSCoder *)coder { 36 | [coder encodeDouble:coordinate.latitude forKey:@"latitude"]; 37 | [coder encodeDouble:coordinate.longitude forKey:@"longitude"]; 38 | [coder encodeObject:title forKey:@"title"]; 39 | [coder encodeObject:stationID forKey:@"stationID"]; 40 | } 41 | 42 | - (void) dealloc{ 43 | [stationID release]; 44 | [title release]; 45 | [subtitle release]; 46 | [super dealloc]; 47 | } 48 | 49 | - (BOOL)isRequested{ 50 | return mIsRequested; 51 | } 52 | 53 | - (void)setIsRequested:(BOOL)isRequested{ 54 | mIsRequested = isRequested; 55 | } 56 | 57 | - (BOOL)isRunning{ 58 | return mIsRunning; 59 | } 60 | 61 | - (void)setIsRunning:(BOOL)isRunning{ 62 | mIsRunning = isRunning; 63 | } 64 | 65 | - (void)setRatio:(float)ratio{ 66 | mRatio = ratio; 67 | } 68 | 69 | - (float)ratio{ 70 | return mRatio; 71 | } 72 | 73 | - (void)setNumAvailable:(int)numAvailable{ 74 | mNumAvailable = numAvailable; 75 | } 76 | 77 | - (int)numAvailable{ 78 | return mNumAvailable; 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /Shared/CustomizedTableCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomizedTableCell.m 3 | // VeloParis 4 | // 5 | // Created by CocoaBob on 10-4-6. 6 | // Copyright 2010 CocoaBob. All rights reserved. 7 | // 8 | 9 | #import "CustomizedTableCell.h" 10 | 11 | 12 | @implementation CustomizedTableCell 13 | 14 | @synthesize mLeftLabel,mRightLabel,mMiddleLabel,mDistanceLabel; 15 | 16 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 17 | if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { 18 | self.selectionStyle = UITableViewCellSelectionStyleNone; 19 | CGRect contentRect = [self.contentView bounds]; 20 | CGRect labelFrame = CGRectMake(contentRect.origin.x + 4, contentRect.origin.y,240, contentRect.size.height - 16); 21 | mLeftLabel = [[UILabel alloc] initWithFrame:labelFrame]; 22 | [mLeftLabel setBackgroundColor:[UIColor clearColor]]; 23 | [mRightLabel setTextAlignment:UITextAlignmentLeft]; 24 | [mLeftLabel setAdjustsFontSizeToFitWidth:YES]; 25 | [mLeftLabel setFont:[UIFont systemFontOfSize:16]]; 26 | [self.contentView addSubview:mLeftLabel]; 27 | 28 | labelFrame = CGRectMake(contentRect.origin.x + 2 + 160, contentRect.origin.y + contentRect.size.height - 18 , 148, 18); 29 | mMiddleLabel = [[UILabel alloc] initWithFrame:labelFrame]; 30 | [mMiddleLabel setBackgroundColor:[UIColor clearColor]]; 31 | [mMiddleLabel setTextAlignment:UITextAlignmentRight]; 32 | [mMiddleLabel setAdjustsFontSizeToFitWidth:YES]; 33 | [mMiddleLabel setFont:[UIFont systemFontOfSize:14]]; 34 | [self.contentView addSubview:mMiddleLabel]; 35 | 36 | labelFrame = CGRectMake(contentRect.origin.x + 10, contentRect.origin.y + contentRect.size.height - 18 , 150, 18); 37 | mDistanceLabel = [[UILabel alloc] initWithFrame:labelFrame]; 38 | [mDistanceLabel setBackgroundColor:[UIColor clearColor]]; 39 | [mDistanceLabel setTextAlignment:UITextAlignmentLeft]; 40 | [mDistanceLabel setAdjustsFontSizeToFitWidth:YES]; 41 | [mDistanceLabel setTextColor:[UIColor grayColor]]; 42 | [mDistanceLabel setFont:[UIFont systemFontOfSize:14]]; 43 | [self.contentView addSubview:mDistanceLabel]; 44 | 45 | labelFrame = CGRectMake(contentRect.origin.x + 3 + mLeftLabel.frame.size.width + 3, contentRect.origin.y, contentRect.size.width - contentRect.origin.x - 3 - mLeftLabel.frame.size.width - 3 - 10, contentRect.size.height - 16); 46 | mRightLabel = [[UILabel alloc] initWithFrame:labelFrame]; 47 | [mRightLabel setBackgroundColor:[UIColor clearColor]]; 48 | [mRightLabel setTextAlignment:UITextAlignmentLeft]; 49 | [mRightLabel setAdjustsFontSizeToFitWidth:YES]; 50 | [mRightLabel setFont:[UIFont systemFontOfSize:14]]; 51 | [self.contentView addSubview:mRightLabel]; 52 | } 53 | return self; 54 | } 55 | 56 | 57 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 58 | [super setSelected:selected animated:animated]; 59 | // Configure the view for the selected state 60 | } 61 | 62 | 63 | - (void)dealloc { 64 | [mMiddleLabel release]; 65 | [mLeftLabel release]; 66 | [mRightLabel release]; 67 | [mDistanceLabel release]; 68 | [super dealloc]; 69 | } 70 | 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /iPad/AppDelegate_iPad.h: -------------------------------------------------------------------------------- 1 | // 2 | // VeloParisAppDelegate.h 3 | // VeloParis 4 | // 5 | // Created by CocoaBob on 10-4-1. 6 | // Copyright CocoaBob 2010. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import "StationAnnotation.h" 13 | #import "ConnectionDelegate.h" 14 | #import "PinAnnotationView.h" 15 | #import "CustomizedTableCell.h" 16 | 17 | @interface AppDelegate_iPad : NSObject { 18 | UIWindow *window; 19 | IBOutlet UIView *mSuperView; 20 | IBOutlet MKMapView *mMapView; 21 | IBOutlet UITableView *mFavoritesTableView; 22 | IBOutlet UITableView *mTableView; 23 | IBOutlet UIView *mSettingView; 24 | IBOutlet UISegmentedControl *mMapTypeSwitch; 25 | IBOutlet UISegmentedControl *mRefreshCacheButton; 26 | IBOutlet UIBarButtonItem *mZoomInButton; 27 | IBOutlet UIBarButtonItem *mZoomOutButton; 28 | IBOutlet UIBarButtonItem *mLocateSelfButton; 29 | IBOutlet UIBarButtonItem *mSettingButton; 30 | IBOutlet UIBarButtonItem *mFavoritesButton; 31 | 32 | CLLocationManager *mLocationManager; 33 | UIImage *mPinGreen; 34 | UIImage *mPinYellowGreen; 35 | UIImage *mPinYellow; 36 | UIImage *mPinOrange; 37 | UIImage *mPinRed; 38 | UIImage *mPinPurple; 39 | NSInteger mRequestCount; 40 | NSInteger mRequestCountForTable; 41 | NSDate *latestThreadTime; 42 | NSDate *latestTableThreadTime; 43 | UIImage *mFavoriteOn; 44 | UIImage *mFavoriteOff; 45 | NSMutableArray *mFavoriteList; 46 | NSMutableDictionary *mAllStationAnnotationData; 47 | BOOL mDidAddAllAnnotations; 48 | BOOL mDidAddUserLocationAnnotation; 49 | UIView *mMKOverlayView; 50 | UIView *mMKMapLevelView; 51 | UIImageView *mUserHeadingView; 52 | BOOL mHasAddedUserHeading; 53 | BOOL mIsHeading; 54 | 55 | NSOperationQueue *mRequestStationStatusOperationQueue; 56 | NSOperationQueue *mRequestVisibleStationStatusOperationQueue; 57 | 58 | BOOL mNeedsUpdateRealTimeStatus; 59 | } 60 | 61 | @property (nonatomic, retain) IBOutlet UIWindow *window; 62 | @property (nonatomic, retain) NSMutableArray *mFavoriteList; 63 | 64 | - (IBAction)doSegmentedControlAction:(id)sender; 65 | - (IBAction)doLocateSelf:(id)sender; 66 | - (IBAction)doZoomIn:(id)sender; 67 | - (IBAction)doZoomOut:(id)sender; 68 | - (IBAction)doSwitchView:(id)sender; 69 | - (IBAction)doSwitchFavoriteButton:(id)sender; 70 | 71 | - (NSArray *)getFavorites; 72 | - (void)saveFavorites; 73 | - (void)addFavorite:(NSString *)stationID; 74 | - (void)removeFavorite:(NSString *)stationID; 75 | - (BOOL)isInFavoriteList:(NSString *)stationID; 76 | - (void)reloadTable; 77 | 78 | - (void)saveLocationLatitude:(double)latitude Longitude:(double)longitude; 79 | - (void)setMapLocation:(CLLocationCoordinate2D)coordinate distance:(double)distance animated:(BOOL)animated; 80 | - (void)addAnnotations; 81 | //- (NSArray *)findVisibleAnnotations:(MKCoordinateRegion)currentRegion; 82 | - (void)threadRequestVisibleAnnotations:(MKMapView *)mapView; 83 | - (void)threadRequestAnnotationsForTable:(NSArray *)annotationArray; 84 | @end 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /iPhone/AppDelegate_iPhone.h: -------------------------------------------------------------------------------- 1 | // 2 | // VeloParisAppDelegate.h 3 | // VeloParis 4 | // 5 | // Created by CocoaBob on 10-4-1. 6 | // Copyright CocoaBob 2010. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import "StationAnnotation.h" 13 | #import "ConnectionDelegate.h" 14 | #import "PinAnnotationView.h" 15 | #import "CustomizedTableCell.h" 16 | 17 | @interface AppDelegate_iPhone : NSObject { 18 | UIWindow *window; 19 | IBOutlet UIView *mSuperView; 20 | IBOutlet MKMapView *mMapView; 21 | IBOutlet UITableView *mFavoritesTableView; 22 | IBOutlet UITableView *mTableView; 23 | IBOutlet UIView *mSettingView; 24 | IBOutlet UISegmentedControl *mMapTypeSwitch; 25 | IBOutlet UISegmentedControl *mRefreshCacheButton; 26 | IBOutlet UIBarButtonItem *mZoomInButton; 27 | IBOutlet UIBarButtonItem *mZoomOutButton; 28 | IBOutlet UIBarButtonItem *mLocateSelfButton; 29 | IBOutlet UIBarButtonItem *mSettingButton; 30 | IBOutlet UIBarButtonItem *mFavoritesButton; 31 | 32 | CLLocationManager *mLocationManager; 33 | UIImage *mPinGreen; 34 | UIImage *mPinYellowGreen; 35 | UIImage *mPinYellow; 36 | UIImage *mPinOrange; 37 | UIImage *mPinRed; 38 | UIImage *mPinPurple; 39 | NSInteger mRequestCount; 40 | NSInteger mRequestCountForTable; 41 | NSDate *latestThreadTime; 42 | NSDate *latestTableThreadTime; 43 | UIImage *mFavoriteOn; 44 | UIImage *mFavoriteOff; 45 | NSMutableArray *mFavoriteList; 46 | NSMutableDictionary *mAllStationAnnotationData; 47 | BOOL mDidAddAllAnnotations; 48 | BOOL mDidAddUserLocationAnnotation; 49 | UIView *mMKOverlayView; 50 | UIView *mMKMapLevelView; 51 | UIImageView *mUserHeadingView; 52 | BOOL mHasAddedUserHeading; 53 | BOOL mIsHeading; 54 | 55 | NSOperationQueue *mRequestStationStatusOperationQueue; 56 | NSOperationQueue *mRequestVisibleStationStatusOperationQueue; 57 | 58 | BOOL mNeedsUpdateRealTimeStatus; 59 | 60 | NSInteger mOperationsCountForMap; 61 | NSInteger mOperationsCountForTable; 62 | } 63 | 64 | @property (nonatomic, retain) IBOutlet UIWindow *window; 65 | @property (nonatomic, retain) NSMutableArray *mFavoriteList; 66 | 67 | - (IBAction)doSegmentedControlAction:(id)sender; 68 | - (IBAction)doLocateSelf:(id)sender; 69 | - (IBAction)doZoomIn:(id)sender; 70 | - (IBAction)doZoomOut:(id)sender; 71 | - (IBAction)doSwitchView:(id)sender; 72 | - (IBAction)doSwitchFavoriteButton:(id)sender; 73 | 74 | - (NSArray *)getFavorites; 75 | - (void)saveFavorites; 76 | - (void)addFavorite:(NSString *)stationID; 77 | - (void)removeFavorite:(NSString *)stationID; 78 | - (BOOL)isInFavoriteList:(NSString *)stationID; 79 | - (void)reloadTable; 80 | 81 | - (void)saveLocationLatitude:(double)latitude Longitude:(double)longitude; 82 | - (void)setMapLocation:(CLLocationCoordinate2D)coordinate distance:(double)distance animated:(BOOL)animated; 83 | - (void)addAnnotations; 84 | //- (NSArray *)findVisibleAnnotations:(MKCoordinateRegion)currentRegion; 85 | - (void)threadRequestVisibleAnnotations:(MKMapView *)mapView; 86 | - (void)threadRequestAnnotationsForTable:(NSArray *)annotationArray; 87 | @end 88 | 89 | -------------------------------------------------------------------------------- /Shared/ConnectionDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ConnectionDelegate.m 3 | // VeloParis 4 | // 5 | // Created by Mengke WANG on 4/2/10. 6 | // Copyright 2010 CocoaBob. All rights reserved. 7 | // 8 | 9 | #import "ConnectionDelegate.h" 10 | #import "SynthesizeSingleton.h" 11 | 12 | 13 | @implementation ConnectionDelegate 14 | 15 | SYNTHESIZE_SINGLETON_FOR_CLASS(ConnectionDelegate); 16 | 17 | - (void)dealloc{ 18 | [receivedData release]; 19 | [super dealloc]; 20 | } 21 | 22 | - (NSMutableData *)receivedData{ 23 | if (!receivedData) { 24 | receivedData = [[NSMutableData alloc] init]; 25 | } 26 | return receivedData; 27 | } 28 | 29 | - (void)getAllStations{ 30 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 31 | NSString *queryString = @"http://www.velib.paris.fr/service/carto"; 32 | NSURL *url = [NSURL URLWithString:queryString]; 33 | NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url]; 34 | [req setHTTPMethod:@"GET"]; 35 | [NSURLConnection connectionWithRequest:req delegate:self]; 36 | } 37 | 38 | #pragma mark - 39 | #pragma mark NSURLConnection 40 | 41 | - (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ 42 | [self.receivedData setLength:0]; 43 | } 44 | 45 | - (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{ 46 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 47 | } 48 | 49 | - (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 50 | { 51 | [self.receivedData appendData:data]; 52 | } 53 | 54 | - (void) connectionDidFinishLoading:(NSURLConnection *)connection{ 55 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 56 | NSArray *parsedArray = [[ParseStations sharedParseStations] parseXMLFromData:self.receivedData parseError:nil]; 57 | 58 | [NSThread detachNewThreadSelector:@selector(threadParseAnnotations:) toTarget:self withObject:parsedArray]; 59 | } 60 | 61 | #pragma mark - 62 | #pragma mark Methods 63 | 64 | - (StationAnnotation *)createAnnotationFromDic:(NSDictionary *)oneStation{ 65 | double latitude = [[oneStation valueForKey:@"lat"] doubleValue]; 66 | double longitude = [[oneStation valueForKey:@"lng"] doubleValue]; 67 | if (latitude && longitude) { 68 | CLLocationCoordinate2D coordinate; 69 | coordinate.latitude = latitude; 70 | coordinate.longitude = longitude; 71 | StationAnnotation *stationAnnotation = [[StationAnnotation alloc] initWithCoords:coordinate]; 72 | [stationAnnotation setStationID:[oneStation valueForKey:@"number"]]; 73 | [stationAnnotation setTitle:[oneStation valueForKey:@"name"]]; 74 | return [stationAnnotation autorelease]; 75 | } 76 | return nil; 77 | } 78 | 79 | - (void)threadParseAnnotations:(NSArray *)allStationsData{ 80 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 81 | NSMutableDictionary *allStationAnnotationData = [[NSMutableDictionary alloc] init]; 82 | 83 | for (NSDictionary *oneStation in allStationsData) { 84 | StationAnnotation *oneStationAnnotation = [self createAnnotationFromDic:oneStation]; 85 | if (oneStationAnnotation) { 86 | [allStationAnnotationData setObject:oneStationAnnotation forKey:[oneStation valueForKey:@"number"]]; 87 | } 88 | } 89 | 90 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 91 | NSString *documentsDirectory = [paths objectAtIndex:0]; 92 | NSString *path = [documentsDirectory stringByAppendingPathComponent:@"AllStationAnnotationsDic.bin"]; 93 | 94 | if ([NSKeyedArchiver archiveRootObject:allStationAnnotationData toFile:path]) { 95 | [[NSNotificationCenter defaultCenter] postNotificationName:@"addAnnotationsNotification" object:nil]; 96 | } 97 | [allStationAnnotationData release]; 98 | 99 | [pool release]; 100 | [NSThread exit]; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /iPad/AppDelegate_iPad.m: -------------------------------------------------------------------------------- 1 | // 2 | // VeloParisAppDelegate.m 3 | // VeloParis 4 | // 5 | // Created by CocoaBob on 10-4-1. 6 | // Copyright CocoaBob 2010. All rights reserved. 7 | // 8 | #define DEGREES_TO_RADIANS(__ANGLE) ((__ANGLE) * M_PI / 180.0) 9 | #define RADIANS_TO_DEGREES(__RADIANS) ((__RADIANS) * 180 / M_PI) 10 | 11 | #import "AppDelegate_iPad.h" 12 | 13 | @interface AppDelegate_iPad() 14 | 15 | - (void)saveLocationLatitude:(double)latitude Longitude:(double)longitude; 16 | 17 | @end 18 | 19 | 20 | @implementation AppDelegate_iPad 21 | 22 | @synthesize window,mFavoriteList; 23 | 24 | - (void)awakeFromNib{ 25 | [[NSNotificationCenter defaultCenter] addObserver:self 26 | selector:@selector(addAnnotationsNotification:) 27 | name:@"addAnnotationsNotification" 28 | object:nil]; 29 | 30 | //Why retain? If not, these images will be release when the application goes into background 31 | mPinGreen = [[UIImage imageNamed:@"pinGreen.png"] retain]; 32 | mPinYellowGreen = [[UIImage imageNamed:@"pinYellowGreen.png"] retain]; 33 | mPinYellow = [[UIImage imageNamed:@"pinYellow.png"] retain]; 34 | mPinOrange = [[UIImage imageNamed:@"pinOrange.png"] retain]; 35 | mPinRed = [[UIImage imageNamed:@"pinRed.png"] retain]; 36 | mPinPurple = [[UIImage imageNamed:@"pinPurple.png"] retain]; 37 | mFavoriteOn = [[UIImage imageNamed:@"FavoriteOn.png"] retain]; 38 | mFavoriteOff = [[UIImage imageNamed:@"FavoriteOff.png"] retain]; 39 | } 40 | 41 | - (void)dealloc { 42 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 43 | [mLocationManager release]; 44 | [window release]; 45 | [latestThreadTime release]; 46 | [mAllStationAnnotationData release]; 47 | [mUserHeadingView release]; 48 | [mPinGreen release]; 49 | [mPinYellowGreen release]; 50 | [mPinYellow release]; 51 | [mPinOrange release]; 52 | [mPinRed release]; 53 | [mPinPurple release]; 54 | [mFavoriteOn release]; 55 | [mFavoriteOff release]; 56 | [mRequestStationStatusOperationQueue release]; 57 | [mRequestVisibleStationStatusOperationQueue release]; 58 | [super dealloc]; 59 | } 60 | 61 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 62 | if (![[NSUserDefaults standardUserDefaults] boolForKey:kIsNotFirstTimeLaunch]) { 63 | [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionary]]; 64 | [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kIsNotFirstTimeLaunch]; 65 | [self saveLocationLatitude:48.856660f Longitude:2.350996f];//Paris 66 | } 67 | 68 | mRequestStationStatusOperationQueue = [[NSOperationQueue alloc] init]; 69 | [mRequestStationStatusOperationQueue setMaxConcurrentOperationCount:10]; 70 | 71 | mRequestVisibleStationStatusOperationQueue = [[NSOperationQueue alloc] init]; 72 | [mRequestStationStatusOperationQueue setMaxConcurrentOperationCount:2]; 73 | 74 | mLocationManager = [[CLLocationManager alloc] init]; 75 | [mLocationManager setDelegate:self]; 76 | [mLocationManager setHeadingFilter:1]; 77 | 78 | self.mFavoriteList = [[self getFavorites] mutableCopy]; 79 | if (!self.mFavoriteList) { 80 | self.mFavoriteList = [[NSMutableArray alloc] init]; 81 | } 82 | 83 | double latitude = [[[NSUserDefaults standardUserDefaults] valueForKey:kLastLocationLatitude] doubleValue]; 84 | double longitude = [[[NSUserDefaults standardUserDefaults] valueForKey:kLastLocationLongitude] doubleValue]; 85 | 86 | CLLocationCoordinate2D coordinate; 87 | 88 | coordinate.latitude = latitude; 89 | coordinate.longitude = longitude; 90 | 91 | [self setMapLocation:coordinate distance:500 animated:NO]; 92 | 93 | [mMapView setShowsUserLocation:YES]; 94 | [mMapView setMapType:[[NSUserDefaults standardUserDefaults] integerForKey:kMapType]]; 95 | 96 | [mMapTypeSwitch setSelectedSegmentIndex:[[NSUserDefaults standardUserDefaults] integerForKey:kMapType]]; 97 | 98 | [mTableView setDataSource:self]; 99 | [window makeKeyAndVisible]; 100 | 101 | [self addAnnotations]; 102 | 103 | return YES; 104 | } 105 | 106 | - (void)applicationDidBecomeActive:(UIApplication *)application{ 107 | if (mDidAddAllAnnotations) { 108 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestVisibleAnnotations:) object:mMapView]; 109 | // [theOp setThreadPriority:0.01f]; 110 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 111 | [theOp release]; 112 | } 113 | 114 | [self doLocateSelf:self]; 115 | } 116 | 117 | - (void)applicationWillEnterForeground:(UIApplication *)application{ 118 | [[NSUserDefaults standardUserDefaults] synchronize]; 119 | 120 | NSArray *allAnnotations = [[NSArray alloc]initWithArray:[mMapView annotations]]; 121 | for (StationAnnotation *stationAnnotation in allAnnotations) 122 | { 123 | if (![stationAnnotation isKindOfClass:[MKUserLocation class]]) { 124 | [stationAnnotation setIsRequested:NO]; 125 | } 126 | } 127 | [allAnnotations release]; 128 | } 129 | 130 | #pragma mark - 131 | #pragma mark CLLocationManagerDelegate 132 | 133 | - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{ 134 | [mMapView setCenterCoordinate:newLocation.coordinate animated:YES]; 135 | [mLocationManager stopUpdatingLocation]; 136 | } 137 | 138 | - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{ 139 | [mLocationManager stopUpdatingLocation]; 140 | [mLocationManager stopUpdatingHeading]; 141 | mIsHeading = NO; 142 | [mUserHeadingView setHidden:YES]; 143 | [[mMapView viewForAnnotation:[mMapView userLocation]] setTransform:CGAffineTransformIdentity]; 144 | /* 145 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Oops" message:[NSString stringWithFormat:@"%@",NSLocalizedString(@"LocationManagerErrorMessage",nil)] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; 146 | [alert show]; 147 | [alert release]; 148 | */ 149 | } 150 | 151 | - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{ 152 | float headingAccuracy = [newHeading trueHeading]; 153 | if (headingAccuracy > 0) { 154 | //CGAffineTransform mapTransform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(headingAccuracy)*-1);//如果你想整个屏幕一起跟着旋转 155 | CGAffineTransform pinTransform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(headingAccuracy)); 156 | //[mMapView viewForAnnotation:[mMapView userLocation]].transform = pinTransform; 157 | mUserHeadingView.transform = pinTransform; 158 | [mUserHeadingView setHidden:NO]; 159 | 160 | /*如果你想整个屏幕一起跟着旋转 161 | for (UIView *subView in [mMapView subviews]) { 162 | //NSLog(@"%@",[subView description]); 163 | if(![[[subView class] description] isEqualToString:@"UIImageView"]){ 164 | subView.transform = mapTransform; 165 | } 166 | } 167 | 168 | for (StationAnnotation *annotation in [mAllStationAnnotationData allValues]) { 169 | [mMapView viewForAnnotation:annotation].transform = pinTransform; 170 | } 171 | */ 172 | } 173 | } 174 | 175 | - (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager{//遇到电磁干扰时,是否弹出按8字形摆动iPhone校准指南针的界面。 176 | return YES; 177 | } 178 | 179 | #pragma mark - 180 | #pragma mark Variables 181 | 182 | - (UIImageView *)userHeadingView{ 183 | if (!mUserHeadingView) { 184 | UIImage *imageUserHeading = [UIImage imageNamed:@"UserHeading.png"]; 185 | mUserHeadingView = [[UIImageView alloc] initWithImage:imageUserHeading]; 186 | [mUserHeadingView setHidden:YES]; 187 | } 188 | return mUserHeadingView; 189 | } 190 | 191 | #pragma mark - 192 | #pragma mark MKMapViewDelegate 193 | 194 | - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{ 195 | [self saveLocationLatitude:mapView.centerCoordinate.latitude Longitude:mapView.centerCoordinate.longitude]; 196 | if (mDidAddAllAnnotations) { 197 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestVisibleAnnotations:) object:mapView]; 198 | // [theOp setThreadPriority:0.01f]; 199 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 200 | [theOp release]; 201 | } 202 | /*如果你想整个屏幕都转动的话,需要在UserLocation离开屏幕中心时停止旋转屏幕……我找不到更好的算法了…… 203 | CLLocationCoordinate2D centerCoordinate = [mMapView centerCoordinate]; 204 | CLLocationCoordinate2D userCoordinate = [mMapView userLocation].coordinate; 205 | if (centerCoordinate.latitude != userCoordinate.latitude && 206 | centerCoordinate.longitude != userCoordinate.longitude) { 207 | [mUserHeadingView setHidden:YES]; 208 | [mLocationManager stopUpdatingHeading]; 209 | } 210 | for (UIView *subView in [mMapView subviews]) { 211 | if(![[[subView class] description] isEqualToString:@"UIImageView"]){ 212 | subView.transform = CGAffineTransformIdentity; 213 | } 214 | } 215 | 216 | for (StationAnnotation *annotation in [mAllStationAnnotationData allValues]) { 217 | [mMapView viewForAnnotation:annotation].transform = CGAffineTransformIdentity; 218 | } 219 | */ 220 | } 221 | 222 | - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation { 223 | if([annotation isKindOfClass:[StationAnnotation class]]){//[annotation isKindOfClass:[StationAnnotation class]]//[annotation isKindOfClass:[MKUserLocation class]] 224 | StationAnnotation *oneStationAnnotation = (StationAnnotation *)annotation; 225 | PinAnnotationView *pinAnnotationView = [(PinAnnotationView *) [mMapView dequeueReusableAnnotationViewWithIdentifier:@"PinAnnotationView"] retain]; 226 | if (!pinAnnotationView) { 227 | pinAnnotationView = [[PinAnnotationView alloc] initWithAnnotation:oneStationAnnotation reuseIdentifier:@"PinAnnotationView"]; 228 | [pinAnnotationView setImage:mPinPurple]; 229 | 230 | UIButton *leftCalloutAccessoryView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 24, 24)]; 231 | if ([self isInFavoriteList:[oneStationAnnotation stationID]]) { 232 | [leftCalloutAccessoryView setImage:mFavoriteOn forState:UIControlStateNormal]; 233 | } 234 | else { 235 | [leftCalloutAccessoryView setImage:mFavoriteOff forState:UIControlStateNormal]; 236 | } 237 | [leftCalloutAccessoryView addTarget:self action:@selector(doSwitchFavoriteButton:) forControlEvents:UIControlEventTouchUpInside]; 238 | [pinAnnotationView setLeftCalloutAccessoryView:leftCalloutAccessoryView]; 239 | [leftCalloutAccessoryView release]; 240 | } 241 | else { 242 | [pinAnnotationView setAnnotation:oneStationAnnotation]; 243 | } 244 | 245 | return [pinAnnotationView autorelease]; 246 | } 247 | 248 | return nil;//Return nil to show the MKUserLocation 249 | } 250 | 251 | - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control{ 252 | NSString *stationID = [(StationAnnotation *)[view annotation] stationID]; 253 | if ([self isInFavoriteList:stationID]) { 254 | [(UIButton *)control setImage:mFavoriteOn forState:UIControlStateNormal]; 255 | } 256 | else { 257 | [(UIButton *)control setImage:mFavoriteOff forState:UIControlStateNormal]; 258 | } 259 | } 260 | 261 | - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views{ 262 | if ([views count]>1) { 263 | mDidAddAllAnnotations = YES; 264 | if ([[mSuperView subviews]lastObject] == mTableView) { 265 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestAnnotationsForTable:) object:self.mFavoriteList]; 266 | // [theOp setThreadPriority:0.01f]; 267 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 268 | [theOp release]; 269 | } 270 | else if ([[mSuperView subviews]lastObject] == mMapView) { 271 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestVisibleAnnotations:) object:mapView]; 272 | // [theOp setThreadPriority:0.01f]; 273 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 274 | [theOp release]; 275 | } 276 | 277 | [self reloadTable]; 278 | } 279 | 280 | UIView *userLocationView = [mMapView viewForAnnotation:[mMapView userLocation]]; 281 | if (userLocationView) { 282 | UIImageView *imageView = [self userHeadingView]; 283 | [imageView setFrame:CGRectMake(userLocationView.frame.origin.x + (userLocationView.frame.size.width - imageView.frame.size.width)/2, userLocationView.frame.origin.y + (userLocationView.frame.size.height - imageView.frame.size.height)/2, imageView.frame.size.width, imageView.frame.size.height)]; 284 | [userLocationView addSubview:imageView]; 285 | mDidAddUserLocationAnnotation = YES; 286 | } 287 | } 288 | 289 | #pragma mark - 290 | #pragma mark Actions 291 | 292 | - (IBAction)doLocateSelf:(id)sender{ 293 | CGPoint userLocationPoint = [mMapView convertCoordinate:[mMapView userLocation].coordinate toPointToView:mMapView]; 294 | if ([mLocationManager locationServicesEnabled]) { 295 | [mLocationManager startUpdatingLocation]; 296 | } 297 | if ([mLocationManager headingAvailable] && mDidAddUserLocationAnnotation) { 298 | if (userLocationPoint.x > 159.0f && userLocationPoint.x < 161.0f && 299 | userLocationPoint.y > 207.0f && userLocationPoint.y < 209.0f){ 300 | if (!mIsHeading) { 301 | [mLocationManager startUpdatingHeading]; 302 | mIsHeading = YES; 303 | } 304 | else { 305 | [mLocationManager stopUpdatingHeading]; 306 | mIsHeading = NO; 307 | [mUserHeadingView setHidden:YES]; 308 | [[mMapView viewForAnnotation:[mMapView userLocation]] setTransform:CGAffineTransformIdentity]; 309 | } 310 | } 311 | } 312 | } 313 | 314 | - (IBAction)doZoomIn:(id)sender{ 315 | MKCoordinateRegion region = mMapView.region; 316 | region.span.latitudeDelta=region.span.latitudeDelta * 0.4; 317 | region.span.longitudeDelta=region.span.longitudeDelta * 0.4; 318 | [mMapView setRegion:region animated:YES]; 319 | } 320 | 321 | - (IBAction)doZoomOut:(id)sender{ 322 | MKCoordinateRegion region = mMapView.region; 323 | region.span.latitudeDelta=region.span.latitudeDelta * 1.3; 324 | region.span.longitudeDelta=region.span.longitudeDelta * 1.3; 325 | [mMapView setRegion:region animated:YES]; 326 | } 327 | 328 | - (IBAction)doSwitchView:(id)sender{ 329 | [UIView beginAnimations:@"animationID" context:nil]; 330 | [UIView setAnimationDuration:0.3f]; 331 | [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; 332 | [UIView setAnimationRepeatAutoreverses:NO]; 333 | if ([[mSuperView subviews]lastObject]!=mMapView) { 334 | [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:mSuperView cache:YES]; 335 | if (mDidAddAllAnnotations) { 336 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestVisibleAnnotations:) object:mMapView]; 337 | // [theOp setThreadPriority:0.01f]; 338 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 339 | [theOp release]; 340 | } 341 | [mSuperView bringSubviewToFront:mMapView]; 342 | [mZoomOutButton setEnabled:YES]; 343 | [mZoomInButton setEnabled:YES]; 344 | [mLocateSelfButton setEnabled:YES]; 345 | [mSettingButton setEnabled:YES]; 346 | [mFavoritesButton setEnabled:YES]; 347 | } 348 | else if(![sender isKindOfClass:[AppDelegate_iPad class]]){ 349 | switch ([sender tag]) { 350 | case 0: 351 | [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:mSuperView cache:YES]; 352 | if (mDidAddAllAnnotations) { 353 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestAnnotationsForTable:) object:self.mFavoriteList]; 354 | // [theOp setThreadPriority:0.01f]; 355 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 356 | [theOp release]; 357 | } 358 | [self reloadTable]; 359 | [mSettingButton setEnabled:NO]; 360 | [mFavoritesButton setEnabled:YES]; 361 | [mSuperView bringSubviewToFront:mTableView]; 362 | break; 363 | case 1: 364 | [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:mSuperView cache:YES]; 365 | [mSettingButton setEnabled:YES]; 366 | [mFavoritesButton setEnabled:NO]; 367 | [mSuperView bringSubviewToFront:mSettingView]; 368 | break; 369 | default: 370 | break; 371 | } 372 | [mZoomOutButton setEnabled:NO]; 373 | [mZoomInButton setEnabled:NO]; 374 | [mLocateSelfButton setEnabled:NO]; 375 | } 376 | 377 | [UIView commitAnimations]; 378 | } 379 | 380 | - (IBAction)doSegmentedControlAction:(id)sender{ 381 | if (sender == mMapTypeSwitch) { 382 | switch (((UISegmentedControl *)sender).selectedSegmentIndex) 383 | { 384 | case 0: 385 | { 386 | mMapView.mapType = MKMapTypeStandard; 387 | [[NSUserDefaults standardUserDefaults] setInteger:MKMapTypeStandard forKey:kMapType]; 388 | break; 389 | } 390 | case 1: 391 | { 392 | mMapView.mapType = MKMapTypeSatellite; 393 | [[NSUserDefaults standardUserDefaults] setInteger:MKMapTypeSatellite forKey:kMapType]; 394 | break; 395 | } 396 | default: 397 | { 398 | mMapView.mapType = MKMapTypeHybrid; 399 | [[NSUserDefaults standardUserDefaults] setInteger:MKMapTypeHybrid forKey:kMapType]; 400 | break; 401 | } 402 | } 403 | } 404 | else if(sender == mRefreshCacheButton){ 405 | [mMapView removeAnnotations:[mMapView annotations]]; 406 | [[ConnectionDelegate sharedConnectionDelegate] getAllStations]; 407 | } 408 | [self doSwitchView:self]; 409 | } 410 | 411 | - (IBAction)doSwitchFavoriteButton:(id)sender{ 412 | PinAnnotationView *pinAnnotationView = (PinAnnotationView *)[[sender superview] superview]; 413 | StationAnnotation *stationAnnotation = (StationAnnotation *)[pinAnnotationView annotation]; 414 | NSString *stationID = [stationAnnotation stationID]; 415 | 416 | if ([self isInFavoriteList:stationID]) { 417 | [self removeFavorite:stationID]; 418 | [(UIButton *)sender setImage:mFavoriteOff forState:UIControlStateNormal]; 419 | } 420 | else { 421 | [self addFavorite:stationID]; 422 | [(UIButton *)sender setImage:mFavoriteOn forState:UIControlStateNormal]; 423 | } 424 | } 425 | 426 | #pragma mark - 427 | #pragma mark Methods 428 | 429 | - (void)addFavorite:(NSString *)stationID{ 430 | if (![self.mFavoriteList containsObject:stationID]) { 431 | [self.mFavoriteList addObject:stationID]; 432 | [self saveFavorites]; 433 | } 434 | } 435 | 436 | - (void)removeFavorite:(NSString *)stationID{ 437 | if ([self.mFavoriteList containsObject:stationID]) { 438 | [self.mFavoriteList removeObject:stationID]; 439 | [self saveFavorites]; 440 | } 441 | } 442 | 443 | - (BOOL)isInFavoriteList:(NSString *)stationID{ 444 | return [self.mFavoriteList containsObject:stationID]; 445 | } 446 | 447 | - (void)saveLocationLatitude:(double)latitude Longitude:(double)longitude{ 448 | NSNumber *locationLatitude = [NSNumber numberWithDouble:latitude]; 449 | NSNumber *locationLongitude = [NSNumber numberWithDouble:longitude]; 450 | [[NSUserDefaults standardUserDefaults] setValue:locationLatitude forKey:kLastLocationLatitude]; 451 | [[NSUserDefaults standardUserDefaults] setValue:locationLongitude forKey:kLastLocationLongitude]; 452 | } 453 | 454 | - (void)setMapLocation:(CLLocationCoordinate2D)coordinate distance:(double)distance animated:(BOOL)animated{ 455 | [self saveLocationLatitude:coordinate.latitude Longitude:coordinate.longitude ]; 456 | MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(coordinate, distance, distance); 457 | MKCoordinateRegion adjustedRegion = [mMapView regionThatFits:viewRegion]; 458 | [mMapView setRegion:adjustedRegion animated:animated]; 459 | } 460 | 461 | - (void)addAnnotations{ 462 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 463 | NSString *documentsDirectory = [paths objectAtIndex:0]; 464 | NSString *path = [documentsDirectory stringByAppendingPathComponent:@"AllStationAnnotationsDic.bin"]; 465 | 466 | if (mAllStationAnnotationData) { 467 | [mAllStationAnnotationData release]; 468 | mAllStationAnnotationData= nil; 469 | } 470 | 471 | mAllStationAnnotationData = [[NSKeyedUnarchiver unarchiveObjectWithFile:path] retain]; 472 | 473 | if (mAllStationAnnotationData) { 474 | mDidAddAllAnnotations = NO; 475 | NSArray *oldAnnotations = [mMapView annotations]; 476 | if (oldAnnotations) { 477 | [mMapView removeAnnotations:oldAnnotations]; 478 | } 479 | 480 | [mMapView addAnnotations:[mAllStationAnnotationData allValues]]; 481 | } 482 | else { 483 | [[ConnectionDelegate sharedConnectionDelegate] getAllStations]; 484 | } 485 | 486 | } 487 | 488 | - (void)setAnnotationView:(StationAnnotation *)stationAnnotation strAvailable:(NSString *)strAvailable strFree:(NSString *)strFree strTotal:(NSString *)strTotal{ 489 | [stationAnnotation setSubtitle:[NSString stringWithFormat:@" %@ / %@",strAvailable,strTotal]]; 490 | 491 | PinAnnotationView *pinAnnotationView = (PinAnnotationView *)[mMapView viewForAnnotation:stationAnnotation]; 492 | 493 | float numFree = [strFree floatValue]; 494 | float numAvailable = [strAvailable floatValue]; 495 | float ratio = numAvailable / (numAvailable + numFree); 496 | [stationAnnotation setRatio:ratio]; 497 | [stationAnnotation setNumAvailable:numAvailable]; 498 | if (pinAnnotationView) { 499 | if (numAvailable < 2) { 500 | [pinAnnotationView performSelectorOnMainThread:@selector(setImage:) withObject:mPinRed waitUntilDone:NO]; 501 | } 502 | else if(ratio < 0.25f) { 503 | [pinAnnotationView performSelectorOnMainThread:@selector(setImage:) withObject:mPinOrange waitUntilDone:NO]; 504 | } 505 | else if(ratio >= 0.25f && ratio < 0.50f) { 506 | [pinAnnotationView performSelectorOnMainThread:@selector(setImage:) withObject:mPinYellow waitUntilDone:NO]; 507 | } 508 | else if(ratio >= 0.50f && ratio < 1.0f) { 509 | [pinAnnotationView performSelectorOnMainThread:@selector(setImage:) withObject:mPinYellowGreen waitUntilDone:NO]; 510 | } 511 | else{ 512 | [pinAnnotationView performSelectorOnMainThread:@selector(setImage:) withObject:mPinGreen waitUntilDone:NO]; 513 | } 514 | } 515 | else { 516 | NSLog(@"not created yet"); 517 | } 518 | } 519 | 520 | - (void)threadSetAnnotationSubTitle:(StationAnnotation *)stationAnnotation{ 521 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:([[mRequestStationStatusOperationQueue operations] count] > 1)]; 522 | 523 | NSData *responseData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.velib.paris.fr/service/stationdetails/%@",[stationAnnotation stationID]]]]; 524 | if (responseData) { 525 | ParseStation *parser = [[ParseStation alloc] init]; 526 | NSDictionary *infoDic = [parser parseXMLFromData:responseData parseError:nil]; 527 | [self setAnnotationView:stationAnnotation strAvailable:[infoDic valueForKey:@"available"] strFree:[infoDic valueForKey:@"free"] strTotal:[infoDic valueForKey:@"total"]]; 528 | [stationAnnotation setIsRequested:YES];//Avoid being requested again 529 | [parser release]; 530 | } 531 | 532 | if ([[mRequestStationStatusOperationQueue operations] count] == 1) { 533 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 534 | [mMapView setNeedsDisplay]; 535 | } 536 | } 537 | 538 | - (void)threadRequestVisibleAnnotations:(MKMapView *)mapView{ 539 | MKCoordinateRegion currentRegion = mapView.region; 540 | CLLocationCoordinate2D currentCenter = currentRegion.center; 541 | MKCoordinateSpan currentSpan = currentRegion.span; 542 | 543 | double latitudeRadius = currentSpan.latitudeDelta/2; 544 | double longitudeRadius = currentSpan.longitudeDelta/2; 545 | 546 | [mRequestStationStatusOperationQueue cancelAllOperations]; 547 | NSArray *allAnnotations = [[NSArray alloc]initWithArray:[mMapView annotations]]; 548 | for (StationAnnotation *stationAnnotation in allAnnotations) 549 | { 550 | if (![stationAnnotation isKindOfClass:[MKUserLocation class]] && 551 | ![stationAnnotation isRequested] && 552 | stationAnnotation.coordinate.latitude >= currentCenter.latitude - latitudeRadius&& 553 | stationAnnotation.coordinate.latitude <= currentCenter.latitude + latitudeRadius && 554 | stationAnnotation.coordinate.longitude >= currentCenter.longitude - longitudeRadius&& 555 | stationAnnotation.coordinate.longitude <= currentCenter.longitude + longitudeRadius) { 556 | 557 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadSetAnnotationSubTitle:) object:stationAnnotation]; 558 | // [theOp setThreadPriority:0.01f]; 559 | [mRequestStationStatusOperationQueue addOperation:theOp]; 560 | [theOp release]; 561 | } 562 | } 563 | 564 | [allAnnotations release]; 565 | } 566 | 567 | - (void)threadSetAnnotationSubTitleForTable:(StationAnnotation *)stationAnnotation{ 568 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:([[mRequestStationStatusOperationQueue operations] count] > 1)]; 569 | 570 | NSData *responseData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.velib.paris.fr/service/stationdetails/%@",[stationAnnotation stationID]]]]; 571 | if (responseData) { 572 | ParseStation *parser = [[ParseStation alloc] init]; 573 | NSDictionary *infoDic = [parser parseXMLFromData:responseData parseError:nil]; 574 | [self setAnnotationView:stationAnnotation strAvailable:[infoDic valueForKey:@"available"] strFree:[infoDic valueForKey:@"free"] strTotal:[infoDic valueForKey:@"total"]]; 575 | [stationAnnotation setIsRequested:YES];//Avoid being requested again 576 | [parser release]; 577 | } 578 | 579 | if ([[mRequestStationStatusOperationQueue operations] count] == 1) { 580 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 581 | [self performSelectorOnMainThread:@selector(reloadTable) withObject:nil waitUntilDone:NO]; 582 | } 583 | } 584 | 585 | - (void)threadRequestAnnotationsForTable:(NSArray *)stationIDArray{ 586 | [mRequestStationStatusOperationQueue cancelAllOperations]; 587 | for (NSString *stationID in stationIDArray) 588 | { 589 | StationAnnotation *stationAnnotation = [mAllStationAnnotationData valueForKey:stationID]; 590 | 591 | if (![stationAnnotation isKindOfClass:[MKUserLocation class]] && 592 | ![stationAnnotation isRequested]) { 593 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadSetAnnotationSubTitleForTable:) object:stationAnnotation]; 594 | // [theOp setThreadPriority:0.01f]; 595 | [mRequestStationStatusOperationQueue addOperation:theOp]; 596 | [theOp release]; 597 | } 598 | } 599 | } 600 | 601 | - (NSArray *)getFavorites{ 602 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 603 | NSString *documentsDirectory = [paths objectAtIndex:0]; 604 | NSString *path = [documentsDirectory stringByAppendingPathComponent:@"favorites.plist"]; 605 | return [NSArray arrayWithContentsOfFile:path]; 606 | } 607 | 608 | - (void)saveFavorites{ 609 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 610 | NSString *documentsDirectory = [paths objectAtIndex:0]; 611 | NSString *path = [documentsDirectory stringByAppendingPathComponent:@"favorites.plist"]; 612 | [self.mFavoriteList writeToFile:path atomically:YES]; 613 | } 614 | 615 | - (void)reloadTable{ 616 | [mTableView reloadData]; 617 | [mTableView setNeedsDisplay]; 618 | } 619 | 620 | #pragma mark - 621 | #pragma mark Notifications 622 | 623 | - (void)addAnnotationsNotification:(NSNotification *)notification{ 624 | [self addAnnotations]; 625 | } 626 | 627 | #pragma mark - 628 | #pragma mark Table view data source 629 | 630 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 631 | // Return the number of sections. 632 | return 1; 633 | } 634 | 635 | 636 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 637 | if (mAllStationAnnotationData) { 638 | return [self.mFavoriteList count]; 639 | } 640 | else { 641 | return 0; 642 | } 643 | } 644 | 645 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 646 | static NSString *CellIdentifier = @"Cell"; 647 | 648 | CustomizedTableCell *cell = (CustomizedTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 649 | if (cell == nil) { 650 | cell = [[[CustomizedTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 651 | } 652 | else { 653 | [[cell mMiddleLabel] setHidden:NO]; 654 | [[cell mRightLabel] setHidden:NO]; 655 | } 656 | 657 | NSString *stationID = [self.mFavoriteList objectAtIndex:indexPath.row]; 658 | StationAnnotation *stationAnnotation = [mAllStationAnnotationData valueForKey:stationID]; 659 | NSString *subTitle = [stationAnnotation subtitle]; 660 | cell.mLeftLabel.text = [NSString stringWithFormat:@"%@",[[[stationAnnotation title] componentsSeparatedByString:@" - "] lastObject]]; 661 | cell.mMiddleLabel.text = subTitle?subTitle:@""; 662 | cell.mRightLabel.text = [NSString stringWithFormat:@"  %@",stationID]; 663 | CLLocation *location = [[CLLocation alloc] initWithLatitude:stationAnnotation.coordinate.latitude longitude:stationAnnotation.coordinate.longitude]; 664 | CLLocation *userLocation = [mLocationManager location]; 665 | cell.mDistanceLabel.text = userLocation?[NSString stringWithFormat:@"Distance %0.2f km",[userLocation getDistanceFrom:location]/1000]:@""; 666 | [location release]; 667 | 668 | return cell; 669 | } 670 | 671 | // Override to support editing the table view. 672 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 673 | if (editingStyle == UITableViewCellEditingStyleDelete) { 674 | NSString *stationID = [self.mFavoriteList objectAtIndex:indexPath.row]; 675 | StationAnnotation *stationAnnotation = [mAllStationAnnotationData valueForKey:stationID]; 676 | PinAnnotationView *pinAnnotationView = (PinAnnotationView *)[mMapView viewForAnnotation:stationAnnotation]; 677 | [(UIButton *)[pinAnnotationView leftCalloutAccessoryView] setImage:mFavoriteOff forState:UIControlStateNormal]; 678 | [self.mFavoriteList removeObjectAtIndex:indexPath.row]; 679 | [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 680 | [self saveFavorites]; 681 | } 682 | } 683 | 684 | 685 | #pragma mark - 686 | #pragma mark Table view delegate 687 | 688 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 689 | NSString *stationID = [self.mFavoriteList objectAtIndex:indexPath.row]; 690 | StationAnnotation *stationAnnotation = [mAllStationAnnotationData valueForKey:stationID]; 691 | [self setMapLocation:stationAnnotation.coordinate distance:500 animated:NO]; 692 | [self doSwitchView:self]; 693 | [mMapView selectAnnotation:stationAnnotation animated:YES]; 694 | } 695 | 696 | - (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath{ 697 | //- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{ 698 | CustomizedTableCell *tableCell = (CustomizedTableCell *)[tableView cellForRowAtIndexPath:indexPath]; 699 | [[tableCell mMiddleLabel] setHidden:YES]; 700 | [[tableCell mRightLabel] setHidden:YES]; 701 | } 702 | 703 | - (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath{ 704 | CustomizedTableCell *tableCell = (CustomizedTableCell *)[tableView cellForRowAtIndexPath:indexPath]; 705 | [[tableCell mMiddleLabel] setHidden:NO]; 706 | [[tableCell mRightLabel] setHidden:NO]; 707 | } 708 | @end 709 | -------------------------------------------------------------------------------- /iPhone/AppDelegate_iPhone.m: -------------------------------------------------------------------------------- 1 | // 2 | // VeloParisAppDelegate.m 3 | // VeloParis 4 | // 5 | // Created by CocoaBob on 10-4-1. 6 | // Copyright CocoaBob 2010. All rights reserved. 7 | // 8 | #define DEGREES_TO_RADIANS(__ANGLE) ((__ANGLE) * M_PI / 180.0) 9 | #define RADIANS_TO_DEGREES(__RADIANS) ((__RADIANS) * 180 / M_PI) 10 | 11 | #import "AppDelegate_iPhone.h" 12 | 13 | @interface AppDelegate_iPhone() 14 | 15 | - (void)saveLocationLatitude:(double)latitude Longitude:(double)longitude; 16 | 17 | @end 18 | 19 | 20 | @implementation AppDelegate_iPhone 21 | 22 | @synthesize window,mFavoriteList; 23 | 24 | - (void)awakeFromNib{ 25 | [[NSNotificationCenter defaultCenter] addObserver:self 26 | selector:@selector(addAnnotationsNotification:) 27 | name:@"addAnnotationsNotification" 28 | object:nil]; 29 | 30 | //Why retain? If not, these images will be release when the application goes into background 31 | mPinGreen = [[UIImage imageNamed:@"pinGreen.png"] retain]; 32 | mPinYellowGreen = [[UIImage imageNamed:@"pinYellowGreen.png"] retain]; 33 | mPinYellow = [[UIImage imageNamed:@"pinYellow.png"] retain]; 34 | mPinOrange = [[UIImage imageNamed:@"pinOrange.png"] retain]; 35 | mPinRed = [[UIImage imageNamed:@"pinRed.png"] retain]; 36 | mPinPurple = [[UIImage imageNamed:@"pinPurple.png"] retain]; 37 | mFavoriteOn = [[UIImage imageNamed:@"FavoriteOn.png"] retain]; 38 | mFavoriteOff = [[UIImage imageNamed:@"FavoriteOff.png"] retain]; 39 | 40 | mOperationsCountForMap = 0; 41 | mOperationsCountForTable = 0; 42 | } 43 | 44 | - (void)dealloc { 45 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 46 | [mLocationManager release]; 47 | [window release]; 48 | [latestThreadTime release]; 49 | [mAllStationAnnotationData release]; 50 | [mUserHeadingView release]; 51 | [mPinGreen release]; 52 | [mPinYellowGreen release]; 53 | [mPinYellow release]; 54 | [mPinOrange release]; 55 | [mPinRed release]; 56 | [mPinPurple release]; 57 | [mFavoriteOn release]; 58 | [mFavoriteOff release]; 59 | [mRequestStationStatusOperationQueue release]; 60 | [mRequestVisibleStationStatusOperationQueue release]; 61 | [super dealloc]; 62 | } 63 | 64 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 65 | if (![[NSUserDefaults standardUserDefaults] boolForKey:kIsNotFirstTimeLaunch]) { 66 | [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionary]]; 67 | [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kIsNotFirstTimeLaunch]; 68 | [self saveLocationLatitude:48.856660f Longitude:2.350996f];//Paris 69 | } 70 | 71 | mRequestStationStatusOperationQueue = [[NSOperationQueue alloc] init]; 72 | [mRequestStationStatusOperationQueue setMaxConcurrentOperationCount:10]; 73 | 74 | mRequestVisibleStationStatusOperationQueue = [[NSOperationQueue alloc] init]; 75 | [mRequestStationStatusOperationQueue setMaxConcurrentOperationCount:2]; 76 | 77 | mLocationManager = [[CLLocationManager alloc] init]; 78 | [mLocationManager setDelegate:self]; 79 | [mLocationManager setHeadingFilter:1]; 80 | 81 | self.mFavoriteList = [[self getFavorites] mutableCopy]; 82 | if (!self.mFavoriteList) { 83 | self.mFavoriteList = [[NSMutableArray alloc] init]; 84 | } 85 | 86 | double latitude = [[[NSUserDefaults standardUserDefaults] valueForKey:kLastLocationLatitude] doubleValue]; 87 | double longitude = [[[NSUserDefaults standardUserDefaults] valueForKey:kLastLocationLongitude] doubleValue]; 88 | 89 | CLLocationCoordinate2D coordinate; 90 | 91 | coordinate.latitude = latitude; 92 | coordinate.longitude = longitude; 93 | 94 | [self setMapLocation:coordinate distance:500 animated:NO]; 95 | 96 | [mMapView setShowsUserLocation:YES]; 97 | [mMapView setMapType:[[NSUserDefaults standardUserDefaults] integerForKey:kMapType]]; 98 | 99 | [mMapTypeSwitch setSelectedSegmentIndex:[[NSUserDefaults standardUserDefaults] integerForKey:kMapType]]; 100 | 101 | [mTableView setDataSource:self]; 102 | [window makeKeyAndVisible]; 103 | 104 | [self addAnnotations]; 105 | 106 | return YES; 107 | } 108 | 109 | - (void)applicationDidBecomeActive:(UIApplication *)application{ 110 | if (mDidAddAllAnnotations && mNeedsUpdateRealTimeStatus) { 111 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestVisibleAnnotations:) object:mMapView]; 112 | // [theOp setThreadPriority:0.01f]; 113 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 114 | [theOp release]; 115 | } 116 | 117 | [self doLocateSelf:self]; 118 | } 119 | 120 | - (void)applicationWillEnterForeground:(UIApplication *)application{ 121 | [[NSUserDefaults standardUserDefaults] synchronize]; 122 | 123 | NSArray *allAnnotations = [[NSArray alloc]initWithArray:[mMapView annotations]]; 124 | for (StationAnnotation *stationAnnotation in allAnnotations) 125 | { 126 | if (![stationAnnotation isKindOfClass:[MKUserLocation class]]) { 127 | [stationAnnotation setIsRequested:NO]; 128 | } 129 | } 130 | [allAnnotations release]; 131 | } 132 | 133 | #pragma mark - 134 | #pragma mark CLLocationManagerDelegate 135 | 136 | - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{ 137 | [mMapView setCenterCoordinate:newLocation.coordinate animated:YES]; 138 | [mLocationManager stopUpdatingLocation]; 139 | } 140 | 141 | - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{ 142 | [mLocationManager stopUpdatingLocation]; 143 | [mLocationManager stopUpdatingHeading]; 144 | mIsHeading = NO; 145 | [mUserHeadingView setHidden:YES]; 146 | [[mMapView viewForAnnotation:[mMapView userLocation]] setTransform:CGAffineTransformIdentity]; 147 | /* 148 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Oops" message:[NSString stringWithFormat:@"%@",NSLocalizedString(@"LocationManagerErrorMessage",nil)] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; 149 | [alert show]; 150 | [alert release]; 151 | */ 152 | } 153 | 154 | - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{ 155 | float headingAccuracy = [newHeading trueHeading]; 156 | if (headingAccuracy > 0) { 157 | //CGAffineTransform mapTransform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(headingAccuracy)*-1);//如果你想整个屏幕一起跟着旋转 158 | CGAffineTransform pinTransform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(headingAccuracy)); 159 | //[mMapView viewForAnnotation:[mMapView userLocation]].transform = pinTransform; 160 | mUserHeadingView.transform = pinTransform; 161 | [mUserHeadingView setHidden:NO]; 162 | 163 | /*如果你想整个屏幕一起跟着旋转 164 | for (UIView *subView in [mMapView subviews]) { 165 | //NSLog(@"%@",[subView description]); 166 | if(![[[subView class] description] isEqualToString:@"UIImageView"]){ 167 | subView.transform = mapTransform; 168 | } 169 | } 170 | 171 | for (StationAnnotation *annotation in [mAllStationAnnotationData allValues]) { 172 | [mMapView viewForAnnotation:annotation].transform = pinTransform; 173 | } 174 | */ 175 | } 176 | } 177 | 178 | - (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager{//遇到电磁干扰时,是否弹出按8字形摆动iPhone校准指南针的界面。 179 | return YES; 180 | } 181 | 182 | #pragma mark - 183 | #pragma mark Variables 184 | 185 | - (UIImageView *)userHeadingView{ 186 | if (!mUserHeadingView) { 187 | UIImage *imageUserHeading = [UIImage imageNamed:@"UserHeading.png"]; 188 | mUserHeadingView = [[UIImageView alloc] initWithImage:imageUserHeading]; 189 | [mUserHeadingView setHidden:YES]; 190 | } 191 | return mUserHeadingView; 192 | } 193 | 194 | #pragma mark - 195 | #pragma mark MKMapViewDelegate 196 | 197 | - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{ 198 | [self saveLocationLatitude:mapView.centerCoordinate.latitude Longitude:mapView.centerCoordinate.longitude]; 199 | if (mDidAddAllAnnotations) { 200 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestVisibleAnnotations:) object:mapView]; 201 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 202 | [theOp release]; 203 | } 204 | /*如果你想整个屏幕都转动的话,需要在UserLocation离开屏幕中心时停止旋转屏幕……我找不到更好的算法了…… 205 | CLLocationCoordinate2D centerCoordinate = [mMapView centerCoordinate]; 206 | CLLocationCoordinate2D userCoordinate = [mMapView userLocation].coordinate; 207 | if (centerCoordinate.latitude != userCoordinate.latitude && 208 | centerCoordinate.longitude != userCoordinate.longitude) { 209 | [mUserHeadingView setHidden:YES]; 210 | [mLocationManager stopUpdatingHeading]; 211 | } 212 | for (UIView *subView in [mMapView subviews]) { 213 | if(![[[subView class] description] isEqualToString:@"UIImageView"]){ 214 | subView.transform = CGAffineTransformIdentity; 215 | } 216 | } 217 | 218 | for (StationAnnotation *annotation in [mAllStationAnnotationData allValues]) { 219 | [mMapView viewForAnnotation:annotation].transform = CGAffineTransformIdentity; 220 | } 221 | */ 222 | } 223 | 224 | - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation { 225 | if([annotation isKindOfClass:[StationAnnotation class]]){//[annotation isKindOfClass:[StationAnnotation class]]//[annotation isKindOfClass:[MKUserLocation class]] 226 | StationAnnotation *oneStationAnnotation = (StationAnnotation *)annotation; 227 | PinAnnotationView *pinAnnotationView = [(PinAnnotationView *) [mMapView dequeueReusableAnnotationViewWithIdentifier:@"PinAnnotationView"] retain]; 228 | if (!pinAnnotationView) { 229 | pinAnnotationView = [[PinAnnotationView alloc] initWithAnnotation:oneStationAnnotation reuseIdentifier:@"PinAnnotationView"]; 230 | [pinAnnotationView setImage:mPinPurple]; 231 | 232 | UIButton *leftCalloutAccessoryView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 24, 24)]; 233 | if ([self isInFavoriteList:[oneStationAnnotation stationID]]) { 234 | [leftCalloutAccessoryView setImage:mFavoriteOn forState:UIControlStateNormal]; 235 | } 236 | else { 237 | [leftCalloutAccessoryView setImage:mFavoriteOff forState:UIControlStateNormal]; 238 | } 239 | [leftCalloutAccessoryView addTarget:self action:@selector(doSwitchFavoriteButton:) forControlEvents:UIControlEventTouchUpInside]; 240 | [pinAnnotationView setLeftCalloutAccessoryView:leftCalloutAccessoryView]; 241 | [leftCalloutAccessoryView release]; 242 | } 243 | else { 244 | [pinAnnotationView setAnnotation:oneStationAnnotation]; 245 | } 246 | 247 | return [pinAnnotationView autorelease]; 248 | } 249 | 250 | return nil;//Return nil to show the MKUserLocation 251 | } 252 | 253 | - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control{ 254 | NSString *stationID = [(StationAnnotation *)[view annotation] stationID]; 255 | if ([self isInFavoriteList:stationID]) { 256 | [(UIButton *)control setImage:mFavoriteOn forState:UIControlStateNormal]; 257 | } 258 | else { 259 | [(UIButton *)control setImage:mFavoriteOff forState:UIControlStateNormal]; 260 | } 261 | } 262 | 263 | - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views{ 264 | if ([views count]>1) { 265 | mDidAddAllAnnotations = YES; 266 | if ([[mSuperView subviews]lastObject] == mTableView) { 267 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestAnnotationsForTable:) object:self.mFavoriteList]; 268 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 269 | [theOp release]; 270 | } 271 | else if ([[mSuperView subviews]lastObject] == mMapView) { 272 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestVisibleAnnotations:) object:mapView]; 273 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 274 | [theOp release]; 275 | } 276 | 277 | [self reloadTable]; 278 | } 279 | 280 | UIView *userLocationView = [mMapView viewForAnnotation:[mMapView userLocation]]; 281 | if (userLocationView) { 282 | UIImageView *imageView = [self userHeadingView]; 283 | [imageView setFrame:CGRectMake(userLocationView.frame.origin.x + (userLocationView.frame.size.width - imageView.frame.size.width)/2, userLocationView.frame.origin.y + (userLocationView.frame.size.height - imageView.frame.size.height)/2, imageView.frame.size.width, imageView.frame.size.height)]; 284 | [userLocationView addSubview:imageView]; 285 | mDidAddUserLocationAnnotation = YES; 286 | } 287 | } 288 | 289 | #pragma mark - 290 | #pragma mark Actions 291 | 292 | - (IBAction)doLocateSelf:(id)sender{ 293 | CGPoint userLocationPoint = [mMapView convertCoordinate:[mMapView userLocation].coordinate toPointToView:mMapView]; 294 | if ([mLocationManager locationServicesEnabled]) { 295 | [mLocationManager startUpdatingLocation]; 296 | } 297 | if ([mLocationManager headingAvailable] && mDidAddUserLocationAnnotation) { 298 | if (userLocationPoint.x > 159.0f && userLocationPoint.x < 161.0f && 299 | userLocationPoint.y > 207.0f && userLocationPoint.y < 209.0f){ 300 | if (!mIsHeading) { 301 | [mLocationManager startUpdatingHeading]; 302 | mIsHeading = YES; 303 | } 304 | else { 305 | [mLocationManager stopUpdatingHeading]; 306 | mIsHeading = NO; 307 | [mUserHeadingView setHidden:YES]; 308 | [[mMapView viewForAnnotation:[mMapView userLocation]] setTransform:CGAffineTransformIdentity]; 309 | } 310 | } 311 | } 312 | } 313 | 314 | - (IBAction)doZoomIn:(id)sender{ 315 | MKCoordinateRegion region = mMapView.region; 316 | region.span.latitudeDelta=region.span.latitudeDelta * 0.4; 317 | region.span.longitudeDelta=region.span.longitudeDelta * 0.4; 318 | [mMapView setRegion:region animated:YES]; 319 | } 320 | 321 | - (IBAction)doZoomOut:(id)sender{ 322 | MKCoordinateRegion region = mMapView.region; 323 | region.span.latitudeDelta=region.span.latitudeDelta * 1.3; 324 | region.span.longitudeDelta=region.span.longitudeDelta * 1.3; 325 | [mMapView setRegion:region animated:YES]; 326 | } 327 | 328 | - (IBAction)doSwitchView:(id)sender{ 329 | [UIView beginAnimations:@"animationID" context:nil]; 330 | [UIView setAnimationDuration:0.3f]; 331 | [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; 332 | [UIView setAnimationRepeatAutoreverses:NO]; 333 | if ([[mSuperView subviews]lastObject]!=mMapView) { 334 | [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:mSuperView cache:YES]; 335 | if (mDidAddAllAnnotations) { 336 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestVisibleAnnotations:) object:mMapView]; 337 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 338 | [theOp release]; 339 | } 340 | [mSuperView bringSubviewToFront:mMapView]; 341 | [mZoomOutButton setEnabled:YES]; 342 | [mZoomInButton setEnabled:YES]; 343 | [mLocateSelfButton setEnabled:YES]; 344 | [mSettingButton setEnabled:YES]; 345 | [mFavoritesButton setEnabled:YES]; 346 | } 347 | else if(![sender isKindOfClass:[AppDelegate_iPhone class]]){ 348 | switch ([sender tag]) { 349 | case 0: 350 | [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:mSuperView cache:YES]; 351 | if (mDidAddAllAnnotations) { 352 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestAnnotationsForTable:) object:self.mFavoriteList]; 353 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 354 | [theOp release]; 355 | } 356 | [self reloadTable]; 357 | [mSettingButton setEnabled:NO]; 358 | [mFavoritesButton setEnabled:YES]; 359 | [mSuperView bringSubviewToFront:mTableView]; 360 | break; 361 | case 1: 362 | [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:mSuperView cache:YES]; 363 | [mSettingButton setEnabled:YES]; 364 | [mFavoritesButton setEnabled:NO]; 365 | [mSuperView bringSubviewToFront:mSettingView]; 366 | break; 367 | default: 368 | break; 369 | } 370 | [mZoomOutButton setEnabled:NO]; 371 | [mZoomInButton setEnabled:NO]; 372 | [mLocateSelfButton setEnabled:NO]; 373 | } 374 | 375 | [UIView commitAnimations]; 376 | } 377 | 378 | - (IBAction)doSegmentedControlAction:(id)sender{ 379 | if (sender == mMapTypeSwitch) { 380 | switch (((UISegmentedControl *)sender).selectedSegmentIndex) 381 | { 382 | case 0: 383 | { 384 | mMapView.mapType = MKMapTypeStandard; 385 | [[NSUserDefaults standardUserDefaults] setInteger:MKMapTypeStandard forKey:kMapType]; 386 | break; 387 | } 388 | case 1: 389 | { 390 | mMapView.mapType = MKMapTypeSatellite; 391 | [[NSUserDefaults standardUserDefaults] setInteger:MKMapTypeSatellite forKey:kMapType]; 392 | break; 393 | } 394 | default: 395 | { 396 | mMapView.mapType = MKMapTypeHybrid; 397 | [[NSUserDefaults standardUserDefaults] setInteger:MKMapTypeHybrid forKey:kMapType]; 398 | break; 399 | } 400 | } 401 | } 402 | else if(sender == mRefreshCacheButton){ 403 | [mMapView removeAnnotations:[mMapView annotations]]; 404 | [[ConnectionDelegate sharedConnectionDelegate] getAllStations]; 405 | } 406 | [self doSwitchView:self]; 407 | } 408 | 409 | - (IBAction)doSwitchFavoriteButton:(id)sender{ 410 | PinAnnotationView *pinAnnotationView = (PinAnnotationView *)[[sender superview] superview]; 411 | StationAnnotation *stationAnnotation = (StationAnnotation *)[pinAnnotationView annotation]; 412 | NSString *stationID = [stationAnnotation stationID]; 413 | 414 | if ([self isInFavoriteList:stationID]) { 415 | [self removeFavorite:stationID]; 416 | [(UIButton *)sender setImage:mFavoriteOff forState:UIControlStateNormal]; 417 | } 418 | else { 419 | [self addFavorite:stationID]; 420 | [(UIButton *)sender setImage:mFavoriteOn forState:UIControlStateNormal]; 421 | } 422 | } 423 | 424 | #pragma mark - 425 | #pragma mark Methods 426 | 427 | - (void)addFavorite:(NSString *)stationID{ 428 | if (![self.mFavoriteList containsObject:stationID]) { 429 | [self.mFavoriteList addObject:stationID]; 430 | [self saveFavorites]; 431 | } 432 | } 433 | 434 | - (void)removeFavorite:(NSString *)stationID{ 435 | if ([self.mFavoriteList containsObject:stationID]) { 436 | [self.mFavoriteList removeObject:stationID]; 437 | [self saveFavorites]; 438 | } 439 | } 440 | 441 | - (BOOL)isInFavoriteList:(NSString *)stationID{ 442 | return [self.mFavoriteList containsObject:stationID]; 443 | } 444 | 445 | - (void)saveLocationLatitude:(double)latitude Longitude:(double)longitude{ 446 | NSNumber *locationLatitude = [NSNumber numberWithDouble:latitude]; 447 | NSNumber *locationLongitude = [NSNumber numberWithDouble:longitude]; 448 | [[NSUserDefaults standardUserDefaults] setValue:locationLatitude forKey:kLastLocationLatitude]; 449 | [[NSUserDefaults standardUserDefaults] setValue:locationLongitude forKey:kLastLocationLongitude]; 450 | } 451 | 452 | - (void)setMapLocation:(CLLocationCoordinate2D)coordinate distance:(double)distance animated:(BOOL)animated{ 453 | [self saveLocationLatitude:coordinate.latitude Longitude:coordinate.longitude ]; 454 | MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(coordinate, distance, distance); 455 | MKCoordinateRegion adjustedRegion = [mMapView regionThatFits:viewRegion]; 456 | [mMapView setRegion:adjustedRegion animated:animated]; 457 | } 458 | 459 | - (void)addAnnotations{ 460 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 461 | NSString *documentsDirectory = [paths objectAtIndex:0]; 462 | NSString *path = [documentsDirectory stringByAppendingPathComponent:@"AllStationAnnotationsDic.bin"]; 463 | 464 | if (mAllStationAnnotationData) { 465 | [mAllStationAnnotationData release]; 466 | mAllStationAnnotationData= nil; 467 | } 468 | 469 | mAllStationAnnotationData = [[NSKeyedUnarchiver unarchiveObjectWithFile:path] retain]; 470 | 471 | if (mAllStationAnnotationData) { 472 | mDidAddAllAnnotations = NO; 473 | NSArray *oldAnnotations = [mMapView annotations]; 474 | if (oldAnnotations) { 475 | [mMapView removeAnnotations:oldAnnotations]; 476 | } 477 | 478 | [mMapView performSelectorOnMainThread:@selector(addAnnotations:) withObject:[mAllStationAnnotationData allValues] waitUntilDone:YES]; 479 | 480 | //Refresh pins 481 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRequestVisibleAnnotations:) object:mMapView]; 482 | [mRequestVisibleStationStatusOperationQueue addOperation:theOp]; 483 | [theOp release]; 484 | } 485 | else { 486 | [[ConnectionDelegate sharedConnectionDelegate] getAllStations]; 487 | } 488 | 489 | } 490 | 491 | - (void)setAnnotationView:(StationAnnotation *)stationAnnotation strAvailable:(NSString *)strAvailable strFree:(NSString *)strFree strTotal:(NSString *)strTotal{ 492 | [stationAnnotation setSubtitle:[NSString stringWithFormat:@" %@ / %@",strAvailable,strTotal]]; 493 | 494 | PinAnnotationView *pinAnnotationView = (PinAnnotationView *)[mMapView viewForAnnotation:stationAnnotation]; 495 | 496 | float numFree = [strFree floatValue]; 497 | float numAvailable = [strAvailable floatValue]; 498 | float ratio = numAvailable / (numAvailable + numFree); 499 | [stationAnnotation setRatio:ratio]; 500 | [stationAnnotation setNumAvailable:numAvailable]; 501 | if (pinAnnotationView) { 502 | if (numAvailable < 2) { 503 | [pinAnnotationView performSelectorOnMainThread:@selector(setImage:) withObject:mPinRed waitUntilDone:NO]; 504 | } 505 | else if(ratio < 0.25f) { 506 | [pinAnnotationView performSelectorOnMainThread:@selector(setImage:) withObject:mPinOrange waitUntilDone:NO]; 507 | } 508 | else if(ratio >= 0.25f && ratio < 0.50f) { 509 | [pinAnnotationView performSelectorOnMainThread:@selector(setImage:) withObject:mPinYellow waitUntilDone:NO]; 510 | } 511 | else if(ratio >= 0.50f && ratio < 1.0f) { 512 | [pinAnnotationView performSelectorOnMainThread:@selector(setImage:) withObject:mPinYellowGreen waitUntilDone:NO]; 513 | } 514 | else{ 515 | [pinAnnotationView performSelectorOnMainThread:@selector(setImage:) withObject:mPinGreen waitUntilDone:NO]; 516 | } 517 | } 518 | else { 519 | NSLog(@"not created yet"); 520 | } 521 | } 522 | 523 | - (void)threadSetAnnotationSubTitle:(StationAnnotation *)stationAnnotation{ 524 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 525 | mOperationsCountForMap += 1; 526 | 527 | NSData *responseData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.velib.paris.fr/service/stationdetails/%@",[stationAnnotation stationID]]]]; 528 | if (responseData) { 529 | ParseStation *parser = [[ParseStation alloc] init]; 530 | NSDictionary *infoDic = [parser parseXMLFromData:responseData parseError:nil]; 531 | [self setAnnotationView:stationAnnotation strAvailable:[infoDic valueForKey:@"available"] strFree:[infoDic valueForKey:@"free"] strTotal:[infoDic valueForKey:@"total"]]; 532 | [stationAnnotation setIsRequested:YES];//Avoid being requested again 533 | [parser release]; 534 | } 535 | 536 | mOperationsCountForMap -= 1; 537 | if (mOperationsCountForMap <= 0) { 538 | mOperationsCountForMap = 0; 539 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 540 | [mMapView setNeedsDisplay]; 541 | } 542 | } 543 | 544 | - (void)threadRequestVisibleAnnotations:(MKMapView *)mapView{ 545 | MKCoordinateRegion currentRegion = mapView.region; 546 | CLLocationCoordinate2D currentCenter = currentRegion.center; 547 | MKCoordinateSpan currentSpan = currentRegion.span; 548 | 549 | double latitudeRadius = currentSpan.latitudeDelta/2; 550 | double longitudeRadius = currentSpan.longitudeDelta/2; 551 | 552 | [mRequestStationStatusOperationQueue cancelAllOperations]; 553 | NSArray *allAnnotations = [[NSArray alloc]initWithArray:[mMapView annotations]]; 554 | for (StationAnnotation *stationAnnotation in allAnnotations) 555 | { 556 | if (![stationAnnotation isKindOfClass:[MKUserLocation class]] && 557 | ![stationAnnotation isRequested] && 558 | stationAnnotation.coordinate.latitude >= currentCenter.latitude - latitudeRadius&& 559 | stationAnnotation.coordinate.latitude <= currentCenter.latitude + latitudeRadius && 560 | stationAnnotation.coordinate.longitude >= currentCenter.longitude - longitudeRadius&& 561 | stationAnnotation.coordinate.longitude <= currentCenter.longitude + longitudeRadius) { 562 | 563 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadSetAnnotationSubTitle:) object:stationAnnotation]; 564 | [mRequestStationStatusOperationQueue addOperation:theOp]; 565 | [theOp release]; 566 | } 567 | } 568 | 569 | [allAnnotations release]; 570 | } 571 | 572 | - (void)threadSetAnnotationSubTitleForTable:(StationAnnotation *)stationAnnotation{ 573 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 574 | mOperationsCountForTable += 1; 575 | 576 | NSData *responseData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.velib.paris.fr/service/stationdetails/%@",[stationAnnotation stationID]]]]; 577 | if (responseData) { 578 | ParseStation *parser = [[ParseStation alloc] init]; 579 | NSDictionary *infoDic = [parser parseXMLFromData:responseData parseError:nil]; 580 | [self setAnnotationView:stationAnnotation strAvailable:[infoDic valueForKey:@"available"] strFree:[infoDic valueForKey:@"free"] strTotal:[infoDic valueForKey:@"total"]]; 581 | [stationAnnotation setIsRequested:YES];//Avoid being requested again 582 | [parser release]; 583 | } 584 | 585 | mOperationsCountForTable -= 1; 586 | if (mOperationsCountForTable <= 0) { 587 | mOperationsCountForTable = 0; 588 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 589 | [self performSelectorOnMainThread:@selector(reloadTable) withObject:nil waitUntilDone:NO]; 590 | } 591 | } 592 | 593 | - (void)threadRequestAnnotationsForTable:(NSArray *)stationIDArray{ 594 | [mRequestStationStatusOperationQueue cancelAllOperations]; 595 | for (NSString *stationID in stationIDArray) 596 | { 597 | StationAnnotation *stationAnnotation = [mAllStationAnnotationData valueForKey:stationID]; 598 | 599 | if (![stationAnnotation isKindOfClass:[MKUserLocation class]] && 600 | ![stationAnnotation isRequested]) { 601 | NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadSetAnnotationSubTitleForTable:) object:stationAnnotation]; 602 | [mRequestStationStatusOperationQueue addOperation:theOp]; 603 | [theOp release]; 604 | } 605 | } 606 | } 607 | 608 | - (NSArray *)getFavorites{ 609 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 610 | NSString *documentsDirectory = [paths objectAtIndex:0]; 611 | NSString *path = [documentsDirectory stringByAppendingPathComponent:@"favorites.plist"]; 612 | return [NSArray arrayWithContentsOfFile:path]; 613 | } 614 | 615 | - (void)saveFavorites{ 616 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 617 | NSString *documentsDirectory = [paths objectAtIndex:0]; 618 | NSString *path = [documentsDirectory stringByAppendingPathComponent:@"favorites.plist"]; 619 | [self.mFavoriteList writeToFile:path atomically:YES]; 620 | } 621 | 622 | - (void)reloadTable{ 623 | [mTableView reloadData]; 624 | [mTableView setNeedsDisplay]; 625 | } 626 | 627 | #pragma mark - 628 | #pragma mark Notifications 629 | 630 | - (void)addAnnotationsNotification:(NSNotification *)notification{ 631 | [self addAnnotations]; 632 | } 633 | 634 | #pragma mark - 635 | #pragma mark Table view data source 636 | 637 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 638 | // Return the number of sections. 639 | return 1; 640 | } 641 | 642 | 643 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 644 | if (mAllStationAnnotationData) { 645 | return [self.mFavoriteList count]; 646 | } 647 | else { 648 | return 0; 649 | } 650 | } 651 | 652 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 653 | static NSString *CellIdentifier = @"Cell"; 654 | 655 | CustomizedTableCell *cell = (CustomizedTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 656 | if (cell == nil) { 657 | cell = [[[CustomizedTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 658 | } 659 | else { 660 | [[cell mMiddleLabel] setHidden:NO]; 661 | [[cell mRightLabel] setHidden:NO]; 662 | } 663 | 664 | NSString *stationID = [self.mFavoriteList objectAtIndex:indexPath.row]; 665 | StationAnnotation *stationAnnotation = [mAllStationAnnotationData valueForKey:stationID]; 666 | NSString *subTitle = [stationAnnotation subtitle]; 667 | cell.mLeftLabel.text = [NSString stringWithFormat:@"%@",[[[stationAnnotation title] componentsSeparatedByString:@" - "] lastObject]]; 668 | cell.mMiddleLabel.text = subTitle?subTitle:@""; 669 | cell.mRightLabel.text = [NSString stringWithFormat:@"  %@",stationID]; 670 | CLLocation *location = [[CLLocation alloc] initWithLatitude:stationAnnotation.coordinate.latitude longitude:stationAnnotation.coordinate.longitude]; 671 | CLLocation *userLocation = [mLocationManager location]; 672 | cell.mDistanceLabel.text = userLocation?[NSString stringWithFormat:@"Distance %0.2f km",[userLocation getDistanceFrom:location]/1000]:@""; 673 | [location release]; 674 | 675 | return cell; 676 | } 677 | 678 | // Override to support editing the table view. 679 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 680 | if (editingStyle == UITableViewCellEditingStyleDelete) { 681 | NSString *stationID = [self.mFavoriteList objectAtIndex:indexPath.row]; 682 | StationAnnotation *stationAnnotation = [mAllStationAnnotationData valueForKey:stationID]; 683 | PinAnnotationView *pinAnnotationView = (PinAnnotationView *)[mMapView viewForAnnotation:stationAnnotation]; 684 | [(UIButton *)[pinAnnotationView leftCalloutAccessoryView] setImage:mFavoriteOff forState:UIControlStateNormal]; 685 | [self.mFavoriteList removeObjectAtIndex:indexPath.row]; 686 | [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 687 | [self saveFavorites]; 688 | } 689 | } 690 | 691 | 692 | #pragma mark - 693 | #pragma mark Table view delegate 694 | 695 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 696 | NSString *stationID = [self.mFavoriteList objectAtIndex:indexPath.row]; 697 | StationAnnotation *stationAnnotation = [mAllStationAnnotationData valueForKey:stationID]; 698 | [self setMapLocation:stationAnnotation.coordinate distance:500 animated:NO]; 699 | [self doSwitchView:self]; 700 | [mMapView selectAnnotation:stationAnnotation animated:YES]; 701 | } 702 | 703 | - (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath{ 704 | //- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{ 705 | CustomizedTableCell *tableCell = (CustomizedTableCell *)[tableView cellForRowAtIndexPath:indexPath]; 706 | [[tableCell mMiddleLabel] setHidden:YES]; 707 | [[tableCell mRightLabel] setHidden:YES]; 708 | } 709 | 710 | - (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath{ 711 | CustomizedTableCell *tableCell = (CustomizedTableCell *)[tableView cellForRowAtIndexPath:indexPath]; 712 | [[tableCell mMiddleLabel] setHidden:NO]; 713 | [[tableCell mRightLabel] setHidden:NO]; 714 | } 715 | @end 716 | -------------------------------------------------------------------------------- /VeloParis.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1001D4EC151E73E100975171 /* MainWindow_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1001D4EB151E73E100975171 /* MainWindow_iPhone.xib */; }; 11 | 1029B7CA12ECF98B007A640B /* FavoriteOff.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7A512ECF98B007A640B /* FavoriteOff.png */; }; 12 | 1029B7CB12ECF98B007A640B /* FavoriteOff@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7A612ECF98B007A640B /* FavoriteOff@2x.png */; }; 13 | 1029B7CC12ECF98B007A640B /* FavoriteOn.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7A712ECF98B007A640B /* FavoriteOn.png */; }; 14 | 1029B7CD12ECF98B007A640B /* FavoriteOn@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7A812ECF98B007A640B /* FavoriteOn@2x.png */; }; 15 | 1029B7CE12ECF98B007A640B /* ICON.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7A912ECF98B007A640B /* ICON.png */; }; 16 | 1029B7CF12ECF98B007A640B /* ICON@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7AA12ECF98B007A640B /* ICON@2x.png */; }; 17 | 1029B7D012ECF98B007A640B /* ICON-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7AB12ECF98B007A640B /* ICON-72.png */; }; 18 | 1029B7D112ECF98B007A640B /* ICON_SMALL.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7AC12ECF98B007A640B /* ICON_SMALL.png */; }; 19 | 1029B7D212ECF98B007A640B /* ICON_SMALL@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7AD12ECF98B007A640B /* ICON_SMALL@2x.png */; }; 20 | 1029B7D312ECF98B007A640B /* IconFavorite.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7AE12ECF98B007A640B /* IconFavorite.png */; }; 21 | 1029B7D412ECF98B007A640B /* IconFavorite@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7AF12ECF98B007A640B /* IconFavorite@2x.png */; }; 22 | 1029B7D512ECF98B007A640B /* IconList.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7B012ECF98B007A640B /* IconList.png */; }; 23 | 1029B7D612ECF98B007A640B /* IconList@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7B112ECF98B007A640B /* IconList@2x.png */; }; 24 | 1029B7D712ECF98B007A640B /* IconLocation.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7B212ECF98B007A640B /* IconLocation.png */; }; 25 | 1029B7D812ECF98B007A640B /* IconLocation@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7B312ECF98B007A640B /* IconLocation@2x.png */; }; 26 | 1029B7D912ECF98B007A640B /* IconZoomIn.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7B412ECF98B007A640B /* IconZoomIn.png */; }; 27 | 1029B7DA12ECF98B007A640B /* IconZoomIn@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7B512ECF98B007A640B /* IconZoomIn@2x.png */; }; 28 | 1029B7DB12ECF98B007A640B /* IconZoomOut.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7B612ECF98B007A640B /* IconZoomOut.png */; }; 29 | 1029B7DC12ECF98B007A640B /* IconZoomOut@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7B712ECF98B007A640B /* IconZoomOut@2x.png */; }; 30 | 1029B7DD12ECF98B007A640B /* pinGreen.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7B812ECF98B007A640B /* pinGreen.png */; }; 31 | 1029B7DE12ECF98B007A640B /* pinGreen@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7B912ECF98B007A640B /* pinGreen@2x.png */; }; 32 | 1029B7DF12ECF98B007A640B /* pinOrange.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7BA12ECF98B007A640B /* pinOrange.png */; }; 33 | 1029B7E012ECF98B007A640B /* pinOrange@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7BB12ECF98B007A640B /* pinOrange@2x.png */; }; 34 | 1029B7E112ECF98B007A640B /* pinPurple.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7BC12ECF98B007A640B /* pinPurple.png */; }; 35 | 1029B7E212ECF98B007A640B /* pinPurple@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7BD12ECF98B007A640B /* pinPurple@2x.png */; }; 36 | 1029B7E312ECF98B007A640B /* pinRed.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7BE12ECF98B007A640B /* pinRed.png */; }; 37 | 1029B7E412ECF98B007A640B /* pinRed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7BF12ECF98B007A640B /* pinRed@2x.png */; }; 38 | 1029B7E512ECF98B007A640B /* pinYellow.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7C012ECF98B007A640B /* pinYellow.png */; }; 39 | 1029B7E612ECF98B007A640B /* pinYellow@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7C112ECF98B007A640B /* pinYellow@2x.png */; }; 40 | 1029B7E712ECF98B007A640B /* pinYellowGreen.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7C212ECF98B007A640B /* pinYellowGreen.png */; }; 41 | 1029B7E812ECF98B007A640B /* pinYellowGreen@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7C312ECF98B007A640B /* pinYellowGreen@2x.png */; }; 42 | 1029B7E912ECF98B007A640B /* UserHeading.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7C412ECF98B007A640B /* UserHeading.png */; }; 43 | 1029B7EA12ECF98B007A640B /* UserHeading@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1029B7C512ECF98B007A640B /* UserHeading@2x.png */; }; 44 | 1029B7FD12ECF9C5007A640B /* ConnectionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1029B7EE12ECF9C5007A640B /* ConnectionDelegate.m */; }; 45 | 1029B7FE12ECF9C5007A640B /* CustomizedTableCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 1029B7F012ECF9C5007A640B /* CustomizedTableCell.m */; }; 46 | 1029B80012ECF9C5007A640B /* ParseStation.m in Sources */ = {isa = PBXBuildFile; fileRef = 1029B7F312ECF9C5007A640B /* ParseStation.m */; }; 47 | 1029B80112ECF9C5007A640B /* ParseStations.m in Sources */ = {isa = PBXBuildFile; fileRef = 1029B7F512ECF9C5007A640B /* ParseStations.m */; }; 48 | 1029B80212ECF9C5007A640B /* PinAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1029B7F712ECF9C5007A640B /* PinAnnotationView.m */; }; 49 | 1029B80312ECF9C5007A640B /* StationAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 1029B7F912ECF9C5007A640B /* StationAnnotation.m */; }; 50 | 1029B82A12ECFAB7007A640B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1029B82912ECFAB7007A640B /* main.m */; }; 51 | 1029E84A121B1FBD00EB15A1 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1029E849121B1FBD00EB15A1 /* MapKit.framework */; }; 52 | 1029E863121B1FCE00EB15A1 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1029E862121B1FCE00EB15A1 /* CoreLocation.framework */; }; 53 | 106DE877151E72CE001615B8 /* ICON-72@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 106DE876151E72CE001615B8 /* ICON-72@2x.png */; }; 54 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 55 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 56 | 2860E328111B887F00E27156 /* AppDelegate_iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 2860E326111B887F00E27156 /* AppDelegate_iPhone.m */; }; 57 | 2860E32E111B888700E27156 /* AppDelegate_iPad.m in Sources */ = {isa = PBXBuildFile; fileRef = 2860E32C111B888700E27156 /* AppDelegate_iPad.m */; }; 58 | 2860E32F111B888700E27156 /* MainWindow_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2860E32D111B888700E27156 /* MainWindow_iPad.xib */; }; 59 | 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; 60 | /* End PBXBuildFile section */ 61 | 62 | /* Begin PBXFileReference section */ 63 | 1001D4EB151E73E100975171 /* MainWindow_iPhone.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainWindow_iPhone.xib; sourceTree = ""; }; 64 | 1029B7A512ECF98B007A640B /* FavoriteOff.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = FavoriteOff.png; path = Shared/PNG/FavoriteOff.png; sourceTree = SOURCE_ROOT; }; 65 | 1029B7A612ECF98B007A640B /* FavoriteOff@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "FavoriteOff@2x.png"; path = "Shared/PNG/FavoriteOff@2x.png"; sourceTree = SOURCE_ROOT; }; 66 | 1029B7A712ECF98B007A640B /* FavoriteOn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = FavoriteOn.png; path = Shared/PNG/FavoriteOn.png; sourceTree = SOURCE_ROOT; }; 67 | 1029B7A812ECF98B007A640B /* FavoriteOn@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "FavoriteOn@2x.png"; path = "Shared/PNG/FavoriteOn@2x.png"; sourceTree = SOURCE_ROOT; }; 68 | 1029B7A912ECF98B007A640B /* ICON.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ICON.png; path = Shared/PNG/ICON.png; sourceTree = SOURCE_ROOT; }; 69 | 1029B7AA12ECF98B007A640B /* ICON@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "ICON@2x.png"; path = "Shared/PNG/ICON@2x.png"; sourceTree = SOURCE_ROOT; }; 70 | 1029B7AB12ECF98B007A640B /* ICON-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "ICON-72.png"; path = "Shared/PNG/ICON-72.png"; sourceTree = SOURCE_ROOT; }; 71 | 1029B7AC12ECF98B007A640B /* ICON_SMALL.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ICON_SMALL.png; path = Shared/PNG/ICON_SMALL.png; sourceTree = SOURCE_ROOT; }; 72 | 1029B7AD12ECF98B007A640B /* ICON_SMALL@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "ICON_SMALL@2x.png"; path = "Shared/PNG/ICON_SMALL@2x.png"; sourceTree = SOURCE_ROOT; }; 73 | 1029B7AE12ECF98B007A640B /* IconFavorite.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = IconFavorite.png; path = Shared/PNG/IconFavorite.png; sourceTree = SOURCE_ROOT; }; 74 | 1029B7AF12ECF98B007A640B /* IconFavorite@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "IconFavorite@2x.png"; path = "Shared/PNG/IconFavorite@2x.png"; sourceTree = SOURCE_ROOT; }; 75 | 1029B7B012ECF98B007A640B /* IconList.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = IconList.png; path = Shared/PNG/IconList.png; sourceTree = SOURCE_ROOT; }; 76 | 1029B7B112ECF98B007A640B /* IconList@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "IconList@2x.png"; path = "Shared/PNG/IconList@2x.png"; sourceTree = SOURCE_ROOT; }; 77 | 1029B7B212ECF98B007A640B /* IconLocation.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = IconLocation.png; path = Shared/PNG/IconLocation.png; sourceTree = SOURCE_ROOT; }; 78 | 1029B7B312ECF98B007A640B /* IconLocation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "IconLocation@2x.png"; path = "Shared/PNG/IconLocation@2x.png"; sourceTree = SOURCE_ROOT; }; 79 | 1029B7B412ECF98B007A640B /* IconZoomIn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = IconZoomIn.png; path = Shared/PNG/IconZoomIn.png; sourceTree = SOURCE_ROOT; }; 80 | 1029B7B512ECF98B007A640B /* IconZoomIn@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "IconZoomIn@2x.png"; path = "Shared/PNG/IconZoomIn@2x.png"; sourceTree = SOURCE_ROOT; }; 81 | 1029B7B612ECF98B007A640B /* IconZoomOut.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = IconZoomOut.png; path = Shared/PNG/IconZoomOut.png; sourceTree = SOURCE_ROOT; }; 82 | 1029B7B712ECF98B007A640B /* IconZoomOut@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "IconZoomOut@2x.png"; path = "Shared/PNG/IconZoomOut@2x.png"; sourceTree = SOURCE_ROOT; }; 83 | 1029B7B812ECF98B007A640B /* pinGreen.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = pinGreen.png; path = Shared/PNG/pinGreen.png; sourceTree = SOURCE_ROOT; }; 84 | 1029B7B912ECF98B007A640B /* pinGreen@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "pinGreen@2x.png"; path = "Shared/PNG/pinGreen@2x.png"; sourceTree = SOURCE_ROOT; }; 85 | 1029B7BA12ECF98B007A640B /* pinOrange.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = pinOrange.png; path = Shared/PNG/pinOrange.png; sourceTree = SOURCE_ROOT; }; 86 | 1029B7BB12ECF98B007A640B /* pinOrange@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "pinOrange@2x.png"; path = "Shared/PNG/pinOrange@2x.png"; sourceTree = SOURCE_ROOT; }; 87 | 1029B7BC12ECF98B007A640B /* pinPurple.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = pinPurple.png; path = Shared/PNG/pinPurple.png; sourceTree = SOURCE_ROOT; }; 88 | 1029B7BD12ECF98B007A640B /* pinPurple@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "pinPurple@2x.png"; path = "Shared/PNG/pinPurple@2x.png"; sourceTree = SOURCE_ROOT; }; 89 | 1029B7BE12ECF98B007A640B /* pinRed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = pinRed.png; path = Shared/PNG/pinRed.png; sourceTree = SOURCE_ROOT; }; 90 | 1029B7BF12ECF98B007A640B /* pinRed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "pinRed@2x.png"; path = "Shared/PNG/pinRed@2x.png"; sourceTree = SOURCE_ROOT; }; 91 | 1029B7C012ECF98B007A640B /* pinYellow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = pinYellow.png; path = Shared/PNG/pinYellow.png; sourceTree = SOURCE_ROOT; }; 92 | 1029B7C112ECF98B007A640B /* pinYellow@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "pinYellow@2x.png"; path = "Shared/PNG/pinYellow@2x.png"; sourceTree = SOURCE_ROOT; }; 93 | 1029B7C212ECF98B007A640B /* pinYellowGreen.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = pinYellowGreen.png; path = Shared/PNG/pinYellowGreen.png; sourceTree = SOURCE_ROOT; }; 94 | 1029B7C312ECF98B007A640B /* pinYellowGreen@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "pinYellowGreen@2x.png"; path = "Shared/PNG/pinYellowGreen@2x.png"; sourceTree = SOURCE_ROOT; }; 95 | 1029B7C412ECF98B007A640B /* UserHeading.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = UserHeading.png; path = Shared/PNG/UserHeading.png; sourceTree = SOURCE_ROOT; }; 96 | 1029B7C512ECF98B007A640B /* UserHeading@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "UserHeading@2x.png"; path = "Shared/PNG/UserHeading@2x.png"; sourceTree = SOURCE_ROOT; }; 97 | 1029B7ED12ECF9C5007A640B /* ConnectionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConnectionDelegate.h; path = Shared/ConnectionDelegate.h; sourceTree = SOURCE_ROOT; }; 98 | 1029B7EE12ECF9C5007A640B /* ConnectionDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ConnectionDelegate.m; path = Shared/ConnectionDelegate.m; sourceTree = SOURCE_ROOT; }; 99 | 1029B7EF12ECF9C5007A640B /* CustomizedTableCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomizedTableCell.h; path = Shared/CustomizedTableCell.h; sourceTree = SOURCE_ROOT; }; 100 | 1029B7F012ECF9C5007A640B /* CustomizedTableCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CustomizedTableCell.m; path = Shared/CustomizedTableCell.m; sourceTree = SOURCE_ROOT; }; 101 | 1029B7F212ECF9C5007A640B /* ParseStation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ParseStation.h; path = Shared/ParseStation.h; sourceTree = SOURCE_ROOT; }; 102 | 1029B7F312ECF9C5007A640B /* ParseStation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ParseStation.m; path = Shared/ParseStation.m; sourceTree = SOURCE_ROOT; }; 103 | 1029B7F412ECF9C5007A640B /* ParseStations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ParseStations.h; path = Shared/ParseStations.h; sourceTree = SOURCE_ROOT; }; 104 | 1029B7F512ECF9C5007A640B /* ParseStations.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ParseStations.m; path = Shared/ParseStations.m; sourceTree = SOURCE_ROOT; }; 105 | 1029B7F612ECF9C5007A640B /* PinAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PinAnnotationView.h; path = Shared/PinAnnotationView.h; sourceTree = SOURCE_ROOT; }; 106 | 1029B7F712ECF9C5007A640B /* PinAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PinAnnotationView.m; path = Shared/PinAnnotationView.m; sourceTree = SOURCE_ROOT; }; 107 | 1029B7F812ECF9C5007A640B /* StationAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StationAnnotation.h; path = Shared/StationAnnotation.h; sourceTree = SOURCE_ROOT; }; 108 | 1029B7F912ECF9C5007A640B /* StationAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StationAnnotation.m; path = Shared/StationAnnotation.m; sourceTree = SOURCE_ROOT; }; 109 | 1029B7FA12ECF9C5007A640B /* SynthesizeSingleton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SynthesizeSingleton.h; path = Shared/SynthesizeSingleton.h; sourceTree = SOURCE_ROOT; }; 110 | 1029B80A12ECFA1A007A640B /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 111 | 1029B81012ECFA40007A640B /* VeloParis_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VeloParis_Prefix.pch; sourceTree = SOURCE_ROOT; }; 112 | 1029B82912ECFAB7007A640B /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; }; 113 | 1029E849121B1FBD00EB15A1 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; 114 | 1029E862121B1FCE00EB15A1 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; 115 | 105A3BFB13020631005B5D7C /* SynthesizeSingleton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SynthesizeSingleton.h; path = Shared/SynthesizeSingleton.h; sourceTree = SOURCE_ROOT; }; 116 | 106DE876151E72CE001615B8 /* ICON-72@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "ICON-72@2x.png"; sourceTree = ""; }; 117 | 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 118 | 1D6058910D05DD3D006BFB54 /* VeloParis.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VeloParis.app; sourceTree = BUILT_PRODUCTS_DIR; }; 119 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 120 | 2860E325111B887F00E27156 /* AppDelegate_iPhone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate_iPhone.h; sourceTree = ""; }; 121 | 2860E326111B887F00E27156 /* AppDelegate_iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate_iPhone.m; sourceTree = ""; }; 122 | 2860E32B111B888700E27156 /* AppDelegate_iPad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate_iPad.h; sourceTree = ""; }; 123 | 2860E32C111B888700E27156 /* AppDelegate_iPad.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate_iPad.m; sourceTree = ""; }; 124 | 2860E32D111B888700E27156 /* MainWindow_iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow_iPad.xib; sourceTree = ""; }; 125 | 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 126 | /* End PBXFileReference section */ 127 | 128 | /* Begin PBXFrameworksBuildPhase section */ 129 | 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { 130 | isa = PBXFrameworksBuildPhase; 131 | buildActionMask = 2147483647; 132 | files = ( 133 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 134 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 135 | 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */, 136 | 1029E84A121B1FBD00EB15A1 /* MapKit.framework in Frameworks */, 137 | 1029E863121B1FCE00EB15A1 /* CoreLocation.framework in Frameworks */, 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXFrameworksBuildPhase section */ 142 | 143 | /* Begin PBXGroup section */ 144 | 1029B7A012ECF98B007A640B /* PNG */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | 1029B7A512ECF98B007A640B /* FavoriteOff.png */, 148 | 1029B7A612ECF98B007A640B /* FavoriteOff@2x.png */, 149 | 1029B7A712ECF98B007A640B /* FavoriteOn.png */, 150 | 1029B7A812ECF98B007A640B /* FavoriteOn@2x.png */, 151 | 1029B7A912ECF98B007A640B /* ICON.png */, 152 | 1029B7AA12ECF98B007A640B /* ICON@2x.png */, 153 | 1029B7AB12ECF98B007A640B /* ICON-72.png */, 154 | 106DE876151E72CE001615B8 /* ICON-72@2x.png */, 155 | 1029B7AC12ECF98B007A640B /* ICON_SMALL.png */, 156 | 1029B7AD12ECF98B007A640B /* ICON_SMALL@2x.png */, 157 | 1029B7AE12ECF98B007A640B /* IconFavorite.png */, 158 | 1029B7AF12ECF98B007A640B /* IconFavorite@2x.png */, 159 | 1029B7B012ECF98B007A640B /* IconList.png */, 160 | 1029B7B112ECF98B007A640B /* IconList@2x.png */, 161 | 1029B7B212ECF98B007A640B /* IconLocation.png */, 162 | 1029B7B312ECF98B007A640B /* IconLocation@2x.png */, 163 | 1029B7B412ECF98B007A640B /* IconZoomIn.png */, 164 | 1029B7B512ECF98B007A640B /* IconZoomIn@2x.png */, 165 | 1029B7B612ECF98B007A640B /* IconZoomOut.png */, 166 | 1029B7B712ECF98B007A640B /* IconZoomOut@2x.png */, 167 | 1029B7B812ECF98B007A640B /* pinGreen.png */, 168 | 1029B7B912ECF98B007A640B /* pinGreen@2x.png */, 169 | 1029B7BA12ECF98B007A640B /* pinOrange.png */, 170 | 1029B7BB12ECF98B007A640B /* pinOrange@2x.png */, 171 | 1029B7BC12ECF98B007A640B /* pinPurple.png */, 172 | 1029B7BD12ECF98B007A640B /* pinPurple@2x.png */, 173 | 1029B7BE12ECF98B007A640B /* pinRed.png */, 174 | 1029B7BF12ECF98B007A640B /* pinRed@2x.png */, 175 | 1029B7C012ECF98B007A640B /* pinYellow.png */, 176 | 1029B7C112ECF98B007A640B /* pinYellow@2x.png */, 177 | 1029B7C212ECF98B007A640B /* pinYellowGreen.png */, 178 | 1029B7C312ECF98B007A640B /* pinYellowGreen@2x.png */, 179 | 1029B7C412ECF98B007A640B /* UserHeading.png */, 180 | 1029B7C512ECF98B007A640B /* UserHeading@2x.png */, 181 | ); 182 | name = PNG; 183 | path = Shared/PNG; 184 | sourceTree = SOURCE_ROOT; 185 | }; 186 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 187 | isa = PBXGroup; 188 | children = ( 189 | 1D6058910D05DD3D006BFB54 /* VeloParis.app */, 190 | ); 191 | name = Products; 192 | sourceTree = ""; 193 | }; 194 | 2860E324111B887F00E27156 /* iPhone */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | 2860E325111B887F00E27156 /* AppDelegate_iPhone.h */, 198 | 2860E326111B887F00E27156 /* AppDelegate_iPhone.m */, 199 | 1001D4EB151E73E100975171 /* MainWindow_iPhone.xib */, 200 | ); 201 | path = iPhone; 202 | sourceTree = ""; 203 | }; 204 | 2860E32A111B888700E27156 /* iPad */ = { 205 | isa = PBXGroup; 206 | children = ( 207 | 2860E32B111B888700E27156 /* AppDelegate_iPad.h */, 208 | 2860E32C111B888700E27156 /* AppDelegate_iPad.m */, 209 | 2860E32D111B888700E27156 /* MainWindow_iPad.xib */, 210 | ); 211 | path = iPad; 212 | sourceTree = ""; 213 | }; 214 | 28EEBF621118D79A00187D67 /* Shared */ = { 215 | isa = PBXGroup; 216 | children = ( 217 | 105A3BFB13020631005B5D7C /* SynthesizeSingleton.h */, 218 | 1029B7ED12ECF9C5007A640B /* ConnectionDelegate.h */, 219 | 1029B7EE12ECF9C5007A640B /* ConnectionDelegate.m */, 220 | 1029B7EF12ECF9C5007A640B /* CustomizedTableCell.h */, 221 | 1029B7F012ECF9C5007A640B /* CustomizedTableCell.m */, 222 | 1029B7F212ECF9C5007A640B /* ParseStation.h */, 223 | 1029B7F312ECF9C5007A640B /* ParseStation.m */, 224 | 1029B7F412ECF9C5007A640B /* ParseStations.h */, 225 | 1029B7F512ECF9C5007A640B /* ParseStations.m */, 226 | 1029B7F612ECF9C5007A640B /* PinAnnotationView.h */, 227 | 1029B7F712ECF9C5007A640B /* PinAnnotationView.m */, 228 | 1029B7F812ECF9C5007A640B /* StationAnnotation.h */, 229 | 1029B7F912ECF9C5007A640B /* StationAnnotation.m */, 230 | 1029B7FA12ECF9C5007A640B /* SynthesizeSingleton.h */, 231 | 1029B7A012ECF98B007A640B /* PNG */, 232 | ); 233 | name = Shared; 234 | sourceTree = ""; 235 | }; 236 | 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { 237 | isa = PBXGroup; 238 | children = ( 239 | 2860E32A111B888700E27156 /* iPad */, 240 | 2860E324111B887F00E27156 /* iPhone */, 241 | 28EEBF621118D79A00187D67 /* Shared */, 242 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 243 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 244 | 19C28FACFE9D520D11CA2CBB /* Products */, 245 | ); 246 | name = CustomTemplate; 247 | sourceTree = ""; 248 | }; 249 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 250 | isa = PBXGroup; 251 | children = ( 252 | 1029B82912ECFAB7007A640B /* main.m */, 253 | 1029B80A12ECFA1A007A640B /* Info.plist */, 254 | 1029B81012ECFA40007A640B /* VeloParis_Prefix.pch */, 255 | ); 256 | name = "Other Sources"; 257 | sourceTree = ""; 258 | }; 259 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 260 | isa = PBXGroup; 261 | children = ( 262 | 1029E849121B1FBD00EB15A1 /* MapKit.framework */, 263 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 264 | 1D30AB110D05D00D00671497 /* Foundation.framework */, 265 | 288765FC0DF74451002DB57D /* CoreGraphics.framework */, 266 | 1029E862121B1FCE00EB15A1 /* CoreLocation.framework */, 267 | ); 268 | name = Frameworks; 269 | sourceTree = ""; 270 | }; 271 | /* End PBXGroup section */ 272 | 273 | /* Begin PBXNativeTarget section */ 274 | 1D6058900D05DD3D006BFB54 /* VeloParis */ = { 275 | isa = PBXNativeTarget; 276 | buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "VeloParis" */; 277 | buildPhases = ( 278 | 1D60588D0D05DD3D006BFB54 /* Resources */, 279 | 1D60588E0D05DD3D006BFB54 /* Sources */, 280 | 1D60588F0D05DD3D006BFB54 /* Frameworks */, 281 | ); 282 | buildRules = ( 283 | ); 284 | dependencies = ( 285 | ); 286 | name = VeloParis; 287 | productName = VeloParis; 288 | productReference = 1D6058910D05DD3D006BFB54 /* VeloParis.app */; 289 | productType = "com.apple.product-type.application"; 290 | }; 291 | /* End PBXNativeTarget section */ 292 | 293 | /* Begin PBXProject section */ 294 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 295 | isa = PBXProject; 296 | attributes = { 297 | LastUpgradeCheck = 0430; 298 | }; 299 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "VeloParis" */; 300 | compatibilityVersion = "Xcode 3.2"; 301 | developmentRegion = English; 302 | hasScannedForEncodings = 1; 303 | knownRegions = ( 304 | English, 305 | Japanese, 306 | French, 307 | German, 308 | zh_HK, 309 | zh_CN, 310 | ); 311 | mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; 312 | projectDirPath = ""; 313 | projectRoot = ""; 314 | targets = ( 315 | 1D6058900D05DD3D006BFB54 /* VeloParis */, 316 | ); 317 | }; 318 | /* End PBXProject section */ 319 | 320 | /* Begin PBXResourcesBuildPhase section */ 321 | 1D60588D0D05DD3D006BFB54 /* Resources */ = { 322 | isa = PBXResourcesBuildPhase; 323 | buildActionMask = 2147483647; 324 | files = ( 325 | 2860E32F111B888700E27156 /* MainWindow_iPad.xib in Resources */, 326 | 1029B7CA12ECF98B007A640B /* FavoriteOff.png in Resources */, 327 | 1029B7CB12ECF98B007A640B /* FavoriteOff@2x.png in Resources */, 328 | 1029B7CC12ECF98B007A640B /* FavoriteOn.png in Resources */, 329 | 1029B7CD12ECF98B007A640B /* FavoriteOn@2x.png in Resources */, 330 | 1029B7CE12ECF98B007A640B /* ICON.png in Resources */, 331 | 1029B7CF12ECF98B007A640B /* ICON@2x.png in Resources */, 332 | 1029B7D012ECF98B007A640B /* ICON-72.png in Resources */, 333 | 1029B7D112ECF98B007A640B /* ICON_SMALL.png in Resources */, 334 | 1029B7D212ECF98B007A640B /* ICON_SMALL@2x.png in Resources */, 335 | 1029B7D312ECF98B007A640B /* IconFavorite.png in Resources */, 336 | 1029B7D412ECF98B007A640B /* IconFavorite@2x.png in Resources */, 337 | 1029B7D512ECF98B007A640B /* IconList.png in Resources */, 338 | 1029B7D612ECF98B007A640B /* IconList@2x.png in Resources */, 339 | 1029B7D712ECF98B007A640B /* IconLocation.png in Resources */, 340 | 1029B7D812ECF98B007A640B /* IconLocation@2x.png in Resources */, 341 | 1029B7D912ECF98B007A640B /* IconZoomIn.png in Resources */, 342 | 1029B7DA12ECF98B007A640B /* IconZoomIn@2x.png in Resources */, 343 | 1029B7DB12ECF98B007A640B /* IconZoomOut.png in Resources */, 344 | 1029B7DC12ECF98B007A640B /* IconZoomOut@2x.png in Resources */, 345 | 1029B7DD12ECF98B007A640B /* pinGreen.png in Resources */, 346 | 1029B7DE12ECF98B007A640B /* pinGreen@2x.png in Resources */, 347 | 1029B7DF12ECF98B007A640B /* pinOrange.png in Resources */, 348 | 1029B7E012ECF98B007A640B /* pinOrange@2x.png in Resources */, 349 | 1029B7E112ECF98B007A640B /* pinPurple.png in Resources */, 350 | 1029B7E212ECF98B007A640B /* pinPurple@2x.png in Resources */, 351 | 1029B7E312ECF98B007A640B /* pinRed.png in Resources */, 352 | 1029B7E412ECF98B007A640B /* pinRed@2x.png in Resources */, 353 | 1029B7E512ECF98B007A640B /* pinYellow.png in Resources */, 354 | 1029B7E612ECF98B007A640B /* pinYellow@2x.png in Resources */, 355 | 1029B7E712ECF98B007A640B /* pinYellowGreen.png in Resources */, 356 | 1029B7E812ECF98B007A640B /* pinYellowGreen@2x.png in Resources */, 357 | 1029B7E912ECF98B007A640B /* UserHeading.png in Resources */, 358 | 1029B7EA12ECF98B007A640B /* UserHeading@2x.png in Resources */, 359 | 106DE877151E72CE001615B8 /* ICON-72@2x.png in Resources */, 360 | 1001D4EC151E73E100975171 /* MainWindow_iPhone.xib in Resources */, 361 | ); 362 | runOnlyForDeploymentPostprocessing = 0; 363 | }; 364 | /* End PBXResourcesBuildPhase section */ 365 | 366 | /* Begin PBXSourcesBuildPhase section */ 367 | 1D60588E0D05DD3D006BFB54 /* Sources */ = { 368 | isa = PBXSourcesBuildPhase; 369 | buildActionMask = 2147483647; 370 | files = ( 371 | 2860E328111B887F00E27156 /* AppDelegate_iPhone.m in Sources */, 372 | 2860E32E111B888700E27156 /* AppDelegate_iPad.m in Sources */, 373 | 1029B7FD12ECF9C5007A640B /* ConnectionDelegate.m in Sources */, 374 | 1029B7FE12ECF9C5007A640B /* CustomizedTableCell.m in Sources */, 375 | 1029B80012ECF9C5007A640B /* ParseStation.m in Sources */, 376 | 1029B80112ECF9C5007A640B /* ParseStations.m in Sources */, 377 | 1029B80212ECF9C5007A640B /* PinAnnotationView.m in Sources */, 378 | 1029B80312ECF9C5007A640B /* StationAnnotation.m in Sources */, 379 | 1029B82A12ECFAB7007A640B /* main.m in Sources */, 380 | ); 381 | runOnlyForDeploymentPostprocessing = 0; 382 | }; 383 | /* End PBXSourcesBuildPhase section */ 384 | 385 | /* Begin XCBuildConfiguration section */ 386 | 105CDC3E121DCEAB00927D13 /* Distribution */ = { 387 | isa = XCBuildConfiguration; 388 | buildSettings = { 389 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 390 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Mengke WANG"; 391 | GCC_C_LANGUAGE_STANDARD = c99; 392 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 393 | GCC_WARN_UNUSED_VARIABLE = YES; 394 | IPHONEOS_DEPLOYMENT_TARGET = 3.0; 395 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 396 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = "89F04576-A1E0-4988-8740-2F47648DA8DA"; 397 | SDKROOT = iphoneos; 398 | SYMROOT = ../build; 399 | TARGETED_DEVICE_FAMILY = 1; 400 | }; 401 | name = Distribution; 402 | }; 403 | 105CDC3F121DCEAB00927D13 /* Distribution */ = { 404 | isa = XCBuildConfiguration; 405 | buildSettings = { 406 | ALWAYS_SEARCH_USER_PATHS = NO; 407 | CODE_SIGN_IDENTITY = "iPhone Developer: Mengke WANG (HPHWG82ABX)"; 408 | COPY_PHASE_STRIP = YES; 409 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 410 | GCC_PREFIX_HEADER = VeloParis_Prefix.pch; 411 | INFOPLIST_FILE = Info.plist; 412 | PRODUCT_NAME = VeloParis; 413 | PROVISIONING_PROFILE = "1C223AEF-D072-4EC3-8AA7-67DA6F603E40"; 414 | TARGETED_DEVICE_FAMILY = "1,2"; 415 | VALIDATE_PRODUCT = YES; 416 | }; 417 | name = Distribution; 418 | }; 419 | 1D6058940D05DD3E006BFB54 /* Debug */ = { 420 | isa = XCBuildConfiguration; 421 | buildSettings = { 422 | ALWAYS_SEARCH_USER_PATHS = NO; 423 | CODE_SIGN_IDENTITY = "iPhone Developer: Mengke WANG (HPHWG82ABX)"; 424 | COPY_PHASE_STRIP = NO; 425 | GCC_DYNAMIC_NO_PIC = NO; 426 | GCC_OPTIMIZATION_LEVEL = 0; 427 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 428 | GCC_PREFIX_HEADER = VeloParis_Prefix.pch; 429 | INFOPLIST_FILE = Info.plist; 430 | PRODUCT_NAME = VeloParis; 431 | PROVISIONING_PROFILE = "1C223AEF-D072-4EC3-8AA7-67DA6F603E40"; 432 | TARGETED_DEVICE_FAMILY = "1,2"; 433 | }; 434 | name = Debug; 435 | }; 436 | 1D6058950D05DD3E006BFB54 /* Release */ = { 437 | isa = XCBuildConfiguration; 438 | buildSettings = { 439 | ALWAYS_SEARCH_USER_PATHS = NO; 440 | CODE_SIGN_IDENTITY = "iPhone Developer: Mengke WANG (HPHWG82ABX)"; 441 | COPY_PHASE_STRIP = YES; 442 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 443 | GCC_PREFIX_HEADER = VeloParis_Prefix.pch; 444 | INFOPLIST_FILE = Info.plist; 445 | PRODUCT_NAME = VeloParis; 446 | PROVISIONING_PROFILE = "1C223AEF-D072-4EC3-8AA7-67DA6F603E40"; 447 | TARGETED_DEVICE_FAMILY = "1,2"; 448 | VALIDATE_PRODUCT = YES; 449 | }; 450 | name = Release; 451 | }; 452 | C01FCF4F08A954540054247B /* Debug */ = { 453 | isa = XCBuildConfiguration; 454 | buildSettings = { 455 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 456 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Mengke WANG (HPHWG82ABX)"; 457 | GCC_C_LANGUAGE_STANDARD = c99; 458 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 459 | GCC_WARN_UNUSED_VARIABLE = YES; 460 | IPHONEOS_DEPLOYMENT_TARGET = 3.0; 461 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = "BA644FF9-D194-4B89-958B-B0F2F6914401"; 462 | SDKROOT = iphoneos; 463 | SYMROOT = ../build; 464 | TARGETED_DEVICE_FAMILY = 1; 465 | }; 466 | name = Debug; 467 | }; 468 | C01FCF5008A954540054247B /* Release */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 472 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Mengke WANG (HPHWG82ABX)"; 473 | GCC_C_LANGUAGE_STANDARD = c99; 474 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 475 | GCC_WARN_UNUSED_VARIABLE = YES; 476 | IPHONEOS_DEPLOYMENT_TARGET = 3.0; 477 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 478 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = "BA644FF9-D194-4B89-958B-B0F2F6914401"; 479 | SDKROOT = iphoneos; 480 | SYMROOT = ../build; 481 | TARGETED_DEVICE_FAMILY = 1; 482 | }; 483 | name = Release; 484 | }; 485 | /* End XCBuildConfiguration section */ 486 | 487 | /* Begin XCConfigurationList section */ 488 | 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "VeloParis" */ = { 489 | isa = XCConfigurationList; 490 | buildConfigurations = ( 491 | 1D6058940D05DD3E006BFB54 /* Debug */, 492 | 1D6058950D05DD3E006BFB54 /* Release */, 493 | 105CDC3F121DCEAB00927D13 /* Distribution */, 494 | ); 495 | defaultConfigurationIsVisible = 0; 496 | defaultConfigurationName = Release; 497 | }; 498 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "VeloParis" */ = { 499 | isa = XCConfigurationList; 500 | buildConfigurations = ( 501 | C01FCF4F08A954540054247B /* Debug */, 502 | C01FCF5008A954540054247B /* Release */, 503 | 105CDC3E121DCEAB00927D13 /* Distribution */, 504 | ); 505 | defaultConfigurationIsVisible = 0; 506 | defaultConfigurationName = Release; 507 | }; 508 | /* End XCConfigurationList section */ 509 | }; 510 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 511 | } 512 | --------------------------------------------------------------------------------