Index: trunk/tools/WikiSnaps/Classes/ImageUploadViewController.m |
— | — | @@ -33,16 +33,16 @@ |
34 | 34 | - (void)viewDidLoad { |
35 | 35 | [super viewDidLoad]; |
36 | 36 | |
37 | | - uploadOverlayImage.image = [UIImage imageWithData:upload.imageData]; |
| 37 | + uploadOverlayImage.image = self.upload.originalImage; |
38 | 38 | uploadProgressMessage.text = NSLocalizedString( @"uploading", @"Upload progress message" ); |
39 | 39 | uploadProgress.progress = 0.0f; |
40 | 40 | |
41 | 41 | // view.frame = CGRectMake(0, 20, 320, 460); |
42 | | - // [[UIApplication sharedApplication].keyWindow addSubview:uploadPhotoOverlay]; |
| 42 | + // [[UIApplication sharedApplication].keyWindow addSubview:PhotoOverlay]; |
43 | 43 | |
44 | 44 | // Start the actual upload |
45 | | - upload.delegate = self; |
46 | | - [upload uploadImage]; |
| 45 | + [self.upload setDelegate: self]; |
| 46 | + [self.upload uploadImage]; |
47 | 47 | } |
48 | 48 | |
49 | 49 | - (void) viewWillAppear:(BOOL)animated{ |
— | — | @@ -77,7 +77,7 @@ |
78 | 78 | |
79 | 79 | |
80 | 80 | - (void)dealloc { |
81 | | - [upload release]; |
| 81 | + self.upload = nil; |
82 | 82 | [super dealloc]; |
83 | 83 | } |
84 | 84 | |
— | — | @@ -92,8 +92,8 @@ |
93 | 93 | [[UIAlertView alloc] initWithTitle: NSLocalizedString( @"Upload succeeded", @"Title for upload succeeded alert" ) |
94 | 94 | message: nil |
95 | 95 | delegate: self |
96 | | - cancelButtonTitle: NSLocalizedString( @"Show upload", @"Title for Show upload button in alert view after upload succeeded" ) |
97 | | - otherButtonTitles: nil]; |
| 96 | + cancelButtonTitle: NSLocalizedString( @"Cancel", @"" ) |
| 97 | + otherButtonTitles: NSLocalizedString( @"Show upload", @"Title for Show upload button in alert view after upload succeeded" ),nil]; |
98 | 98 | [alert show]; |
99 | 99 | [alert release]; |
100 | 100 | } |
— | — | @@ -104,8 +104,12 @@ |
105 | 105 | } |
106 | 106 | |
107 | 107 | - (void) alertView: (UIAlertView *) alertView clickedButtonAtIndex: (NSInteger) buttonIndex { |
108 | | - [[UIApplication sharedApplication] openURL:[NSURL URLWithString: [NSString stringWithFormat: COMMONS_DESTINATION_URL, [upload.title stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]]; |
109 | | - //[self.navigationController popToRootViewControllerAnimated:YES]; |
| 108 | + if( buttonIndex == 0 ) { |
| 109 | + NSLog( @"Cancel" ); |
| 110 | + } else if ( buttonIndex == 1 ) { |
| 111 | + [[UIApplication sharedApplication] openURL:[NSURL URLWithString: [NSString stringWithFormat: COMMONS_DESTINATION_URL, [self.upload.imageTitle stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]]; |
| 112 | + } |
| 113 | + [self.navigationController popToRootViewControllerAnimated:YES]; |
110 | 114 | } // clickedButtonAtIndex |
111 | 115 | |
112 | 116 | |
Index: trunk/tools/WikiSnaps/Classes/ImageDetailsViewController.m |
— | — | @@ -63,9 +63,9 @@ |
64 | 64 | |
65 | 65 | |
66 | 66 | - (void)dealloc { |
67 | | - [titleField release]; |
68 | | - [descriptionText release]; |
69 | | - [upload release]; |
| 67 | + self.titleField = nil; |
| 68 | + self.descriptionText = nil; |
| 69 | + self.upload = nil; |
70 | 70 | [super dealloc]; |
71 | 71 | } |
72 | 72 | |
— | — | @@ -76,11 +76,11 @@ |
77 | 77 | -(void)textFieldDidEndEditing:(id)sender { |
78 | 78 | if(sender == titleField ) { |
79 | 79 | /* Verify name */ |
80 | | - if( ![upload verifyTitle: titleField.text] ) { |
81 | | - titleField.textColor = [UIColor redColor]; |
| 80 | + if( ![self.upload verifyTitle: self.titleField.text] ) { |
| 81 | + self.titleField.textColor = [UIColor redColor]; |
82 | 82 | } else { |
83 | | - titleField.textColor = [UIColor blackColor]; |
84 | | - [descriptionText becomeFirstResponder]; |
| 83 | + self.titleField.textColor = [UIColor blackColor]; |
| 84 | + [self.descriptionText becomeFirstResponder]; |
85 | 85 | } |
86 | 86 | return; |
87 | 87 | } |
— | — | @@ -94,12 +94,12 @@ |
95 | 95 | } |
96 | 96 | |
97 | 97 | - (void)doUpload:(id)sender { |
98 | | - upload.title = [NSString stringWithFormat: @"%@.jpg", titleField.text]; |
99 | | - upload.description = descriptionText.text; |
100 | | - [descriptionText resignFirstResponder]; |
| 98 | + self.upload.imageTitle = [NSString stringWithFormat: @"%@.jpg", self.titleField.text]; |
| 99 | + self.upload.description = self.descriptionText.text; |
| 100 | + [self.descriptionText resignFirstResponder]; |
101 | 101 | |
102 | 102 | ImageUploadViewController *uploadViewController = [[ImageUploadViewController alloc] init]; |
103 | | - uploadViewController.upload = upload; |
| 103 | + uploadViewController.upload = self.upload; |
104 | 104 | [self.navigationController pushViewController:uploadViewController animated:YES]; |
105 | 105 | [uploadViewController release]; |
106 | 106 | } |
Index: trunk/tools/WikiSnaps/Classes/SourcePickerViewController.h |
— | — | @@ -13,13 +13,17 @@ |
14 | 14 | #import "Configuration.h" |
15 | 15 | |
16 | 16 | @interface SourcePickerViewController : UITableViewController <UINavigationControllerDelegate, |
17 | | - UIImagePickerControllerDelegate> { |
| 17 | + UIImagePickerControllerDelegate> |
| 18 | +{ |
| 19 | + UIImagePickerController *imagePicker; |
18 | 20 | BOOL cameraAvailable; |
19 | 21 | BOOL fakeCameraAvailable; |
20 | | - NSData *imageData; |
| 22 | + UIImage *image; |
21 | 23 | |
22 | 24 | NSArray *licenses; |
23 | 25 | } |
| 26 | +@property (nonatomic, retain) UIImage *image; |
| 27 | +@property (nonatomic, retain) UIImagePickerController *imagePicker; |
24 | 28 | |
25 | 29 | - (IBAction)settingsPressed:(id)sender; |
26 | 30 | - (IBAction)infoPressed:(id)sender; |
Index: trunk/tools/WikiSnaps/Classes/SourcePickerViewController.m |
— | — | @@ -9,6 +9,8 @@ |
10 | 10 | // Based on Photopicker (MIT) |
11 | 11 | |
12 | 12 | #import "PhotoPickerAppDelegate.h" |
| 13 | +#import <AssetsLibrary/AssetsLibrary.h> |
| 14 | +#import <ImageIO/ImageIO.h> |
13 | 15 | |
14 | 16 | #import "SourcePickerViewController.h" |
15 | 17 | #import "SettingsViewController.h" |
— | — | @@ -24,13 +26,14 @@ |
25 | 27 | |
26 | 28 | /* Private */ |
27 | 29 | @interface SourcePickerViewController () |
28 | | - @property (nonatomic, retain) NSData *imageData; |
29 | 30 | - (void)pickPhoto:(UIImagePickerControllerSourceType)sourceType; |
| 31 | + - (void)detailsForImageWithURL:(NSURL *)assetURL; |
30 | 32 | @end |
31 | 33 | |
32 | 34 | @implementation SourcePickerViewController |
33 | 35 | |
34 | | -@synthesize imageData; |
| 36 | +@synthesize image; |
| 37 | +@synthesize imagePicker; |
35 | 38 | |
36 | 39 | #pragma mark - |
37 | 40 | #pragma mark Actions |
— | — | @@ -63,8 +66,8 @@ |
64 | 67 | |
65 | 68 | /* Open a photopicker */ |
66 | 69 | - (void)pickPhoto:(UIImagePickerControllerSourceType)sourceType { |
67 | | - UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init]; |
68 | | - imagePickerController.delegate = self; |
| 70 | + self.imagePicker = [[[UIImagePickerController alloc] init] autorelease]; |
| 71 | + self.imagePicker.delegate = self; |
69 | 72 | |
70 | 73 | // If the camera is force enabled, show the library instead. |
71 | 74 | #ifdef FORCE_ENABLE_CAMERA |
— | — | @@ -73,13 +76,68 @@ |
74 | 77 | } |
75 | 78 | #endif |
76 | 79 | |
77 | | - imagePickerController.sourceType = sourceType; |
| 80 | + self.imagePicker.sourceType = sourceType; |
78 | 81 | // imagePickerController.allowsImageEditing = YES; |
79 | | - |
80 | | - [self presentModalViewController:imagePickerController animated:YES]; |
81 | | - [imagePickerController release]; |
| 82 | + |
| 83 | + [self presentModalViewController:self.imagePicker animated:YES]; |
82 | 84 | } |
83 | 85 | |
| 86 | +- (NSMutableDictionary*)currentLocation { |
| 87 | + NSMutableDictionary *locDict = [[NSMutableDictionary alloc] init]; |
| 88 | + PhotoPickerAppDelegate *appDelegate = |
| 89 | + (PhotoPickerAppDelegate *) [UIApplication sharedApplication].delegate; |
| 90 | + CLLocation *lastLocation = appDelegate.lastLocation; |
| 91 | + |
| 92 | + if (lastLocation != nil) { |
| 93 | + CLLocationDegrees exifLatitude = lastLocation.coordinate.latitude; |
| 94 | + CLLocationDegrees exifLongitude = lastLocation.coordinate.longitude; |
| 95 | + CLLocationDistance exifAltitude = lastLocation.altitude; |
| 96 | + |
| 97 | + [locDict setObject:@"2.2.0.0" forKey:(NSString *)kCGImagePropertyGPSVersion]; |
| 98 | + [locDict setObject:lastLocation.timestamp forKey:(NSString*)kCGImagePropertyGPSTimeStamp]; |
| 99 | + |
| 100 | + if (exifLatitude < 0.0) { |
| 101 | + exifLatitude = exifLatitude*(-1); |
| 102 | + [locDict setObject:@"S" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef]; |
| 103 | + } else { |
| 104 | + [locDict setObject:@"N" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef]; |
| 105 | + } |
| 106 | + [locDict setObject:[NSNumber numberWithFloat:exifLatitude] forKey:(NSString*)kCGImagePropertyGPSLatitude]; |
| 107 | + |
| 108 | + if (exifLongitude < 0.0) { |
| 109 | + exifLongitude=exifLongitude*(-1); |
| 110 | + [locDict setObject:@"W" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef]; |
| 111 | + } else { |
| 112 | + [locDict setObject:@"E" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef]; |
| 113 | + } |
| 114 | + [locDict setObject:[NSNumber numberWithFloat:exifLongitude] forKey:(NSString*) kCGImagePropertyGPSLongitude]; |
| 115 | + |
| 116 | + if (!isnan(exifAltitude)){ |
| 117 | + if (exifAltitude < 0) { |
| 118 | + exifAltitude = -exifAltitude; |
| 119 | + [locDict setObject:@"1" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef]; |
| 120 | + } else { |
| 121 | + [locDict setObject:@"0" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef]; |
| 122 | + } |
| 123 | + [locDict setObject:[NSNumber numberWithFloat:exifAltitude] forKey:(NSString *)kCGImagePropertyGPSAltitude]; |
| 124 | + } |
| 125 | + |
| 126 | + // Speed, must be converted from m/s to km/h |
| 127 | + if (lastLocation.speed >= 0){ |
| 128 | + [locDict setObject:@"K" forKey:(NSString *)kCGImagePropertyGPSSpeedRef]; |
| 129 | + [locDict setObject:[NSNumber numberWithFloat:lastLocation.speed*3.6] forKey:(NSString *)kCGImagePropertyGPSSpeed]; |
| 130 | + } |
| 131 | + |
| 132 | + // Heading |
| 133 | + if (lastLocation.course >= 0){ |
| 134 | + [locDict setObject:@"T" forKey:(NSString *)kCGImagePropertyGPSTrackRef]; |
| 135 | + [locDict setObject:[NSNumber numberWithFloat:lastLocation.course] forKey:(NSString *)kCGImagePropertyGPSTrack]; |
| 136 | + } |
| 137 | + } |
| 138 | + |
| 139 | + return [locDict autorelease]; |
| 140 | +} |
| 141 | + |
84 | 142 | #pragma mark - |
85 | 143 | #pragma mark View lifecycle |
86 | 144 | |
— | — | @@ -214,18 +272,42 @@ |
215 | 273 | didFinishPickingMediaWithInfo:(NSDictionary *)info { |
216 | 274 | NSLog(@"Image info: %@",info); |
217 | 275 | |
218 | | - UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage]; |
| 276 | + self.image = [info valueForKey:UIImagePickerControllerOriginalImage]; |
| 277 | + NSURL *imageURL = [info valueForKey:UIImagePickerControllerMediaURL]; |
| 278 | + NSMutableDictionary *metaData = [NSMutableDictionary dictionaryWithDictionary:[info valueForKey:UIImagePickerControllerMediaMetadata]]; |
219 | 279 | |
220 | | - image = [image correctOrientation:image]; |
| 280 | + [metaData setObject:[self currentLocation] forKey: (NSString *)kCGImagePropertyGPSDictionary]; |
221 | 281 | |
222 | 282 | // Store the image on the Camera Roll |
223 | 283 | if( picker.sourceType == UIImagePickerControllerSourceTypeCamera ) { |
224 | | - UIImageWriteToSavedPhotosAlbum( image, nil, nil, nil ); |
| 284 | + Class assestsLibClass = (NSClassFromString(@"ALAssetsLibrary")); |
| 285 | + if( assestsLibClass != nil ) { |
| 286 | + ALAssetsLibrary *library = [[[ALAssetsLibrary alloc] init] autorelease]; |
| 287 | + |
| 288 | + ALAssetsLibraryWriteImageCompletionBlock completionBlock = ^(NSURL *newURL, NSError *error) { |
| 289 | + if (error) { |
| 290 | + NSLog( @"Could not write image to photoalbum: %@", error ); |
| 291 | + } else { |
| 292 | + [self detailsForImageWithURL: newURL]; |
| 293 | + } |
| 294 | + }; |
| 295 | + |
| 296 | + [library writeImageToSavedPhotosAlbum:[self.image CGImage] metadata:metaData completionBlock:completionBlock]; |
| 297 | + return; |
| 298 | + } else { |
| 299 | + self.image = [self.image correctOrientation:self.image]; |
| 300 | + UIImageWriteToSavedPhotosAlbum( self.image, nil, nil, nil ); |
| 301 | + } |
225 | 302 | } |
| 303 | + [self detailsForImageWithURL: imageURL]; |
226 | 304 | |
| 305 | +} |
| 306 | + |
| 307 | +- (void)detailsForImageWithURL:(NSURL *)assetURL { |
227 | 308 | // Prepare upload |
228 | 309 | CommonsUpload *ourUpload = [[CommonsUpload alloc] init]; |
229 | | - ourUpload.imageData = UIImageJPEGRepresentation(image, 0.85f); |
| 310 | + ourUpload.originalImage = self.image; |
| 311 | + ourUpload.imageURL = assetURL; |
230 | 312 | |
231 | 313 | ImageDetailsViewController *detailsController = [[ImageDetailsViewController alloc] init]; |
232 | 314 | |
— | — | @@ -235,8 +317,8 @@ |
236 | 318 | //to push the UIView. |
237 | 319 | [self.navigationController pushViewController:detailsController animated:YES]; |
238 | 320 | [detailsController release]; |
239 | | - |
240 | | - [picker dismissModalViewControllerAnimated:YES]; |
| 321 | + |
| 322 | + [self dismissModalViewControllerAnimated:YES]; |
241 | 323 | } |
242 | 324 | |
243 | 325 | |
— | — | @@ -252,7 +334,7 @@ |
253 | 335 | if (shouldCancelApp) { |
254 | 336 | //[self cancelApp]; |
255 | 337 | } else { |
256 | | - [picker dismissModalViewControllerAnimated:YES]; |
| 338 | + [self dismissModalViewControllerAnimated:YES]; |
257 | 339 | |
258 | 340 | //[self showPhotoSourceMenuOrPhotoSourceDirectly]; |
259 | 341 | } |
— | — | @@ -275,6 +357,8 @@ |
276 | 358 | |
277 | 359 | |
278 | 360 | - (void)dealloc { |
| 361 | + self.image = nil; |
| 362 | + self.imagePicker = nil; |
279 | 363 | [super dealloc]; |
280 | 364 | } |
281 | 365 | |
Index: trunk/tools/WikiSnaps/Classes/SettingsViewController.m |
— | — | @@ -43,8 +43,8 @@ |
44 | 44 | PhotoPickerAppDelegate *appDelegate = |
45 | 45 | (PhotoPickerAppDelegate *) [UIApplication sharedApplication].delegate; |
46 | 46 | |
47 | | - licenses = appDelegate.licenses; |
48 | | - selectedLicense = 0; |
| 47 | + self.licenses = appDelegate.licenses; |
| 48 | + self.selectedLicense = 0; |
49 | 49 | |
50 | 50 | [self loadData]; |
51 | 51 | |
— | — | @@ -97,33 +97,36 @@ |
98 | 98 | |
99 | 99 | |
100 | 100 | - (void)dealloc { |
101 | | - [username release]; |
102 | | - [password release]; |
103 | | - [license release]; |
104 | | - [save release]; |
| 101 | + self.username = nil; |
| 102 | + self.password = nil; |
| 103 | + self.license = nil; |
| 104 | + self.save = nil; |
| 105 | + |
| 106 | + self.licenses = nil; |
| 107 | + |
105 | 108 | [super dealloc]; |
106 | 109 | } |
107 | 110 | |
108 | 111 | #pragma mark Data loading and saving |
109 | 112 | |
110 | 113 | - (void)loadData { |
111 | | - username.text = [[NSUserDefaults standardUserDefaults] valueForKey: COMMONS_USERNAME_KEY]; |
| 114 | + self.username.text = [[NSUserDefaults standardUserDefaults] valueForKey: COMMONS_USERNAME_KEY]; |
112 | 115 | |
113 | 116 | NSString *licenseDefault = [[NSUserDefaults standardUserDefaults] stringForKey: COMMONS_LICENSE_KEY]; |
114 | | - NSEnumerator *enumerator = [licenses objectEnumerator]; |
| 117 | + NSEnumerator *enumerator = [self.licenses objectEnumerator]; |
115 | 118 | NSDictionary *aLicense; |
116 | 119 | while( licenseDefault != nil && (aLicense = [enumerator nextObject]) ) { |
117 | 120 | if( [licenseDefault compare: [aLicense objectForKey:@"short"]] == NSOrderedSame ) { |
118 | | - license.text = [aLicense objectForKey:@"name"]; |
| 121 | + self.license.text = [aLicense objectForKey:@"name"]; |
119 | 122 | break; |
120 | 123 | } |
121 | | - selectedLicense++; |
| 124 | + self.selectedLicense++; |
122 | 125 | } |
123 | | - if( selectedLicense == [licenses count] ) |
124 | | - selectedLicense = 0; |
| 126 | + if( self.selectedLicense == [self.licenses count] ) |
| 127 | + self.selectedLicense = 0; |
125 | 128 | |
126 | 129 | NSError *error = nil; |
127 | | - password.text = [SFHFKeychainUtils getPasswordForUsername:username.text andServiceName:COMMONS_KEYCHAIN_KEY error: &error]; |
| 130 | + self.password.text = [SFHFKeychainUtils getPasswordForUsername:username.text andServiceName:COMMONS_KEYCHAIN_KEY error: &error]; |
128 | 131 | if( error ) { |
129 | 132 | NSLog( @"pasword storage problem: %@", [error localizedDescription] ); |
130 | 133 | } |
— | — | @@ -132,7 +135,7 @@ |
133 | 136 | - (void)saveData { |
134 | 137 | NSError *error = nil; |
135 | 138 | NSString *oldUsername = [[NSUserDefaults standardUserDefaults] valueForKey: COMMONS_USERNAME_KEY]; |
136 | | - if( [username.text compare:oldUsername] != NSOrderedSame ) { |
| 139 | + if( [self.username.text compare:oldUsername] != NSOrderedSame ) { |
137 | 140 | /* Delete password for previous username */ |
138 | 141 | [SFHFKeychainUtils deleteItemForUsername:oldUsername andServiceName:COMMONS_KEYCHAIN_KEY error:&error]; |
139 | 142 | if( error ) { |
— | — | @@ -142,13 +145,13 @@ |
143 | 146 | } |
144 | 147 | |
145 | 148 | /* Save the data */ |
146 | | - [[NSUserDefaults standardUserDefaults] setObject:username.text forKey:COMMONS_USERNAME_KEY]; |
| 149 | + [[NSUserDefaults standardUserDefaults] setObject:self.username.text forKey:COMMONS_USERNAME_KEY]; |
147 | 150 | |
148 | | - NSDictionary *aLicense = [licenses objectAtIndex:selectedLicense]; |
| 151 | + NSDictionary *aLicense = [self.licenses objectAtIndex:self.selectedLicense]; |
149 | 152 | [[NSUserDefaults standardUserDefaults] setObject:[aLicense objectForKey:@"short"] forKey:COMMONS_LICENSE_KEY]; |
150 | 153 | |
151 | 154 | /* Store the password in the keychain */ |
152 | | - [SFHFKeychainUtils storeUsername: username.text andPassword: password.text forServiceName:COMMONS_KEYCHAIN_KEY updateExisting: YES error: &error]; |
| 155 | + [SFHFKeychainUtils storeUsername: self.username.text andPassword: self.password.text forServiceName:COMMONS_KEYCHAIN_KEY updateExisting: YES error: &error]; |
153 | 156 | |
154 | 157 | if( error ) { |
155 | 158 | NSLog( @"pasword storage problem: %@", [error localizedDescription] ); |
— | — | @@ -169,7 +172,7 @@ |
170 | 173 | |
171 | 174 | - (IBAction)textFieldDidEnd:(id)sender { |
172 | 175 | if(sender == username ) { |
173 | | - [password becomeFirstResponder]; |
| 176 | + [self.password becomeFirstResponder]; |
174 | 177 | return; |
175 | 178 | } |
176 | 179 | [sender resignFirstResponder]; |
— | — | @@ -186,8 +189,8 @@ |
187 | 190 | - (IBAction) pickLicensePicker:(id)sender{ |
188 | 191 | LicensePickerViewController *picker = [[LicensePickerViewController alloc] initWithNibName:@"LicensePickerViewController" bundle:nil]; |
189 | 192 | picker.delegate = self; |
190 | | - picker.licenses = licenses; |
191 | | - picker.selectedLicense = selectedLicense; |
| 193 | + picker.licenses = self.licenses; |
| 194 | + picker.selectedLicense = self.selectedLicense; |
192 | 195 | [self presentModalViewController:picker animated:YES]; |
193 | 196 | [picker release]; |
194 | 197 | } |
— | — | @@ -196,8 +199,8 @@ |
197 | 200 | |
198 | 201 | -(void)licensePickerDidFinish:(int)theSelectedLicense { |
199 | 202 | NSDictionary *licenseDict = [licenses objectAtIndex:theSelectedLicense]; |
200 | | - license.text = [licenseDict objectForKey:@"name"]; |
201 | | - selectedLicense = theSelectedLicense; |
| 203 | + self.license.text = [licenseDict objectForKey:@"name"]; |
| 204 | + self.selectedLicense = theSelectedLicense; |
202 | 205 | [self dismissModalViewControllerAnimated:YES]; |
203 | 206 | } |
204 | 207 | |
Index: trunk/tools/WikiSnaps/Classes/Configuration.h |
— | — | @@ -13,6 +13,7 @@ |
14 | 14 | #define COMMONS_USERNAME_KEY @"CommonsUsernameKey" |
15 | 15 | #define COMMONS_LICENSE_KEY @"CommonsLicenseKey" |
16 | 16 | #define COMMONS_KEYCHAIN_KEY @"CommonsKey" |
| 17 | +#define GEOTAGGING_KEY @"GeoTaggingKey" |
17 | 18 | |
18 | 19 | // Constants |
19 | 20 | #define COMMONS_DESTINATION_URL @"http://commons.wikimedia.org/wiki/File:%@" |
Index: trunk/tools/WikiSnaps/Classes/CommonsUpload.h |
— | — | @@ -20,8 +20,9 @@ |
21 | 21 | |
22 | 22 | |
23 | 23 | @interface CommonsUpload : NSObject { |
24 | | - NSData *imageData; |
25 | | - NSString *title; |
| 24 | + UIImage *originalImage; |
| 25 | + NSURL *imageURL; |
| 26 | + NSString *imageTitle; |
26 | 27 | NSString *description; |
27 | 28 | NSString *token; |
28 | 29 | NSString *editToken; |
— | — | @@ -29,8 +30,9 @@ |
30 | 31 | id <CommonsUploadDelegate> delegate; |
31 | 32 | } |
32 | 33 | |
33 | | -@property (nonatomic, retain) NSData *imageData; |
34 | | -@property (nonatomic, retain) NSString *title; |
| 34 | +@property (nonatomic, retain) UIImage *originalImage; |
| 35 | +@property (nonatomic, retain) NSURL *imageURL; |
| 36 | +@property (nonatomic, retain) NSString *imageTitle; |
35 | 37 | @property (nonatomic, retain) NSString *description; |
36 | 38 | @property (nonatomic, assign) id <CommonsUploadDelegate> delegate; |
37 | 39 | |
Index: trunk/tools/WikiSnaps/Classes/PhotoPickerAppDelegate.h |
— | — | @@ -8,6 +8,7 @@ |
9 | 9 | // Based on Photopicker (MIT) |
10 | 10 | |
11 | 11 | #import <UIKit/UIKit.h> |
| 12 | +#import <CoreLocation/CoreLocation.h> |
12 | 13 | |
13 | 14 | #import "Configuration.h" |
14 | 15 | |
— | — | @@ -15,27 +16,37 @@ |
16 | 17 | @class PhotoPickerViewController; |
17 | 18 | |
18 | 19 | |
19 | | -@interface PhotoPickerAppDelegate : NSObject <UIApplicationDelegate> { |
| 20 | +@interface PhotoPickerAppDelegate : NSObject <UIApplicationDelegate, |
| 21 | + CLLocationManagerDelegate> { |
20 | 22 | int defaultImageSource; |
21 | 23 | BOOL justInstalled; |
| 24 | + |
22 | 25 | NSString *postContext; |
23 | 26 | UIWindow *window; |
24 | 27 | PhotoPickerViewController *viewController; |
25 | 28 | UINavigationController *navController; |
| 29 | + |
26 | 30 | NSArray *licenses; |
| 31 | + |
| 32 | + CLLocationManager *locationManager; |
| 33 | + CLLocation *lastLocation; |
27 | 34 | } |
28 | 35 | |
29 | | -@property (nonatomic, assign) int defaultImageSource; |
| 36 | +@property int defaultImageSource; |
30 | 37 | |
31 | 38 | // Checking the justInstalled property could be useful if you want to point the somewhere special |
32 | 39 | // the first time they run the app. |
33 | | -@property (nonatomic, assign) BOOL justInstalled; |
| 40 | +@property BOOL justInstalled; |
34 | 41 | |
35 | 42 | @property (nonatomic, retain) NSString *postContext; |
36 | 43 | @property (nonatomic, retain) IBOutlet PhotoPickerViewController *viewController; |
37 | 44 | @property (nonatomic, retain) IBOutlet UINavigationController *navController; |
38 | 45 | @property (nonatomic, retain) IBOutlet UIWindow *window; |
| 46 | + |
39 | 47 | @property (nonatomic, retain) NSArray *licenses; |
40 | 48 | |
| 49 | +@property (nonatomic, assign) CLLocationManager *locationManager; |
| 50 | +@property (nonatomic, retain) CLLocation *lastLocation; |
| 51 | + |
41 | 52 | @end |
42 | 53 | |
Index: trunk/tools/WikiSnaps/Classes/LicensePickerViewController.m |
— | — | @@ -34,9 +34,9 @@ |
35 | 35 | dismissButton.action = @selector( dismissLicensePicker: ); |
36 | 36 | |
37 | 37 | [pickerControl selectRow:selectedLicense inComponent:0 animated: NO]; |
38 | | - NSDictionary *aLicense = [licenses objectAtIndex:selectedLicense]; |
39 | | - pickerLabel.text = [aLicense objectForKey:@"name"]; |
40 | | - [descriptionText loadHTMLString: [aLicense objectForKey:@"description"] baseURL: nil]; |
| 38 | + NSDictionary *aLicense = [self.licenses objectAtIndex:selectedLicense]; |
| 39 | + self.pickerLabel.text = [aLicense objectForKey:@"name"]; |
| 40 | + [self.descriptionText loadHTMLString: [aLicense objectForKey:@"description"] baseURL: nil]; |
41 | 41 | } |
42 | 42 | |
43 | 43 | |
— | — | @@ -63,13 +63,18 @@ |
64 | 64 | |
65 | 65 | |
66 | 66 | - (void)dealloc { |
| 67 | + self.descriptionText = nil; |
| 68 | + self.pickerLabel = nil; |
| 69 | + self.licenses = nil; |
| 70 | + self.delegate = nil; |
| 71 | + |
67 | 72 | [super dealloc]; |
68 | 73 | } |
69 | 74 | |
70 | 75 | #pragma mark Actions |
71 | 76 | - (IBAction) dismissLicensePicker: (id) sender |
72 | 77 | { |
73 | | - [delegate licensePickerDidFinish: [pickerControl selectedRowInComponent:0]]; |
| 78 | + [self.delegate licensePickerDidFinish: [pickerControl selectedRowInComponent:0]]; |
74 | 79 | } |
75 | 80 | |
76 | 81 | #pragma mark UIPickerViewDelegate |
— | — | @@ -78,7 +83,7 @@ |
79 | 84 | titleForRow: (NSInteger)row |
80 | 85 | forComponent: (NSInteger)component |
81 | 86 | { |
82 | | - NSDictionary *dict = [licenses objectAtIndex:row]; |
| 87 | + NSDictionary *dict = [self.licenses objectAtIndex:row]; |
83 | 88 | if( dict != nil ) { |
84 | 89 | return [dict objectForKey:@"short"]; |
85 | 90 | } |
— | — | @@ -89,10 +94,10 @@ |
90 | 95 | didSelectRow:(NSInteger)row |
91 | 96 | inComponent:(NSInteger)component |
92 | 97 | { |
93 | | - NSDictionary *dict = [licenses objectAtIndex:row]; |
| 98 | + NSDictionary *dict = [self.licenses objectAtIndex:row]; |
94 | 99 | if( dict != nil ) { |
95 | | - pickerLabel.text = [dict objectForKey:@"name"]; |
96 | | - [descriptionText loadHTMLString: [dict objectForKey:@"description"] baseURL: nil]; |
| 100 | + self.pickerLabel.text = [dict objectForKey:@"name"]; |
| 101 | + [self.descriptionText loadHTMLString: [dict objectForKey:@"description"] baseURL: nil]; |
97 | 102 | } |
98 | 103 | } |
99 | 104 | |
— | — | @@ -106,7 +111,7 @@ |
107 | 112 | |
108 | 113 | - (NSInteger)pickerView: (UIPickerView *)aPickerView numberOfRowsInComponent: (NSInteger)component |
109 | 114 | { |
110 | | - NSInteger numberOfRows = [licenses count]; |
| 115 | + NSInteger numberOfRows = [self.licenses count]; |
111 | 116 | |
112 | 117 | return numberOfRows; |
113 | 118 | } |
Index: trunk/tools/WikiSnaps/Classes/CommonsUpload.m |
— | — | @@ -8,6 +8,8 @@ |
9 | 9 | // Dual-licensed MIT and BSD |
10 | 10 | |
11 | 11 | #import "CommonsUpload.h" |
| 12 | +#import <AssetsLibrary/AssetsLibrary.h> |
| 13 | + |
12 | 14 | #import "Configuration.h" |
13 | 15 | #import "ASIFormDataRequest.h" |
14 | 16 | #import "XMLReader.h" |
— | — | @@ -23,8 +25,22 @@ |
24 | 26 | |
25 | 27 | @implementation CommonsUpload |
26 | 28 | |
27 | | -@synthesize imageData, title, description, delegate; |
| 29 | +@synthesize originalImage; |
| 30 | +@synthesize imageURL; |
| 31 | +@synthesize imageTitle; |
| 32 | +@synthesize description; |
| 33 | +@synthesize delegate; |
28 | 34 | |
| 35 | +- (void)dealloc { |
| 36 | + self.originalImage = nil; |
| 37 | + self.imageURL = nil; |
| 38 | + self.imageTitle = nil; |
| 39 | + self.description = nil; |
| 40 | + self.delegate = nil; |
| 41 | + |
| 42 | + [super dealloc]; |
| 43 | +} |
| 44 | + |
29 | 45 | - (NSString *)getUploadText { |
30 | 46 | return @""; |
31 | 47 | } |
— | — | @@ -60,14 +76,15 @@ |
61 | 77 | |
62 | 78 | NSLog(@"%@", dateString); |
63 | 79 | |
64 | | - return [NSString stringWithFormat: @"{{Information\n|Description={{en|1=%@}}\n|Author=[[User:%@]]\n|Source={{own}}\n|Date=%@\n|Permission=\n|other_versions=\n}}\n\n== {{int:license}} ==\n%@\n\n[[Category:%@]]", |
65 | | - description, |
66 | | - [[NSUserDefaults standardUserDefaults] valueForKey: COMMONS_USERNAME_KEY], |
67 | | - dateString, |
68 | | - [self getLicenseString], |
69 | | - APPLICATION_CATEGORY, |
70 | | - nil |
| 80 | + NSString *result = [NSString stringWithFormat: @"{{Information\n|Description={{en|1=%@}}\n|Author=[[User:%@]]\n|Source={{own}}\n|Date=%@\n|Permission=\n|other_versions=\n}}\n\n== {{int:license}} ==\n%@\n\n[[Category:%@]]", |
| 81 | + self.description, |
| 82 | + [[NSUserDefaults standardUserDefaults] stringForKey: COMMONS_USERNAME_KEY], |
| 83 | + dateString, |
| 84 | + [self getLicenseString], |
| 85 | + APPLICATION_CATEGORY |
71 | 86 | ]; |
| 87 | + NSLog( @"%@", result ); |
| 88 | + return result; |
72 | 89 | } |
73 | 90 | |
74 | 91 | - (void)uploadImage { |
— | — | @@ -196,7 +213,7 @@ |
197 | 214 | [newRequest addPostValue:@"query" forKey:@"action"]; |
198 | 215 | [newRequest addPostValue:@"xml" forKey: @"format"]; |
199 | 216 | [newRequest addPostValue:@"edit" forKey:@"intoken"]; |
200 | | - [newRequest addPostValue:title forKey:@"titles"]; |
| 217 | + [newRequest addPostValue:self.imageTitle forKey:@"titles"]; |
201 | 218 | [newRequest addPostValue:@"info" forKey:@"prop"]; |
202 | 219 | |
203 | 220 | [newRequest setDelegate:self]; |
— | — | @@ -242,7 +259,7 @@ |
243 | 260 | return; |
244 | 261 | } |
245 | 262 | |
246 | | - editToken = [query objectForKey:@"edittoken"]; |
| 263 | + editToken = [query objectForKey:@"edittoken"]; |
247 | 264 | if( !editToken ) { |
248 | 265 | [delegate uploadFailed: [NSString stringWithFormat:@"could not find edittoken"]]; |
249 | 266 | return; |
— | — | @@ -250,18 +267,43 @@ |
251 | 268 | |
252 | 269 | //New request |
253 | 270 | NSURL *url = [NSURL URLWithString:COMMONS_API_URL]; |
| 271 | + NSString *uploadDescription = [self getUploadDescription]; |
254 | 272 | ASIFormDataRequest *newRequest = [ASIFormDataRequest requestWithURL:url]; |
255 | 273 | [newRequest setPostFormat:ASIMultipartFormDataPostFormat]; |
256 | 274 | |
257 | 275 | [newRequest addPostValue:@"upload" forKey:@"action"]; |
258 | 276 | [newRequest addPostValue:@"xml" forKey: @"format"]; |
259 | 277 | [newRequest addPostValue:editToken forKey:@"token"]; |
260 | | - [newRequest addPostValue:title forKey:@"filename"]; |
261 | | - [newRequest addPostValue:[self getUploadDescription] forKey:@"comment"]; |
262 | | - [newRequest addPostValue:[self getUploadDescription] forKey:@"text"]; |
263 | | - [newRequest addData:imageData forKey:@"file"]; |
| 278 | + [newRequest addPostValue:self.imageTitle forKey:@"filename"]; |
| 279 | + [newRequest addPostValue:uploadDescription forKey:@"comment"]; |
| 280 | + [newRequest addPostValue:uploadDescription forKey:@"text"]; |
| 281 | + if( self.imageURL == nil && self.originalImage != nil ) { |
| 282 | + [newRequest addData:UIImageJPEGRepresentation(self.originalImage, 0.85f) forKey:@"file"]; |
| 283 | + } else if ( self.imageURL ) { |
| 284 | + ALAssetsLibrary *assetLib = [[[ALAssetsLibrary alloc] init] autorelease]; |
| 285 | + ALAssetsLibraryAssetForURLResultBlock resultBlock = |
| 286 | + ^(ALAsset *asset) { |
| 287 | + ALAssetRepresentation *representation = [asset defaultRepresentation]; |
| 288 | + Byte *buf = malloc([representation size]); |
| 289 | + NSError *err = nil; |
| 290 | + NSUInteger bytes = [representation getBytes:buf fromOffset:0LL length:[representation size] error:&err]; |
| 291 | + if (err || bytes == 0) { |
| 292 | + NSLog( @"Could not read asset: %@", err ); |
| 293 | + } else { |
| 294 | + NSData *cumbersomeWayToGetNSData = [NSData dataWithBytesNoCopy:buf length:[representation size] freeWhenDone:YES]; |
| 295 | + [newRequest addData:cumbersomeWayToGetNSData forKey:@"file"]; |
| 296 | + } |
| 297 | + }; |
| 298 | + |
| 299 | + [assetLib assetForURL:self.imageURL resultBlock:resultBlock failureBlock:^(NSError *error) { |
| 300 | + NSLog( @"Error finding asset: %@", error); |
| 301 | + }]; |
| 302 | + /* |
| 303 | + NSData *tempData = [NSData dataWithContentsOfURL:self.imageURL]; |
| 304 | + [newRequest addData:tempData forKey:@"file"]; |
| 305 | + */ |
| 306 | + } |
264 | 307 | |
265 | | - |
266 | 308 | [newRequest setDelegate:self]; |
267 | 309 | [newRequest setDidFinishSelector:@selector(requestUploadFinished:)]; |
268 | 310 | [newRequest setDidFailSelector:@selector(requestUploadFailed:)]; |
Index: trunk/tools/WikiSnaps/Classes/PhotoPickerAppDelegate.m |
— | — | @@ -12,6 +12,8 @@ |
13 | 13 | |
14 | 14 | @interface PhotoPickerAppDelegate () |
15 | 15 | - (void)checkIfJustInstalled; |
| 16 | + - (void)startLocationUpdates; |
| 17 | + - (void)stopLocationUpdates; |
16 | 18 | @end |
17 | 19 | |
18 | 20 | |
— | — | @@ -22,10 +24,11 @@ |
23 | 25 | @synthesize postContext; |
24 | 26 | @synthesize viewController; |
25 | 27 | @synthesize navController; |
26 | | -@synthesize window; |
27 | 28 | @synthesize licenses; |
28 | 29 | |
| 30 | +@synthesize locationManager, lastLocation; |
29 | 31 | |
| 32 | + |
30 | 33 | - (BOOL)application:(UIApplication *)application |
31 | 34 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { |
32 | 35 | |
— | — | @@ -34,28 +37,100 @@ |
35 | 38 | self.defaultImageSource = -1; |
36 | 39 | |
37 | 40 | NSString *path = [[NSBundle mainBundle] pathForResource:@"Licenses" ofType:@"plist"]; |
38 | | - licenses = [[NSMutableArray alloc] initWithContentsOfFile:path]; |
39 | | - if( licenses == nil ) { |
| 41 | + self.licenses = [[NSMutableArray alloc] initWithContentsOfFile:path]; |
| 42 | + if( self.licenses == nil ) { |
40 | 43 | NSLog( @"Could not load the licenses information" ); |
41 | 44 | } |
42 | 45 | |
43 | 46 | [window addSubview:navController.view]; |
44 | 47 | [window makeKeyAndVisible]; |
45 | | - |
| 48 | + |
| 49 | + [self startLocationUpdates]; |
46 | 50 | return YES; |
47 | 51 | } |
48 | 52 | |
| 53 | +- (void)applicationWillTerminate:(UIApplication *)application { |
| 54 | + [self stopLocationUpdates]; |
| 55 | +} |
49 | 56 | |
| 57 | +- (void)applicationWillEnterForeground:(UIApplication *)application { |
| 58 | + [self startLocationUpdates]; |
| 59 | +} |
| 60 | + |
| 61 | + |
| 62 | +- (void)applicationDidEnterBackground:(UIApplication *)application { |
| 63 | + [self stopLocationUpdates]; |
| 64 | +} |
| 65 | + |
| 66 | + |
50 | 67 | - (void)dealloc { |
51 | 68 | self.viewController = nil; |
52 | 69 | self.navController = nil; |
53 | 70 | self.window = nil; |
54 | | - [licenses release]; |
| 71 | + self.licenses = nil; |
| 72 | + self.lastLocation = nil; |
55 | 73 | |
56 | 74 | [super dealloc]; |
57 | 75 | } |
58 | 76 | |
| 77 | +#pragma mark Location services |
| 78 | +- (void)startLocationUpdates { |
| 79 | + // Create the location manager if this object does not |
| 80 | + // already have one. |
| 81 | + if( [CLLocationManager locationServicesEnabled] && |
| 82 | + //[[NSUserDefaults standardUserDefaults] boolForKey: GEOTAGGING_KEY] ) |
| 83 | + TRUE ) |
| 84 | + { |
| 85 | + if (nil == self.locationManager) |
| 86 | + self.locationManager = [[CLLocationManager alloc] init]; |
| 87 | + |
| 88 | + self.locationManager.delegate = self; |
| 89 | + self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; |
| 90 | + |
| 91 | + // Set a movement threshold for new events. |
| 92 | + self.locationManager.distanceFilter = 500; |
| 93 | + |
| 94 | + [self.locationManager startUpdatingLocation]; |
| 95 | + |
| 96 | + if( [self.locationManager headingAvailable] ) { |
| 97 | + [self.locationManager startUpdatingHeading]; |
| 98 | + } |
| 99 | + } |
| 100 | +} |
59 | 101 | |
| 102 | +- (void)stopLocationUpdates { |
| 103 | + if( self.locationManager != nil ) { |
| 104 | + [self.locationManager stopUpdatingHeading]; |
| 105 | + [self.locationManager stopUpdatingLocation]; |
| 106 | + [self.locationManager release]; |
| 107 | + self.locationManager = nil; |
| 108 | + } |
| 109 | +} |
| 110 | + |
| 111 | +#pragma mark LocationManager Delegate |
| 112 | + |
| 113 | +// Delegate method from the CLLocationManagerDelegate protocol. |
| 114 | +- (void)locationManager:(CLLocationManager *)manager |
| 115 | + didUpdateToLocation:(CLLocation *)newLocation |
| 116 | + fromLocation:(CLLocation *)oldLocation |
| 117 | +{ |
| 118 | + // If it's a relatively recent event, turn off updates to save power |
| 119 | + NSDate* eventDate = newLocation.timestamp; |
| 120 | + NSTimeInterval howRecent = [eventDate timeIntervalSinceNow]; |
| 121 | + if (abs(howRecent) < 15.0) |
| 122 | + { |
| 123 | + NSLog(@"latitude %+.6f, longitude %+.6f\n", |
| 124 | + newLocation.coordinate.latitude, |
| 125 | + newLocation.coordinate.longitude); |
| 126 | + } |
| 127 | + self.lastLocation = newLocation; |
| 128 | +} |
| 129 | + |
| 130 | +- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error |
| 131 | +{ |
| 132 | + NSLog(@"%@", error ); |
| 133 | +} |
| 134 | + |
60 | 135 | #pragma mark Private |
61 | 136 | |
62 | 137 | |
— | — | @@ -66,6 +141,7 @@ |
67 | 142 | if (!testForInstallKey) { |
68 | 143 | self.justInstalled = YES; |
69 | 144 | [defaults setBool:YES forKey:@"installed"]; |
| 145 | + [defaults setBool:NO forKey:GEOTAGGING_KEY]; |
70 | 146 | } |
71 | 147 | } |
72 | 148 | |
Index: trunk/tools/WikiSnaps/WikiSnaps.xcodeproj/project.pbxproj |
— | — | @@ -25,6 +25,9 @@ |
26 | 26 | 4971EC87133E77FD0043DD67 /* Licenses.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4971EC86133E77FD0043DD67 /* Licenses.plist */; }; |
27 | 27 | 4971ED31133E9DD90043DD67 /* LicensePickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4971ED2F133E9DD90043DD67 /* LicensePickerViewController.m */; }; |
28 | 28 | 4971ED32133E9DD90043DD67 /* LicensePickerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4971ED30133E9DD90043DD67 /* LicensePickerViewController.xib */; }; |
| 29 | + 49E03406133F6C1300BFE247 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49E03405133F6C1300BFE247 /* CoreLocation.framework */; }; |
| 30 | + 49E0340A133F72A100BFE247 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49E03409133F72A100BFE247 /* AssetsLibrary.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; |
| 31 | + 49E03463133F814D00BFE247 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49E03462133F814D00BFE247 /* ImageIO.framework */; }; |
29 | 32 | A127DA4012E0DF9700149FC9 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A127DA3E12E0DF9700149FC9 /* SettingsViewController.m */; }; |
30 | 33 | A127DA4112E0DF9700149FC9 /* SettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = A127DA3F12E0DF9700149FC9 /* SettingsViewController.xib */; }; |
31 | 34 | A1338B8612E0F01700662B28 /* ASIAuthenticationDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = A1338B7312E0F01700662B28 /* ASIAuthenticationDialog.m */; }; |
— | — | @@ -80,6 +83,9 @@ |
81 | 84 | 4971ED2E133E9DD90043DD67 /* LicensePickerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LicensePickerViewController.h; sourceTree = "<group>"; }; |
82 | 85 | 4971ED2F133E9DD90043DD67 /* LicensePickerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LicensePickerViewController.m; sourceTree = "<group>"; }; |
83 | 86 | 4971ED30133E9DD90043DD67 /* LicensePickerViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = LicensePickerViewController.xib; path = Classes/LicensePickerViewController.xib; sourceTree = "<group>"; }; |
| 87 | + 49E03405133F6C1300BFE247 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; |
| 88 | + 49E03409133F72A100BFE247 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; |
| 89 | + 49E03462133F814D00BFE247 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; |
84 | 90 | 8D1107310486CEB800E47090 /* WikiSnaps-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "WikiSnaps-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; }; |
85 | 91 | A127DA3D12E0DF9700149FC9 /* SettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsViewController.h; sourceTree = "<group>"; }; |
86 | 92 | A127DA3E12E0DF9700149FC9 /* SettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsViewController.m; sourceTree = "<group>"; }; |
— | — | @@ -142,6 +148,9 @@ |
143 | 149 | A159144712E0F69C0003BBE2 /* MobileCoreServices.framework in Frameworks */, |
144 | 150 | A159144B12E0F6BE0003BBE2 /* SystemConfiguration.framework in Frameworks */, |
145 | 151 | 49354963130096A000A7A44E /* Security.framework in Frameworks */, |
| 152 | + 49E03406133F6C1300BFE247 /* CoreLocation.framework in Frameworks */, |
| 153 | + 49E0340A133F72A100BFE247 /* AssetsLibrary.framework in Frameworks */, |
| 154 | + 49E03463133F814D00BFE247 /* ImageIO.framework in Frameworks */, |
146 | 155 | ); |
147 | 156 | runOnlyForDeploymentPostprocessing = 0; |
148 | 157 | }; |
— | — | @@ -231,6 +240,9 @@ |
232 | 241 | A159144612E0F69C0003BBE2 /* MobileCoreServices.framework */, |
233 | 242 | A159144A12E0F6BE0003BBE2 /* SystemConfiguration.framework */, |
234 | 243 | 49354962130096A000A7A44E /* Security.framework */, |
| 244 | + 49E03405133F6C1300BFE247 /* CoreLocation.framework */, |
| 245 | + 49E03409133F72A100BFE247 /* AssetsLibrary.framework */, |
| 246 | + 49E03462133F814D00BFE247 /* ImageIO.framework */, |
235 | 247 | ); |
236 | 248 | name = Frameworks; |
237 | 249 | sourceTree = "<group>"; |