2
0

WFCULocationViewController.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. //
  2. // LocationViewController.m
  3. // WFChat UIKit
  4. //
  5. // Created by WF Chat on 2017/10/28.
  6. // Copyright © 2017年 WildFireChat. All rights reserved.
  7. //
  8. #import "WFCULocationViewController.h"
  9. #import "UIView+Toast.h"
  10. #import "WFCULocationPoint.h"
  11. #import <AddressBookUI/AddressBookUI.h>
  12. #import <CoreLocation/CoreLocation.h>
  13. #import "UIView+Screenshot.h"
  14. #import "WFCUImage.h"
  15. @interface WFCULocationViewController () <CLLocationManagerDelegate, UITableViewDelegate, UITableViewDataSource>
  16. @property(nonatomic, strong) UIBarButtonItem *sendButton;
  17. @property(nonatomic, strong) CLLocationManager *locationManager;
  18. @property(nonatomic, strong) WFCULocationPoint *locationPoint;
  19. @property(nonatomic, strong) CLGeocoder * geoCoder;
  20. @property(nonatomic, strong) CALayer *annotationLayer;
  21. @property(nonatomic, assign) BOOL updateUserLocation;
  22. @property(nonatomic, strong) MKMapView *mapView;
  23. @property(nonatomic, strong) UITableView *locationTableView;
  24. @property(nonatomic, strong) NSMutableArray<CLPlacemark *> *marks;
  25. @property(nonatomic, weak) id<LocationViewControllerDelegate> delegate;
  26. @end
  27. @implementation WFCULocationViewController
  28. - (instancetype)initWithDelegate:(id<LocationViewControllerDelegate>)delegate {
  29. self = [super init];
  30. if (self) {
  31. _locationManager = [[CLLocationManager alloc] init];
  32. _geoCoder = [[CLGeocoder alloc] init];
  33. _delegate = delegate;
  34. }
  35. return self;
  36. }
  37. - (instancetype)initWithLocationPoint:(WFCULocationPoint *)locationPoint{
  38. self = [self initWithNibName:nil bundle:nil];
  39. if (self) {
  40. _locationPoint = locationPoint;
  41. _geoCoder = [[CLGeocoder alloc] init];
  42. }
  43. return self;
  44. }
  45. - (void)viewDidLoad {
  46. [super viewDidLoad];
  47. self.navigationItem.title = WFCString(@"Location");
  48. self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:WFCString(@"Cancel") style:UIBarButtonItemStylePlain target:self action:@selector(dismiss:)];
  49. if (_locationManager) {
  50. CGRect frame = self.view.bounds;
  51. frame.size.height /= 2;
  52. self.mapView = [[MKMapView alloc] initWithFrame:frame];
  53. frame.origin.y += frame.size.height;
  54. self.locationTableView = [[UITableView alloc] initWithFrame:frame style:UITableViewStylePlain];
  55. [self.view addSubview:self.locationTableView];
  56. self.locationTableView.delegate = self;
  57. self.locationTableView.dataSource = self;
  58. if (@available(iOS 15, *)) {
  59. self.locationTableView.sectionHeaderTopPadding = 0;
  60. }
  61. self.mapView.showsUserLocation = YES;
  62. self.annotationLayer = [CALayer layer];
  63. UIImage *image = [WFCUImage imageNamed:@"PinGreen"];
  64. self.annotationLayer.contents = (id)image.CGImage;
  65. self.annotationLayer.frame = CGRectMake(0, 0, 35, 35);
  66. self.annotationLayer.anchorPoint = CGPointMake(0.25f, 0.f);
  67. self.annotationLayer.position = CGPointMake(CGRectGetMidX(self.mapView.bounds), CGRectGetMidY(self.mapView.bounds));
  68. [self setUpRightNavButton];
  69. self.locationPoint = [[WFCULocationPoint alloc] init];
  70. self.locationManager = [CLLocationManager new];
  71. [self.locationManager requestWhenInUseAuthorization];
  72. self.locationManager.delegate = self;
  73. if ([CLLocationManager locationServicesEnabled]) {
  74. [_locationManager requestLocation];
  75. CLAuthorizationStatus status = CLLocationManager.authorizationStatus;
  76. if (status == kCLAuthorizationStatusRestricted || status == kCLAuthorizationStatusDenied) {
  77. [self.view makeToast:@"请在设置-隐私里允许程序使用地理位置服务"
  78. duration:2
  79. position:CSToastPositionCenter];
  80. }else{
  81. self.mapView.showsUserLocation = YES;
  82. }
  83. }else{
  84. [self.view makeToast:@"请打开地理位置服务"
  85. duration:2
  86. position:CSToastPositionCenter];
  87. }
  88. } else /*if (self.locationPoint)*/ {
  89. self.mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
  90. MKCoordinateRegion theRegion;
  91. theRegion.center = self.locationPoint.coordinate;
  92. theRegion.span.longitudeDelta = 0.01f;
  93. theRegion.span.latitudeDelta = 0.01f;
  94. [self.mapView addAnnotation:self.locationPoint];
  95. [self.mapView setRegion:theRegion animated:YES];
  96. }
  97. self.mapView.delegate = self;
  98. [self.view addSubview:self.mapView];
  99. }
  100. - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
  101. }
  102. - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations {
  103. if (locations.count) {
  104. [self reverseGeoLocation:locations[0].coordinate];
  105. }
  106. }
  107. - (void)setUpRightNavButton{
  108. UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"选定" style:UIBarButtonItemStyleDone target:self action:@selector(onSend:)];
  109. self.navigationItem.rightBarButtonItem = item;
  110. self.sendButton = item;
  111. self.sendButton.enabled = NO;
  112. }
  113. - (void)onSend:(id)sender{
  114. if ([self.delegate respondsToSelector:@selector(onSendLocation:)]) {
  115. UIView * view = [self.mapView viewForAnnotation:self.mapView.userLocation];
  116. view.hidden = YES;
  117. CGRect frame = self.mapView.frame;
  118. UIImage *thumbnail = [self.mapView screenshotWithRect:CGRectMake(0, (frame.size.height - frame.size.width * 2 / 3.f)/2, frame.size.width, frame.size.width * 2 / 3.f)];
  119. self.locationPoint.thumbnail = thumbnail;
  120. [self.delegate onSendLocation:self.locationPoint];
  121. }
  122. [self.navigationController dismissViewControllerAnimated:YES completion:nil];
  123. }
  124. - (void)didReceiveMemoryWarning {
  125. [super didReceiveMemoryWarning];
  126. }
  127. #pragma mark - MKMapViewDelegate
  128. - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
  129. if (!_updateUserLocation) {
  130. return;
  131. }
  132. CLLocationCoordinate2D centerCoordinate = mapView.region.center;
  133. [self reverseGeoLocation:centerCoordinate];
  134. [self.annotationLayer removeFromSuperlayer];
  135. }
  136. - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
  137. if (!_updateUserLocation) {
  138. return;
  139. }
  140. [_mapView removeAnnotations:_mapView.annotations];
  141. [self.mapView.layer addSublayer:self.annotationLayer];
  142. }
  143. - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
  144. if (annotation == self.mapView.userLocation) {
  145. return nil;
  146. }
  147. if (_locationManager) {
  148. static NSString *reusePin = @"reusePin";
  149. MKPinAnnotationView * pin = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:reusePin];
  150. if (!pin) {
  151. pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reusePin];
  152. }
  153. pin.draggable = YES;
  154. pin.canShowCallout = YES;
  155. return pin;
  156. }
  157. return nil;
  158. }
  159. - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
  160. _updateUserLocation = YES;
  161. MKCoordinateRegion theRegion;
  162. theRegion.center = userLocation.coordinate;
  163. theRegion.span.longitudeDelta = 0.01f;
  164. theRegion.span.latitudeDelta = 0.01f;
  165. [_mapView setRegion:theRegion animated:NO];
  166. }
  167. - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views{
  168. [_mapView selectAnnotation:self.locationPoint animated:YES];
  169. }
  170. - (void)reverseGeoLocation:(CLLocationCoordinate2D)locationCoordinate2D{
  171. if (self.geoCoder.isGeocoding) {
  172. [self.geoCoder cancelGeocode];
  173. }
  174. CLLocation *location = [[CLLocation alloc]initWithLatitude:locationCoordinate2D.latitude
  175. longitude:locationCoordinate2D.longitude];
  176. __weak typeof(self) ws = self;
  177. self.sendButton.enabled = NO;
  178. [self.geoCoder reverseGeocodeLocation:location
  179. completionHandler:^(NSArray *placemarks, NSError *error) {
  180. if (!error) {
  181. CLPlacemark *mark = [placemarks firstObject];
  182. ws.marks = [placemarks mutableCopy];
  183. NSArray *lines = mark.addressDictionary[@"FormattedAddressLines"];
  184. NSString *title = [lines componentsJoinedByString:@"\n"];
  185. WFCULocationPoint *ponit = [[WFCULocationPoint alloc] initWithCoordinate:locationCoordinate2D andTitle:nil];
  186. [ws.mapView addAnnotation:ponit];
  187. ws.locationPoint = [[WFCULocationPoint alloc] initWithCoordinate:locationCoordinate2D andTitle:title];;
  188. ws.sendButton.enabled = YES;
  189. ws.title = title;
  190. [ws.locationTableView reloadData];
  191. } else {
  192. ws.locationPoint = nil;
  193. ws.sendButton.enabled = NO;
  194. ws.title = WFCString(@"Location");
  195. }
  196. }];
  197. }
  198. - (void)dismiss:(id)sender {
  199. if (self.navigationController.presentingViewController) {
  200. [self.navigationController dismissViewControllerAnimated:YES completion:nil];
  201. }else{
  202. [self.navigationController popViewControllerAnimated:YES];
  203. }
  204. }
  205. #pragma mark - UITableViewDataSource
  206. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  207. return self.marks.count;
  208. }
  209. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  210. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
  211. if (!cell) {
  212. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
  213. }
  214. NSArray *lines = self.marks[indexPath.row].addressDictionary[@"FormattedAddressLines"];
  215. NSString *title = [lines componentsJoinedByString:@"\n"];
  216. cell.textLabel.text = title;
  217. if (cell.selected) {
  218. cell.imageView.image = [WFCUImage imageNamed:@"multi_selected"];
  219. } else {
  220. cell.imageView.image = nil;
  221. }
  222. return cell;
  223. }
  224. -(void)dealloc {
  225. [self.locationManager stopUpdatingLocation];
  226. [self.geoCoder cancelGeocode];
  227. }
  228. @end