MKMapView pin animation and annotation - objective-c

I'm using the google places API to find some restaurants nearby (based on current location using core location manager); currently, I'm able to drop pins. I use the searchBarSearchButtonClicked method, and inside of a dispatch_async block, I call my method to parse through my serialized data and attribute values to properties of my pin class (class MKAnnotation). I'd like to animate my pin drops, and also actually display annotations...for some reason I had them working before but now they won't show up when I click on the pins.
VIEW CONTROLLER.H
#interface MyViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate, UISearchBarDelegate,NSURLSessionDelegate> {
CLLocationManager *locationManager;
}
#property (strong, nonatomic) MKMapView *mapView;
#property (strong, nonatomic) UISearchBar *searchBar;
#property (strong, nonatomic) UIImageView *logo;
#property (strong, nonatomic) UIToolbar *toolBar;
#property (strong, nonatomic) NSString *places;
#end
VIEW CONTROLLER.M
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSLog(#"%#", self.searchBar.text);
NSURLSession *session = [NSURLSession sharedSession];
NSString *s = [NSString
stringWithFormat:#"https://maps.googleapis.com/maps/api/place/nearbysearch/json?keyword=%#&location=%f,%f&radius=5&types=food&key=AIzaSyCg6Ahz_hQ1f2rjKEAWcJKQetblPVjHS-E", self.searchBar.text, locationManager.location.coordinate.latitude, locationManager.location.coordinate.longitude];
NSURL *url = [[NSURL alloc]initWithString:s];
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSData *dataResponse = [[NSData alloc]initWithContentsOfURL:location];
NSDictionary *dictionaryReponse = [NSJSONSerialization JSONObjectWithData:dataResponse options:kNilOptions error:&error];
NSMutableArray *finalResults = [dictionaryReponse objectForKey:#"results"];
dispatch_async(dispatch_get_main_queue(), ^{
[self placeAnnotations:finalResults];
});
}];
[task resume];
}
-(void)placeAnnotations:(NSMutableArray *)data {
for (id<MKAnnotation> annotation in self.mapView.annotations) {
// if ([annotation isKindOfClass:[MapPoint class]]) {
[self.mapView removeAnnotation:annotation];
// }
}
for (int i = 0; i < [data count]; i++) {
NSDictionary *place = [data objectAtIndex:i];
NSDictionary *geo = [place objectForKey:#"geometry"];
NSDictionary *location = [geo objectForKey:#"location"];
NSString *name = [place objectForKey:#"name"];
NSString *vicinity = [place objectForKey:#"vicinity"];
CLLocationCoordinate2D placeCoord;
placeCoord.latitude = [[location objectForKey:#"lat"] doubleValue];
placeCoord.longitude = [[location objectForKey:#"lng"] doubleValue];
MapPoint *newPin = [MapPoint new];
newPin.name = name;
newPin.address = vicinity;
newPin.coordinate = placeCoord;
MKPinAnnotationView *newAnnotation = [[MKPinAnnotationView alloc]initWithAnnotation:newPin reuseIdentifier:#"annotation"];
newAnnotation.animatesDrop = YES;
[self.mapView addAnnotation:newPin];
}
[self.mapView reloadInputViews];
}
I

Related

How to add directions among two custom locations in Mapview for IOS 7 (objective c)

I have to add directions among two custom locations in IOS 7.
Any one tell me please.
Thanks.
Try this:
1.Create a file named ViewController with MKMapView as an IBOutlet and connect the map view from Storyboard to MKMapView property.
[ViewController.h]
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <MapKit/MKAnnotation.h>
#interface ViewController : UIViewController <MKMapViewDelegate>
#property (nonatomic, strong) IBOutlet MKMapView *mapView;
#end
[ViewController.m]
#import "ViewController.h"
#import "Annotation.h"
#define Location1Latitude -12.429481
#define Location1Longitude 130.863324
#define Location2Latitude -32.15037
#define Location2Longitude 115.782909
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.mapView.delegate = self;
[self.mapView setMapType:MKMapTypeStandard];
[self.mapView setZoomEnabled:YES];
[self.mapView setScrollEnabled:YES];
//Annotation
NSMutableArray * locations = [[NSMutableArray alloc] init];
CLLocationCoordinate2D location;
Annotation * myAnn;
// Location 1 Annotation
myAnn = [[Annotation alloc] init];
location.latitude = Location1Latitude;
location.longitude = Location1Longitude;
[locations addObject:myAnn];
//Location 2 Annotation
myAnn = [[Annotation alloc] init];
location.latitude = Location2Latitude;
location.longitude = Location2Longitude;
myAnn.coordinate = location;
[locations addObject:myAnn];
[self.mapView addAnnotations:locations];
[self performSelector:#selector(drawRoute) withObject:self afterDelay:1.0];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)drawRoute {
MKPlacemark *source = [[MKPlacemark alloc]initWithCoordinate:CLLocationCoordinate2DMake(Location1Latitude, Location1Longitude) addressDictionary:nil];
MKMapItem *srcMapItem = [[MKMapItem alloc]initWithPlacemark:source];
[srcMapItem setName:#"source"];
MKPlacemark *destination = [[MKPlacemark alloc]initWithCoordinate:CLLocationCoordinate2DMake(Location2Latitude, Location2Longitude) addressDictionary:nil ];
MKMapItem *destMapItem = [[MKMapItem alloc]initWithPlacemark:destination];
[destMapItem setName:#"dest"];
MKDirectionsRequest *request = [[MKDirectionsRequest alloc]init];
[request setSource:srcMapItem];
[request setDestination:destMapItem];
[request setTransportType:MKDirectionsTransportTypeAutomobile];
MKDirections *direction = [[MKDirections alloc]initWithRequest:request];
[direction calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
NSLog(#"response = %# \n eror %#",response, error);
NSArray *arrRoutes = [response routes];
[arrRoutes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
MKRoute *rout = obj;
MKPolyline *line = [rout polyline];
[self.mapView addOverlay:line];
NSLog(#"Rout Name : %#",rout.name);
NSLog(#"Total Distance (in Meters) :%f",rout.distance);
NSArray *steps = [rout steps];
NSLog(#"Total Steps : %lu",(unsigned long)[steps count]);
[steps enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"Rout Distance : %f",[obj distance]);
NSLog(#"Rout Instruction : %#",[obj instructions]);
}];
}];
}];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id < MKOverlay >)overlay
{
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
renderer.strokeColor = [UIColor colorWithRed:55.0/255.0 green:160.0/255.0 blue:250.0/255.0 alpha:1.0];
renderer.lineWidth = 4.0;
return renderer;
}
2.Create a file named Annotation.
[Annotation.h]
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface Annotation : NSObject <MKAnnotation>
#property(nonatomic, assign) CLLocationCoordinate2D coordinate;
#property(nonatomic, copy) NSString * title;
#property(nonatomic, copy) NSString * subtitle;
#property(nonatomic, copy) NSString * imageName;
#end
[Annotation.m]
#import "Annotation.h"
#implementation Annotation
#end

json photo path xcode

i can't get my photo in json, did i haven't something wrong to get that? i already check my photo url in php,it works,
in my tableview.m file:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailHomeViewController * dvc = [[DetailHomeViewController alloc]init];
HomeDetail * currentHome = [HomeArray objectAtIndex:indexPath.row];
dvc.photodetail = currentHome.photo_path;
NSURL *url = [NSURL URLWithString:dvc.photodetail];
NSData *data = [NSData dataWithContentsOfURL:url];
dvc.photolabel.image = [UIImage imageWithData:data];
[self presentViewController:dvc animated:YES completion:nil];
}
#pragma mark - Methods
- (void) retrieveData
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSURL * url = [NSURL URLWithString:getDataURL];
NSData * data = [NSData dataWithContentsOfURL:url];
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
HomeArray = [[NSMutableArray alloc]init];
for (int i = 0; i < json.count; i++)
{
NSString * photo = [[json objectAtIndex:i] objectForKey:#"photo_path"];
HomeDetail * home2 = [[HomeDetail alloc]initWithPhoto_path:photo];
[HomeArray addObject:home2];
}
[self.myTableView reloadData];
}
my HomeDetail.h file:(Json file)
#property (nonatomic, strong) NSString * photo_path;
//Methods
- (id) initWithPhoto_path: (NSString *) photo ;
my HomeDetail.m file:
- (id) initWithPhoto_path: (NSString *) photo ;
{
self = [super init];
if (self)
{photo_path = photo;}
return self;
}
my DetailHomeViewController.h file:
#property (nonatomic, strong) NSString * photodetail;
#property (strong, nonatomic) IBOutlet UIImageView *photolabel;
my DetailHomeViewController.m file:
- (void)viewDidLoad
{
[super viewDidLoad];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
// photolabel.image = photodetail;
NSURL *url = [NSURL URLWithString:photodetail];
NSData *data = [NSData dataWithContentsOfURL:url];
photolabel.image = [UIImage imageWithData:data];
}
and here is my json data:
[{"id":"2","detail_english":" TESTING_DETAIL","photo_path":"img\/uploads\/news\/news_20150320075842.png","date":"2013-10-15"‌​,"display_stat":"1","news_order":"1"},
{"id":"5","detail_english":"empty","photo_path":"img\/uploads\/news\/news_20150323105547.png","date":"2015-03-20","display_stat":"1","news_order":"1"}]
Your photo path is not a full url, you need to append the domain name.
So you string would look like this:
http://www.domain.com/img/uploads/news/news_20150323105547.png

AVAssetWriter is always on AVAssetWriterStatusFailed status

my goal is to apply some filters on the camera input in real time. To do that step by step, I'm trying to get the input form the camera with AVFoundation record a video and save it in the camera roll. I tried, but for some reason the AVAssetWriter is always in AVAssetWriterStatusFailed and so the appendSampleBuffer: method always failed. Where is my error? Someone can help me?
Thanks!
ViewController.h
#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>
#import <AVFoundation/AVFoundation.h>
#interface ViewController : UIViewController <AVCaptureVideoDataOutputSampleBufferDelegate>
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet UIButton *startRecButton;
#property (weak, nonatomic) IBOutlet UIButton *stopRecButton;
#property (weak, nonatomic) IBOutlet UIButton *startVideocamera;
- (IBAction)startRecordingButtonPressed:(UIButton *)sender;
- (IBAction)stopRecordingButtonPressed:(UIButton *)sender;
- (IBAction)startVideocameraButtonPressed:(UIButton *)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#property (strong, nonatomic) AVAssetWriter* videoAssetWriter;
#property (strong, nonatomic) AVAssetWriterInput* videoAssetWriterInput;
#property (strong, nonatomic) NSURL* temporaryVideoURL;
#end
#implementation ViewController
#pragma mark - Variables
#synthesize imageView;
#synthesize videoAssetWriter;
#synthesize videoAssetWriterInput;
#synthesize temporaryVideoURL;
//initCaptureSession Method
AVCaptureSession* captureSession;
AVCaptureDevice* videoCaptureDevice;
AVCaptureDeviceInput* videoCaptureDeviceInput;
AVCaptureVideoDataOutput* videoDataOutput;
dispatch_queue_t videoQueue;
//captureOutput:didOutputSampleBuffer Method
CMSampleBufferRef currentSampleBuffer;
BOOL isRecording;
//newPixelBufferFromCGImage Method
CGAffineTransform frameTransform;
CGSize frameSize;
#pragma mark - User Interface
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)startRecordingButtonPressed:(UIButton *)sender {
[self initWriter];
}
- (IBAction)stopRecordingButtonPressed:(UIButton *)sender {
[self stopWriter];
}
- (IBAction)startVideocameraButtonPressed:(UIButton *)sender {
[self initCaptureSession];
}
#pragma mark - Capture Utils
-(void) initCaptureSession{
captureSession = [[AVCaptureSession alloc] init];
[captureSession setSessionPreset:AVCaptureSessionPreset1280x720];
videoCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError* error;
videoCaptureDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:videoCaptureDevice error:&error];
if([captureSession canAddInput:videoCaptureDeviceInput]){
[captureSession addInput:videoCaptureDeviceInput];
}
videoDataOutput = [[AVCaptureVideoDataOutput alloc]init];
[captureSession addOutput:videoDataOutput];
videoQueue = dispatch_queue_create("videoQueue", NULL);
[videoDataOutput setAlwaysDiscardsLateVideoFrames:NO];
[videoDataOutput setSampleBufferDelegate:self queue:videoQueue];
NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
[videoDataOutput setVideoSettings:videoSettings];
[captureSession startRunning];
}
-(void) captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer: (CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
currentSampleBuffer = sampleBuffer;
CGImageRef image = [self imageFromSampleBuffer:currentSampleBuffer];
dispatch_sync(dispatch_get_main_queue(),
^{
if(!isRecording){
imageView.image = [UIImage imageWithCGImage: image scale:1.0 orientation:UIImageOrientationRight];
}
else{
imageView.image = [UIImage imageWithCGImage: image scale:1.0 orientation:UIImageOrientationRight];
// [videoAssetWriterInput appendSampleBuffer:currentSampleBuffer];
if (![videoAssetWriterInput appendSampleBuffer:sampleBuffer]) {
[self showError:[videoAssetWriter error]];
}
NSLog(#"%ld", (long)[videoAssetWriter status]);
}
});
CGImageRelease(image);
}
-(void)captureOutput:(AVCaptureOutput *)captureOutput didDropSampleBuffer: (CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
NSLog(#"didDropSampleBuffer CALLED");
}
#pragma mark - Writer Utils
-(void) initWriter{
temporaryVideoURL = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#%#", NSTemporaryDirectory(), #"Movie.MOV"]];
NSLog(#"%#", temporaryVideoURL);
NSError* error;
videoAssetWriter = [[AVAssetWriter alloc] initWithURL:temporaryVideoURL fileType:AVFileTypeQuickTimeMovie error:&error];
NSParameterAssert(videoAssetWriter);
NSLog(#"%ld", (long)[videoAssetWriter status]);
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt:1280], AVVideoWidthKey,
[NSNumber numberWithInt:720], AVVideoHeightKey,
nil];
videoAssetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
NSParameterAssert(videoAssetWriterInput);
NSLog(#"%ld", (long)[videoAssetWriter status]);
if([videoAssetWriter canAddInput:videoAssetWriterInput]){
[videoAssetWriter addInput:videoAssetWriterInput];
}
isRecording = YES;
[videoAssetWriter startWriting];
NSLog(#"%ld", (long)[videoAssetWriter status]);
}
-(void) stopWriter{
[videoAssetWriterInput markAsFinished];
[videoAssetWriter finishWritingWithCompletionHandler:^{
NSLog(#"finishWritingWithCompletionHandler CALLED");
isRecording = NO;
[self saveVideoToCameraRoll];
videoAssetWriter =nil;
videoAssetWriterInput= nil;
}];
// [videoAssetWriter finishWriting];
// isRecording = NO;
// [self saveVideoToCameraRoll];
}
-(void) saveVideoToCameraRoll{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:temporaryVideoURL completionBlock:^(NSURL *assetURL, NSError *error){
NSLog(#"ASSET URL: %#", [assetURL path]);
if(error) {
NSLog(#"CameraViewController: Error on saving movie : %# {imagePickerController}", error);
}
else {
NSLog(#"Video salvato correttamente in URL: %#", assetURL);
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[temporaryVideoURL path]];
NSLog(#"IL FILE ESISTE: %hhd", fileExists);
NSLog(#"E PESA: %#", [[[NSFileManager defaultManager] attributesOfItemAtPath: [temporaryVideoURL path] error:&error] objectForKey:NSFileSize]);
}
}];
}
This error is because of a reason that a file with similar filename already exist.
In my case, I was using a static file name for testing purpose, which caused the error. Making it something unique something like:
"\(Date().timeIntervalSince1970).mp4" fixed it.

Encoding a CLLocationcoordinate2D

I am trying to encode annotations that are on a map, but I read that I am not able to encode CLLocationcoordinate2D variables. Does anyone know how I can solve this? Here is some code.
This is where I drop the pins:
- (void)press:(UILongPressGestureRecognizer *)recognizer {
CGPoint touchPoint = [recognizer locationInView:_worldView];
CLLocationCoordinate2D touchMapCoordinate = [_worldView convertPoint:touchPoint toCoordinateFromView:_worldView];
geocoder = [[CLGeocoder alloc]init];
CLLocation *location = [[CLLocation alloc]initWithCoordinate:touchMapCoordinate
altitude:CLLocationDistanceMax
horizontalAccuracy:kCLLocationAccuracyBest
verticalAccuracy:kCLLocationAccuracyBest
timestamp:[NSDate date]];
[geocoder reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error) {
//NSLog(#"reverseGeocoder:completionHandler: called");
if (error) {
//NSLog(#"Geocoder failed with error: %#", error);
} else {
CLPlacemark *place = [placemarks objectAtIndex:0];
geocodedAddress = [NSString stringWithFormat:#"%# %#, %# %#", [place subThoroughfare], [place thoroughfare], [place locality], [place administrativeArea]];
if (UIGestureRecognizerStateBegan == [recognizer state]) {
value = [number intValue];
number = [NSNumber numberWithInt:value + 1];
_addressPin = [[MapPoint alloc]initWithAddress:geocodedAddress coordinate:touchMapCoordinate
title:geocodedAddress identifier:number];
NSLog(#"The identifier is %#", number);
[[Data singleton].annotations addObject:_addressPin];
[_worldView addAnnotation:_addressPin];
NSLog(#"The number of pins in the annotation array is: %u",[Data singleton].annotations.count);
}
}
}];
}
Here is my class that conforms to the MKAnnotation protcol:
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface MapPoint : NSObject <MKAnnotation, NSCoding>
{
}
- (id)initWithAddress:(NSString*)address
coordinate:(CLLocationCoordinate2D)coordinate
title:(NSString *)t
identifier:(NSNumber *)ident;
//This is a required property from MKAnnotation
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
//This is an optional property from MKAnnotataion
#property (nonatomic, copy) NSString *title;
#property (nonatomic, readonly, copy) NSString *subtitle;
#property (nonatomic) BOOL animatesDrop;
#property (nonatomic) BOOL canShowCallout;
#property (copy) NSString *address;
#property (copy) NSNumber *identifier;
#property (nonatomic, copy) NSString *imageKey;
#property (nonatomic, copy) UIImage *image;
#end
import "MapPoint.h"
#implementation MapPoint
#synthesize title, subtitle, animatesDrop, canShowCallout, imageKey, image;
#synthesize address = _address, coordinate = _coordinate, identifier = _indentifier;
-(id)initWithAddress:(NSString *)address
coordinate:(CLLocationCoordinate2D)coordinate
title:(NSString *)t
identifier:(NSNumber *)ident {
self = [super init];
if (self) {
_address = [address copy];
_coordinate = coordinate;
_indentifier = ident;
[self setTitle:t];
NSDate *theDate = [NSDate date];
subtitle = [NSDateFormatter localizedStringFromDate:theDate
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterShortStyle];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_address forKey:#"address"];
[aCoder encodeObject:title forKey:#"title"];
[aCoder encodeObject:_indentifier forKey:#"identifier"];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
[self setAddress:[aDecoder decodeObjectForKey:#"address"]];
}
return self;
}
#end
Just encode the two fields of the CLLocationCoordinate2D value.
[aCoder encodeDouble:_coordinate.latitude forKey:#"latitude"];
[aCoder encodeDouble:_coordinate.longitude forKey:#"longitude"];
NSValue is NSCoding compliant. You can box your CLLocationcoordinate2D variable in an NSValue object:
[coder encodeObject:[NSValue valueWithMKCoordinate:coordinate] forKey:#"coordinate"]
The CLLocationCoordinate2D's latitude and longitude are of type CLLocationDegrees which is, essentially, a fancy way of saying double.
This is how you can encode and decode them:
NSString *const kPinCoordinateLatitudeKey = #"kPinCoordinateLatitudeKey";
NSString *const kPinCoordinateLongitudeKey = #"kPinCoordinateLongitudeKey";
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeDouble:self.coordinate.latitude forKey:kPinCoordinateLatitudeKey];
[encoder encodeDouble:self.coordinate.longitude forKey:kPinCoordinateLongitudeKey];
}
- (id)initWithCoder:(NSCoder *)decoder
{
if((self = [super init])) {
CLLocationDegrees latitude = [decoder decodeDoubleForKey:kPinCoordinateLatitudeKey];
CLLocationDegrees longitude = [decoder decodeDoubleForKey:kPinCoordinateLongitudeKey];
_coordinate = CLLocationCoordinate2DMake(latitude, longitude);
}
return self;
}
I decided to encode use a CLLocation property handle this situation, which conforms to NSSecureCoding.
If you need to convert to or from a CLLocationCoordinate2D:
// Coordinate to Location
CLLocationCoordinate2D coord;
CLLocation *loc = [[CLLocation alloc] initWithLatitude:coord.latitude
longitude:coord.longitude];
// Location to Coordinate
CLLocationCoordinate2D coord = loc.coordinate;

App crashed when trying to change UITextView.text

My app crashed when i trying to change UITextView text.
Here is the code: (header file):
//
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController {
IBOutlet UIImageView *appImage;
IBOutlet UILabel *appName;
IBOutlet UILabel *appDeveloper;
IBOutlet UILabel *appVersion;
UIActivityIndicatorView *loading;
IBOutlet UITextView *appAbout;
NSString *selectedApp;
}
#property (nonatomic, retain) NSString *selectedApp;
#property (nonatomic, retain) IBOutlet UIImageView *appImage;
#property (nonatomic, retain) IBOutlet UILabel *appName;
#property (nonatomic, retain) IBOutlet UILabel *appDeveloper;
#property (nonatomic, retain) IBOutlet UILabel *appVersion;
#property (nonatomic, retain) UIActivityIndicatorView *loading;
#property (nonatomic, retain) UITextView *appAbout;
#end
implementation file:
- (void)loadData {
NSString *trimmedString = [selectedApp stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
self.navigationItem.title = #"Info";
NSLog(#"%#", trimmedString);
NSString *website = [NSString stringWithFormat:#"http://shaymargolisapps.x10.mx/send.php?mission=GetNameOfApps&aname=%#", trimmedString];
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:website]];
NSString *strResult = [[[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding]autorelease];
appName.text = strResult;
NSString *website1 = [NSString stringWithFormat:#"http://shaymargolisapps.x10.mx/send.php?mission=GetDeveloperOfApp&aname=%#", trimmedString];
NSData *dataURL1 = [NSData dataWithContentsOfURL:[NSURL URLWithString:website1]];
NSString *strResult1 = [[[NSString alloc] initWithData:dataURL1 encoding:NSUTF8StringEncoding]autorelease];
appDeveloper.text = strResult1;
NSString *website2 = [NSString stringWithFormat:#"http://shaymargolisapps.x10.mx/send.php?mission=GetVersionOfApp&aname=%#", trimmedString];
NSData *dataURL2 = [NSData dataWithContentsOfURL:[NSURL URLWithString:website2]];
NSString *strResult2 = [[[NSString alloc] initWithData:dataURL2 encoding:NSUTF8StringEncoding]autorelease];
appVersion.text = strResult2;
NSString *website3 = [NSString stringWithFormat:#"http://shaymargolisapps.x10.mx/send.php?mission=GetInfoOfApp&aname=%#", trimmedString];
NSData *dataURL3 = [NSData dataWithContentsOfURL:[NSURL URLWithString:website3]];
NSString *strResult3 = [[[NSString alloc] initWithData:dataURL3 encoding:NSUTF8StringEncoding]autorelease];
NSLog(#"%#", strResult3);
**appAbout.text = strResult3;**
NSString *website4 = [NSString stringWithFormat:#"http://shaymargolisapps.x10.mx/send.php?mission=GetImageOfApp&aname=%#", trimmedString];
NSData *dataURL4 = [NSData dataWithContentsOfURL:[NSURL URLWithString:website4]];
NSString *strResult4 = [[[NSString alloc] initWithData:dataURL4 encoding:NSUTF8StringEncoding]autorelease];
NSData* imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:strResult4]];
UIImage* image = [[UIImage alloc] initWithData:imageData];
[appImage setImage:image];
[image release];
[imageData release];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[loading stopAnimating];
[loading setHidden:YES];
[appName setHidden:NO];
[appDeveloper setHidden:NO];
[appVersion setHidden:NO];
[appImage setHidden:NO];
[appAbout setHidden:NO];
}
My app crashed on appAbout.text = strResult3; line. What am I doing wrong?
loadData is called with [self performSelectorInBackground:#selector(loadData) withObject:nil]; from viewDidLoad
(Xcode 4.4 DP2, iPhone Simulator 5.1, base SDK 4.3)
You must not change UI* objects from a background thread. That has to be done from the main thread.
You could use gcd to perform the changes on the main thread. Something like this:
/* ... */
NSString *strResult4 = [[[NSString alloc] initWithData:dataURL4 encoding:NSUTF8StringEncoding]autorelease];
NSData* imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:strResult4]];
UIImage* image = [[UIImage alloc] initWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
self.navigationItem.title = #"Info";
appName.text = strResult;
appDeveloper.text = strResult1;
appVersion.text = strResult2;
appAbout.text = strResult3;
[appImage setImage:image];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[loading stopAnimating];
[loading setHidden:YES];
[appName setHidden:NO];
[appDeveloper setHidden:NO];
[appVersion setHidden:NO];
[appImage setHidden:NO];
[appAbout setHidden:NO];
});
[image release];
[imageData release];