1. 程式人生 > >iOS定位和獲取當前天氣

iOS定位和獲取當前天氣

cat ide 獲取 data device targe user urn fig

  這裏是定義了一個類,用來當app 啟動的時候,在後臺獲取當前和位置,並根據位置獲取當前天氣信息,當點擊底部的 tabbar 顯示我的控制器的時候,在頁面上顯示當前位置和當前的天氣狀況,天氣接口用的 “心知天氣” 這個免費的接口,因為是免費的所以天氣信息很少,只能獲取到當前溫度、當前天氣狀況(晴還是雨)和指定的一組天氣圖片從他們網站下載下來直接拖進項目裏面,根據天氣狀態顯示指定的圖片。(項目全面接入的MVVM 和 RAC)

 CHMLocationManager.h

 1 #import "BaseViewModel.h"
 2 #import "Config.h"
 3 
 4 @class
CHMSeniverseResultModel; 5 6 @interface CHMLocationManager : BaseViewModel 7 8 @property (nonatomic, assign) double latitude; 9 @property (nonatomic, assign) double longitude; 10 @property (nonatomic, assign) BOOL currentLocationAbility; 11 @property (nonatomic, strong) RACSubject *refreshSubject;
12 @property (nonatomic, strong) RACCommand *weatherDataCommand; 13 @property (nonatomic, copy) NSString *currentCity; 14 @property (nonatomic, strong) CHMSeniverseResultModel *seniverseResultModel; 15 16 + (instancetype)sharedInstance; 17 - (void)startLocation; 18 19 @end

 CHMLocationManager.m

  1
#import "CHMLocationManager.h" 2 #import <CoreLocation/CoreLocation.h> 3 #import "MBProgressHUD+Custom.h" 4 #import "MLNetworkingManager.h" 5 #import "NSString+Custom.h" 6 #import "CHMSeniverseResultModel.h" 7 8 #define kSeniverseAPI @"bfdvxqnyj8k2sooo" 9 10 @interface CHMLocationManager () <CLLocationManagerDelegate> 11 12 @property (nonatomic, strong) CLLocationManager *locationManager; 13 @property (nonatomic, strong) CLGeocoder *geocoder; 14 15 @end 16 17 @implementation CHMLocationManager 18 19 + (instancetype)sharedInstance { 20 static CHMLocationManager *locationManager = nil; 21 static dispatch_once_t onceToken; 22 dispatch_once(&onceToken, ^{ 23 locationManager = [[CHMLocationManager alloc] init]; 24 }); 25 return locationManager; 26 } 27 28 - (void)xm_initialize { 29 self.locationManager = [[CLLocationManager alloc] init]; 30 self.geocoder = [[CLGeocoder alloc] init]; 31 self.locationManager.delegate = self; 32 self.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers; 33 self.refreshSubject = [RACSubject subject]; 34 } 35 36 - (void)startLocation { 37 if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { 38 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.f) { 39 [self.locationManager requestWhenInUseAuthorization]; 40 } 41 } 42 43 [self.locationManager startUpdatingLocation]; 44 45 if ([CLLocationManager locationServicesEnabled] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) { 46 self.currentCity = NSLocalizedString(@"打開定位", nil); 47 self.currentLocationAbility = NO; 48 } else { 49 self.currentLocationAbility = YES; 50 } 51 } 52 53 #pragma mark - CLLocationManagerDelegate 54 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations { 55 CLLocation *location = [locations lastObject]; 56 CLLocationCoordinate2D coordinate = location.coordinate; 57 58 self.latitude = coordinate.latitude; 59 self.longitude = coordinate.longitude; 60 DebugLog(@"當前位置信息 %lf %lf", self.latitude, self.longitude); 61 62 [manager stopUpdatingLocation]; 63 64 [self reverseCurrentGeocodeLocation:location]; 65 } 66 67 - (void)reverseCurrentGeocodeLocation:(CLLocation *)location { 68 @weakify(self); 69 [self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { 70 @strongify(self); 71 if (placemarks.count > 0) { 72 CLPlacemark *place = [placemarks firstObject]; 73 if (place != nil) { 74 if (place.locality && place.locality.length > 0) { 75 self.currentCity = place.locality; 76 } else { 77 //四大直轄市的城市信息無法通過locality獲得,只能通過獲取省份的方法來獲得(如果city為空,則可知為直轄市) 78 self.currentCity = place.administrativeArea; 79 } 80 81 [self.weatherDataCommand execute:@{@"location": [NSString stringWithFormat:@"%.2f:%.2f", self.latitude, self.longitude], @"language": [NSString currentLanguageForSeniverse]}]; 82 } else { 83 DebugLog(@"CLPlacemark place 是 nil"); 84 self.currentCity = NSLocalizedString(@"位置未知", nil); 85 } 86 } else if (error == nil && placemarks.count == 0) { 87 DebugLog(@"沒有定位結果返回"); 88 self.currentCity = NSLocalizedString(@"沒有定位信息", nil); 89 } else { 90 DebugLog(@"反地理編碼失敗 %@", error); 91 } 92 [self.refreshSubject sendNext:self.currentCity]; 93 }]; 94 } 95 96 - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { 97 [manager stopUpdatingLocation]; 98 99 switch (error.code) { 100 case kCLErrorDenied: 101 { 102 DebugLog(@"用戶拒絕了對位置或測距的訪問權限"); 103 self.currentCity = NSLocalizedString(@"打開定位", nil); 104 } 105 break; 106 default: 107 { 108 [MBProgressHUD showBriefPoint:NSLocalizedString(@"定位失敗", nil)]; 109 self.currentCity = NSLocalizedString(@"定位失敗", nil); 110 } 111 break; 112 } 113 } 114 115 #pragma mark - Setter Getter 116 - (CHMSeniverseResultModel *)seniverseResultModel { 117 if (!_seniverseResultModel) { 118 _seniverseResultModel = [[CHMSeniverseResultModel alloc] init]; 119 } 120 return _seniverseResultModel; 121 } 122 123 - (RACCommand *)weatherDataCommand { 124 if (!_weatherDataCommand) { 125 _weatherDataCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(NSDictionary *dic) { 126 127 DebugLog(@"請求當前的天氣情況 %@", dic); 128 129 return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { 130 131 MLURLSessionTask *task = [MLNetworkingManager requestWeatherWithAPI:kSeniverseAPI location:[dic objectForKey:@"location"] language:[dic objectForKey:@"language"] unit:@"c" success:^(CHMSeniverseResultModel *response) { 132 [CHMLocationManager sharedInstance].seniverseResultModel = response; 133 [subscriber sendNext:response]; 134 [subscriber sendCompleted]; 135 } fail:^(NSError *error) { 136 [subscriber sendError:error]; 137 }]; 138 139 return [RACDisposable disposableWithBlock:^{ 140 [task cancel]; 141 }]; 142 }]; 143 }]; 144 } 145 return _weatherDataCommand; 146 } 147 148 @end
 1 + (MLURLSessionTask *)requestWeatherWithAPI:(NSString *)API location:(NSString *)location language:(NSString *)language unit:(NSString *)unit success:(MLResponseSuccess)success fail:(MLResponseFail)fail {
 2     NSString *tempURLStr = [NSString stringWithFormat:@"https://api.seniverse.com/v3/weather/now.json?key=%@&location=%@&language=%@&unit=%@", API, location, language, unit];
 3     
 4     NSURLSessionTask *task = [MLNetworking getWithUrl:tempURLStr refreshCache:YES showMBProHUD:NO success:^(id response) {
 5         CHMSeniverseResultModel *seniverseResultModel = [CHMSeniverseResultModel mj_objectWithKeyValues:((NSArray *)[response objectForKey:@"results"]).firstObject];
 6         seniverseResultModel.seniverseNowModel = [CHMSeniverseNowModel mj_objectWithKeyValues:[((NSArray *)[response objectForKey:@"results"]).firstObject objectForKey:@"now"]];
 7         seniverseResultModel.seniverseLocationModel = [CHMSeniverseLocationModel mj_objectWithKeyValues:[((NSArray *)[response objectForKey:@"results"]).firstObject objectForKey:@"location"]];
 8         
 9         if (success) {
10             success(seniverseResultModel);
11         }
12         DebugLog(@"requestWeatherWithAPI %@", response);
13     } fail:^(NSError *error) {
14         if (fail) {
15             fail(error);
16         }
17         [MLNetworkingManager showRequestFailInfo:kFailErrorUserInfoDataStr];
18         DebugLog(@"requstWeatherWithAPI %@", error);
19     }];
20     
21     return task;
22 }

END

iOS定位和獲取當前天氣