Bladeren bron

附近的人

桂欢 1 jaar geleden
bovenliggende
commit
a28fb19fda

+ 28 - 0
SLAiELTS/SLAiELTS.xcodeproj/project.pbxproj

@@ -41,6 +41,8 @@
 		3D1B9D0829C1B7A90008D01A /* SLImagePickerAndUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B9D0729C1B7A90008D01A /* SLImagePickerAndUpload.m */; };
 		3D1B9D0C29C2A1360008D01A /* SLPlaceholderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B9D0A29C2A1360008D01A /* SLPlaceholderCell.m */; };
 		3D1B9D0D29C2A1360008D01A /* SLPlaceholderCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3D1B9D0B29C2A1360008D01A /* SLPlaceholderCell.xib */; };
+		3D1F17AE2A0DE55D00F030AD /* SLLocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D1F17AD2A0DE55D00F030AD /* SLLocationManager.m */; };
+		3D1F17B22A0DE60100F030AD /* JZLocationConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D1F17B02A0DE60100F030AD /* JZLocationConverter.m */; };
 		3D24986529AC7224003C3AFA /* SLBaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D24986429AC7224003C3AFA /* SLBaseViewController.m */; };
 		3D24986C29AC72E2003C3AFA /* SLLoginVCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D24986A29AC72E2003C3AFA /* SLLoginVCViewController.m */; };
 		3D24986D29AC72E2003C3AFA /* SLLoginVCViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3D24986B29AC72E2003C3AFA /* SLLoginVCViewController.xib */; };
@@ -327,6 +329,10 @@
 		3D1B9D0929C2A1360008D01A /* SLPlaceholderCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLPlaceholderCell.h; sourceTree = "<group>"; };
 		3D1B9D0A29C2A1360008D01A /* SLPlaceholderCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLPlaceholderCell.m; sourceTree = "<group>"; };
 		3D1B9D0B29C2A1360008D01A /* SLPlaceholderCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SLPlaceholderCell.xib; sourceTree = "<group>"; };
+		3D1F17AC2A0DE55D00F030AD /* SLLocationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLLocationManager.h; sourceTree = "<group>"; };
+		3D1F17AD2A0DE55D00F030AD /* SLLocationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLLocationManager.m; sourceTree = "<group>"; };
+		3D1F17B02A0DE60100F030AD /* JZLocationConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JZLocationConverter.m; sourceTree = "<group>"; };
+		3D1F17B12A0DE60100F030AD /* JZLocationConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JZLocationConverter.h; sourceTree = "<group>"; };
 		3D24986329AC7224003C3AFA /* SLBaseViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLBaseViewController.h; sourceTree = "<group>"; };
 		3D24986429AC7224003C3AFA /* SLBaseViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLBaseViewController.m; sourceTree = "<group>"; };
 		3D24986929AC72E2003C3AFA /* SLLoginVCViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLLoginVCViewController.h; sourceTree = "<group>"; };
@@ -789,6 +795,24 @@
 			path = SLAiELTS/Vendor/modeling/UnityFramework;
 			sourceTree = "<group>";
 		};
+		3D1F17AB2A0DE55D00F030AD /* GPSLocation */ = {
+			isa = PBXGroup;
+			children = (
+				3D1F17AC2A0DE55D00F030AD /* SLLocationManager.h */,
+				3D1F17AD2A0DE55D00F030AD /* SLLocationManager.m */,
+			);
+			path = GPSLocation;
+			sourceTree = "<group>";
+		};
+		3D1F17AF2A0DE60100F030AD /* JZLocationConverter */ = {
+			isa = PBXGroup;
+			children = (
+				3D1F17B02A0DE60100F030AD /* JZLocationConverter.m */,
+				3D1F17B12A0DE60100F030AD /* JZLocationConverter.h */,
+			);
+			path = JZLocationConverter;
+			sourceTree = "<group>";
+		};
 		3D24985F29AC6A7D003C3AFA /* ViewControllers */ = {
 			isa = PBXGroup;
 			children = (
@@ -1024,6 +1048,8 @@
 		3D2510AF29AF1943000AE530 /* Tool */ = {
 			isa = PBXGroup;
 			children = (
+				3D1F17AF2A0DE60100F030AD /* JZLocationConverter */,
+				3D1F17AB2A0DE55D00F030AD /* GPSLocation */,
 				3D19CBEF29E7ABFD0041A6B8 /* CYLTableViewPlaceHolder */,
 				3D2D8BF129DE5AE4009392DA /* SCIndexView */,
 				3D2D8C0429DE7404009392DA /* TextFieldCategory */,
@@ -2027,6 +2053,7 @@
 				3D25108829ADD46C000AE530 /* SLRoleLabelView.m in Sources */,
 				3D2510D129AF3DC4000AE530 /* SLLoginInfo.m in Sources */,
 				3D8C9F8229AC57F200678283 /* ViewController.m in Sources */,
+				3D1F17AE2A0DE55D00F030AD /* SLLocationManager.m in Sources */,
 				3D24987429AC7909003C3AFA /* UIViewController+Extension.m in Sources */,
 				3D19CC0229E7E9340041A6B8 /* SLMomentDetailTableVc.m in Sources */,
 				3D25105B29AC9475000AE530 /* SLForgetPWViewController.m in Sources */,
@@ -2041,6 +2068,7 @@
 				3D19CBF829E7ABFD0041A6B8 /* UITableView+CYLTableViewPlaceHolder.m in Sources */,
 				3DA5AF5C29B8843C009E4925 /* SLBaseTabBarController.m in Sources */,
 				3D2DC3E029B0991E0041A729 /* YMIMMessageCollectionView.m in Sources */,
+				3D1F17B22A0DE60100F030AD /* JZLocationConverter.m in Sources */,
 				3DB97D6D29D6ABC100B12754 /* UIView+SDExtension.m in Sources */,
 				3DF3DAFA29BB187D00CAD3AB /* SLHomeTopCollectionViewCell.m in Sources */,
 				3D8515D729CD92A400418BAB /* JXCategoryTitleBackgroundCellModel.m in Sources */,

+ 22 - 0
SLAiELTS/SLAiELTS/Assets.xcassets/other/icon_sex_woman_r.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "icon_sex_woman_r@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "icon_sex_woman_r@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
SLAiELTS/SLAiELTS/Assets.xcassets/other/icon_sex_woman_r.imageset/icon_sex_woman_r@2x.png


BIN
SLAiELTS/SLAiELTS/Assets.xcassets/other/icon_sex_woman_r.imageset/icon_sex_woman_r@3x.png


+ 8 - 0
SLAiELTS/SLAiELTS/Info.plist

@@ -2,6 +2,14 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
+	<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
+	<string>定位服务用于发现附近的用户</string>
+	<key>NSLocationAlwaysUsageDescription</key>
+	<string>定位服务用于发现附近的用户</string>
+	<key>NSLocationUsageDescription</key>
+	<string>定位服务用于发现附近的用户</string>
+	<key>NSLocationWhenInUseUsageDescription</key>
+	<string>定位服务用于发现附近的用户</string>
 	<key>NSAppTransportSecurity</key>
 	<dict>
 		<key>NSAllowsArbitraryLoads</key>

+ 39 - 0
SLAiELTS/SLAiELTS/Tool/GPSLocation/SLLocationManager.h

@@ -0,0 +1,39 @@
+//
+//  YMLocationManager.h
+//  PCDBank
+//
+//  Created by raohb on 2020/7/30.
+//  Copyright © 2020 YMBank. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+typedef void(^YMCurrentLocationBlock)(CLLocation *__nullable currentLocation);
+
+@interface SLLocationManager : NSObject
+//用户当前位置
+@property (nonatomic, copy) CLLocation *__nullable currentLocation;
+@property (nonatomic, copy) NSString *city;      // 当前城市
+@property (nonatomic, copy) NSString *province;  // 当前省
+@property (nonatomic, copy) NSString *state;     // 当前国家
+
+/// 单例
++ (instancetype)shareInstance;
+
+//获取位置
+- (void)getLocationComplete:(YMCurrentLocationBlock)completeBlock;
+
+/// 不请求权限获取位置,获取不到返回空
+/// @param locationBlock 如果对象不是单例,block值为实际返回的
+- (CLLocation *)getCurrentLocation:(YMCurrentLocationBlock)locationBlock;
+/// 清空当前定位
++ (void)clearLocation;
+/// 清空当前地址
++ (void)clearAddress;
+/// 清空全部
++ (void)clearAll;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 269 - 0
SLAiELTS/SLAiELTS/Tool/GPSLocation/SLLocationManager.m

@@ -0,0 +1,269 @@
+
+#import "SLLocationManager.h"
+#import "JZLocationConverter.h"
+
+#define authStatus(status) @"#status"
+
+@interface SLLocationManager () <CLLocationManagerDelegate>
+
+@property (nonatomic, strong) NSMutableArray *completeBlocks;
+@property (nonatomic, strong) CLLocationManager *locationManager;
+@property (nonatomic, copy) YMCurrentLocationBlock locationBlock;
+//持续定位
+@property (nonatomic, strong) CLLocationManager *holdLocationManager;
+@property (nonatomic, assign) BOOL holdLocating;// 持续定位:正在定位
+
+@end
+
+@implementation SLLocationManager
+
++ (instancetype)shareInstance
+{
+    static SLLocationManager *_instance = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        _instance = [[[self class] alloc] init];
+    });
+    return _instance;
+}
+
+- (void)dealloc
+{
+    NSLog(@"释放 %s", __func__);
+}
+
+- (NSMutableArray *)completeBlocks
+{
+    if (!_completeBlocks) {
+        _completeBlocks = [NSMutableArray array];
+    }
+    return _completeBlocks;
+}
+
+- (void)setCurrentLocation:(CLLocation *)currentLocation
+{
+    _currentLocation = currentLocation;
+}
+
+- (void)getLocationComplete:(YMCurrentLocationBlock)completeBlock
+                
+{
+//    if (self.currentLocation) {
+//        [self ym_reverseGeocodeLocation:self.currentLocation completionHandler:completeBlock];
+//        return;
+//    }
+    [self.completeBlocks addObject:completeBlock];
+    CLAuthorizationStatus authStatus = [CLLocationManager  authorizationStatus];
+    if(authStatus == kCLAuthorizationStatusNotDetermined) {
+        [self.locationManager requestWhenInUseAuthorization];
+    } else {
+        [self.locationManager startUpdatingLocation];
+    }
+}
+
++ (BOOL)locationEnabled
+{
+    if (![CLLocationManager locationServicesEnabled]) {
+        return NO;
+    }
+    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
+    if (kCLAuthorizationStatusAuthorizedWhenInUse == status ||
+        kCLAuthorizationStatusAuthorizedAlways == status) {
+        return YES;
+    }
+    return NO;
+}
+
+- (CLLocation *)getCurrentLocation:(YMCurrentLocationBlock)locationBlock
+{
+    if (NSThread.currentThread.isMainThread) {
+        [self getCurrentLocationInMainThread:locationBlock];
+    } else {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [self getCurrentLocationInMainThread:locationBlock];
+        });
+    }
+    return self.currentLocation;
+}
+
+- (void)getCurrentLocationInMainThread:(YMCurrentLocationBlock)locationBlock
+{
+    if (!self.currentLocation &&
+        [SLLocationManager locationEnabled]) {
+        if (self.holdLocating) {
+            return;
+        }
+        self.holdLocating = YES;
+        self.locationBlock = locationBlock;
+        [self.holdLocationManager startUpdatingLocation];
+    } else {
+        if (locationBlock) {
+            locationBlock(self.currentLocation);
+        }
+    }
+}
+
+/// 清空当前定位
++ (void)clearLocation
+{
+    [[SLLocationManager shareInstance] setCurrentLocation:nil];
+}
+/// 清空当前地址
++ (void)clearAddress
+{
+    [[SLLocationManager shareInstance] setState:@""];
+    [[SLLocationManager shareInstance] setProvince:@""];
+    [[SLLocationManager shareInstance] setCity:@""];
+}
+/// 清空全部
++ (void)clearAll
+{
+    [self clearLocation];
+    [self clearAddress];
+}
+
+#pragma mark - CLLocationManagerDelegate
+// 授权状态变更
+- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
+{
+    if (manager == _locationManager) {
+        if (CLLocationManager.authorizationStatus != kCLAuthorizationStatusNotDetermined) {
+            [self.locationManager startUpdatingLocation];
+        }
+    }
+}
+// 更新地位回调
+- (void)locationManager:(CLLocationManager *)manager
+     didUpdateLocations:(NSArray<CLLocation *> *)locations
+{
+    if (manager == _locationManager) {
+        if (locations.count == 0) {
+            for (YMCurrentLocationBlock completeBlock in self.completeBlocks) {
+                completeBlock(nil);
+            }
+            [self.completeBlocks removeAllObjects];
+            return;
+        }
+        [self.locationManager stopUpdatingLocation];
+        
+        CLLocation *newLocation = [locations lastObject];
+        if (newLocation) {
+            [self ym_reverseGeocodeLocation:newLocation completionHandler:^(void) {
+                for (YMCurrentLocationBlock completeBlock in self.completeBlocks) {
+                    completeBlock(newLocation);
+                }
+                [self.completeBlocks removeAllObjects];
+            }];
+        }
+    } else if (manager == _holdLocationManager) {
+        self.holdLocating = NO;
+        if (locations.count > 0) {
+            [self.holdLocationManager stopUpdatingLocation];
+            CLLocation *newLocation = [locations lastObject];
+            if (self.locationBlock) {
+                self.locationBlock(newLocation);
+            }
+        }
+    }
+    
+}
+// 定位失败回调
+- (void)locationManager:(CLLocationManager *)manager
+       didFailWithError:(NSError *)error
+{
+    if (manager == _locationManager) {
+        [self.locationManager stopUpdatingLocation];
+        if (CLLocationManager.authorizationStatus != kCLAuthorizationStatusNotDetermined) {
+            for (YMCurrentLocationBlock completeBlock in self.completeBlocks) {
+                completeBlock(manager.location);
+            }
+            [self.completeBlocks removeAllObjects];
+        }
+    } else if (manager == _holdLocationManager) {
+        [self.holdLocationManager stopUpdatingLocation];
+        self.holdLocating = NO;
+        if (self.locationBlock) {
+            self.locationBlock(nil);
+        }
+    }
+}
+
+// 反向地址编码
+- (void)ym_reverseGeocodeLocation:(CLLocation *)location
+                completionHandler:(void(^)(void))completionHandler
+{
+    if (self.state.length && self.city.length) {
+        if (completionHandler) {
+            completionHandler();
+        }
+        return;
+    }
+    if (@available(iOS 10.0, *)) {
+        NSString *countryCode = [NSLocale autoupdatingCurrentLocale].countryCode;
+        if ([countryCode isEqualToString:@"CN"] ||
+            [countryCode isEqualToString:@"HK"] ||
+            [countryCode isEqualToString:@"MO"] ||
+            [countryCode isEqualToString:@"TW"]) {
+            CLLocationCoordinate2D cor = [JZLocationConverter wgs84ToGcj02:location.coordinate];
+            location = [[CLLocation alloc] initWithLatitude:cor.latitude longitude:cor.longitude];
+            //YMLLog(@"转换后lat:%f", location.coordinate.latitude);
+            //YMLLog(@"转换后long:%f", location.coordinate.longitude);
+        }
+    } else {
+        NSString *localeIdentifier = [NSLocale autoupdatingCurrentLocale].localeIdentifier;
+        if ([localeIdentifier.lowercaseString hasSuffix:@"cn"] ||
+            [localeIdentifier.lowercaseString hasSuffix:@"hk"] ||
+            [localeIdentifier.lowercaseString hasSuffix:@"mo"] ||
+            [localeIdentifier.lowercaseString hasSuffix:@"tw"]) {
+            CLLocationCoordinate2D cor = [JZLocationConverter wgs84ToGcj02:location.coordinate];
+            location = [[CLLocation alloc] initWithLatitude:cor.latitude longitude:cor.longitude];
+            //YMLLog(@"转换后lat:%f", location.coordinate.latitude);
+            //YMLLog(@"转换后long:%f", location.coordinate.longitude);
+        }
+    }
+    
+    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
+    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
+        //YMLLog(@"placemarks:%@(%@)", placemarks, error);
+        if (placemarks.count > 0) {
+            CLPlacemark *first = placemarks[0];
+            
+            NSString *country = first.country;
+            NSString *province = first.administrativeArea;
+            NSString *city = first.locality;
+            
+            self.state = country ? : @"";
+            self.province = province ? : @"";
+            self.city = city ? : @"";
+        }
+        if (completionHandler) {
+            completionHandler();
+        }
+    }];
+}
+
+
+#pragma mark - instance
+- (CLLocationManager *)locationManager
+{
+    if (!_locationManager) {
+        _locationManager = [[CLLocationManager alloc] init];
+        _locationManager.delegate = self;
+        _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
+        _locationManager.distanceFilter = 5.0;
+    }
+    return _locationManager;
+}
+
+- (CLLocationManager *)holdLocationManager
+{
+    if (!_holdLocationManager) {
+        _holdLocationManager = [[CLLocationManager alloc] init];
+        _holdLocationManager.delegate = self;
+        _holdLocationManager.desiredAccuracy = kCLLocationAccuracyBest;
+        _holdLocationManager.distanceFilter = 5.0;
+    }
+    return _holdLocationManager;
+}
+
+@end

+ 79 - 0
SLAiELTS/SLAiELTS/Tool/JZLocationConverter/JZLocationConverter.h

@@ -0,0 +1,79 @@
+//
+//  JZLocationConverter.h
+//  JZCLLocationMangerDome
+//
+//  Created by jack zhou on 13-8-22.
+//  Copyright (c) 2013年 JZ. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <CoreLocation/CoreLocation.h>
+@interface JZLocationConverter : NSObject
+
+/**
+ *	@brief	世界标准地理坐标(WGS-84) 转换成 中国国测局地理坐标(GCJ-02)<火星坐标>
+ *
+ *  ####只在中国大陆的范围的坐标有效,以外直接返回世界标准坐标
+ *
+ *	@param 	location 	世界标准地理坐标(WGS-84)
+ *
+ *	@return	中国国测局地理坐标(GCJ-02)<火星坐标>
+ */
++ (CLLocationCoordinate2D)wgs84ToGcj02:(CLLocationCoordinate2D)location;
+
+
+/**
+ *	@brief	中国国测局地理坐标(GCJ-02) 转换成 世界标准地理坐标(WGS-84)
+ *
+ *  ####此接口有1-2米左右的误差,需要精确定位情景慎用
+ *
+ *	@param 	location 	中国国测局地理坐标(GCJ-02)
+ *
+ *	@return	世界标准地理坐标(WGS-84)
+ */
++ (CLLocationCoordinate2D)gcj02ToWgs84:(CLLocationCoordinate2D)location;
+
+
+/**
+ *	@brief	世界标准地理坐标(WGS-84) 转换成 百度地理坐标(BD-09)
+ *
+ *	@param 	location 	世界标准地理坐标(WGS-84)
+ *
+ *	@return	百度地理坐标(BD-09)
+ */
++ (CLLocationCoordinate2D)wgs84ToBd09:(CLLocationCoordinate2D)location;
+
+
+/**
+ *	@brief	中国国测局地理坐标(GCJ-02)<火星坐标> 转换成 百度地理坐标(BD-09)
+ *
+ *	@param 	location 	中国国测局地理坐标(GCJ-02)<火星坐标>
+ *
+ *	@return	百度地理坐标(BD-09)
+ */
++ (CLLocationCoordinate2D)gcj02ToBd09:(CLLocationCoordinate2D)location;
+
+
+/**
+ *	@brief	百度地理坐标(BD-09) 转换成 中国国测局地理坐标(GCJ-02)<火星坐标>
+ *
+ *	@param 	location 	百度地理坐标(BD-09)
+ *
+ *	@return	中国国测局地理坐标(GCJ-02)<火星坐标>
+ */
++ (CLLocationCoordinate2D)bd09ToGcj02:(CLLocationCoordinate2D)location;
+
+
+/**
+ *	@brief	百度地理坐标(BD-09) 转换成 世界标准地理坐标(WGS-84)
+ *
+ *  ####此接口有1-2米左右的误差,需要精确定位情景慎用
+ *
+ *	@param 	location 	百度地理坐标(BD-09)
+ *
+ *	@return	世界标准地理坐标(WGS-84)
+ */
++ (CLLocationCoordinate2D)bd09ToWgs84:(CLLocationCoordinate2D)location;
+
+
+@end

+ 155 - 0
SLAiELTS/SLAiELTS/Tool/JZLocationConverter/JZLocationConverter.m

@@ -0,0 +1,155 @@
+//
+//  JZLocationConverter.m
+//  JZCLLocationMangerDome
+//
+//  Created by jack zhou on 13-8-22.
+//  Copyright (c) 2013年 JZ. All rights reserved.
+//
+
+#import "JZLocationConverter.h"
+#import <CoreLocation/CoreLocation.h>
+#define LAT_OFFSET_0(x,y) -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(fabs(x))
+#define LAT_OFFSET_1 (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0
+#define LAT_OFFSET_2 (20.0 * sin(y * M_PI) + 40.0 * sin(y / 3.0 * M_PI)) * 2.0 / 3.0
+#define LAT_OFFSET_3 (160.0 * sin(y / 12.0 * M_PI) + 320 * sin(y * M_PI / 30.0)) * 2.0 / 3.0
+
+#define LON_OFFSET_0(x,y) 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(x))
+#define LON_OFFSET_1 (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0
+#define LON_OFFSET_2 (20.0 * sin(x * M_PI) + 40.0 * sin(x / 3.0 * M_PI)) * 2.0 / 3.0
+#define LON_OFFSET_3 (150.0 * sin(x / 12.0 * M_PI) + 300.0 * sin(x / 30.0 * M_PI)) * 2.0 / 3.0
+
+#define RANGE_LON_MAX 137.8347
+#define RANGE_LON_MIN 72.004
+#define RANGE_LAT_MAX 55.8271
+#define RANGE_LAT_MIN 0.8293
+// jzA = 6378245.0, 1/f = 298.3
+// b = a * (1 - f)
+// ee = (a^2 - b^2) / a^2;
+#define jzA 6378245.0
+#define jzEE 0.00669342162296594323
+
+
+
+@implementation JZLocationConverter
+
++ (double)transformLat:(double)x bdLon:(double)y
+{
+    double ret = LAT_OFFSET_0(x, y);
+    ret += LAT_OFFSET_1;
+    ret += LAT_OFFSET_2;
+    ret += LAT_OFFSET_3;
+    return ret;
+}
+
++ (double)transformLon:(double)x bdLon:(double)y
+{
+    double ret = LON_OFFSET_0(x, y);
+    ret += LON_OFFSET_1;
+    ret += LON_OFFSET_2;
+    ret += LON_OFFSET_3;
+    return ret;
+}
+
++ (BOOL)outOfChina:(double)lat bdLon:(double)lon
+{
+    if (lon < RANGE_LON_MIN || lon > RANGE_LON_MAX)
+        return true;
+    if (lat < RANGE_LAT_MIN || lat > RANGE_LAT_MAX)
+        return true;
+    return false;
+}
+
++ (CLLocationCoordinate2D)gcj02Encrypt:(double)ggLat bdLon:(double)ggLon
+{
+    CLLocationCoordinate2D resPoint;
+    double mgLat;
+    double mgLon;
+    if ([self outOfChina:ggLat bdLon:ggLon]) {
+        resPoint.latitude = ggLat;
+        resPoint.longitude = ggLon;
+        return resPoint;
+    }
+    double dLat = [self transformLat:(ggLon - 105.0)bdLon:(ggLat - 35.0)];
+    double dLon = [self transformLon:(ggLon - 105.0) bdLon:(ggLat - 35.0)];
+    double radLat = ggLat / 180.0 * M_PI;
+    double magic = sin(radLat);
+    magic = 1 - jzEE * magic * magic;
+    double sqrtMagic = sqrt(magic);
+    dLat = (dLat * 180.0) / ((jzA * (1 - jzEE)) / (magic * sqrtMagic) * M_PI);
+    dLon = (dLon * 180.0) / (jzA / sqrtMagic * cos(radLat) * M_PI);
+    mgLat = ggLat + dLat;
+    mgLon = ggLon + dLon;
+    
+    resPoint.latitude = mgLat;
+    resPoint.longitude = mgLon;
+    return resPoint;
+}
+
++ (CLLocationCoordinate2D)gcj02Decrypt:(double)gjLat gjLon:(double)gjLon {
+    CLLocationCoordinate2D  gPt = [self gcj02Encrypt:gjLat bdLon:gjLon];
+    double dLon = gPt.longitude - gjLon;
+    double dLat = gPt.latitude - gjLat;
+    CLLocationCoordinate2D pt;
+    pt.latitude = gjLat - dLat;
+    pt.longitude = gjLon - dLon;
+    return pt;
+}
+
++ (CLLocationCoordinate2D)bd09Decrypt:(double)bdLat bdLon:(double)bdLon
+{
+    CLLocationCoordinate2D gcjPt;
+    double x = bdLon - 0.0065, y = bdLat - 0.006;
+    double z = sqrt(x * x + y * y) - 0.00002 * sin(y * M_PI);
+    double theta = atan2(y, x) - 0.000003 * cos(x * M_PI);
+    gcjPt.longitude = z * cos(theta);
+    gcjPt.latitude = z * sin(theta);
+    return gcjPt;
+}
+
++(CLLocationCoordinate2D)bd09Encrypt:(double)ggLat bdLon:(double)ggLon
+{
+    CLLocationCoordinate2D bdPt;
+    double x = ggLon, y = ggLat;
+    double z = sqrt(x * x + y * y) + 0.00002 * sin(y * M_PI);
+    double theta = atan2(y, x) + 0.000003 * cos(x * M_PI);
+    bdPt.longitude = z * cos(theta) + 0.0065;
+    bdPt.latitude = z * sin(theta) + 0.006;
+    return bdPt;
+}
+
+
++ (CLLocationCoordinate2D)wgs84ToGcj02:(CLLocationCoordinate2D)location
+{
+    return [self gcj02Encrypt:location.latitude bdLon:location.longitude];
+}
+
++ (CLLocationCoordinate2D)gcj02ToWgs84:(CLLocationCoordinate2D)location
+{
+    return [self gcj02Decrypt:location.latitude gjLon:location.longitude];
+}
+
+
++ (CLLocationCoordinate2D)wgs84ToBd09:(CLLocationCoordinate2D)location
+{
+    CLLocationCoordinate2D gcj02Pt = [self gcj02Encrypt:location.latitude
+                                                  bdLon:location.longitude];
+    return [self bd09Encrypt:gcj02Pt.latitude bdLon:gcj02Pt.longitude] ;
+}
+
++ (CLLocationCoordinate2D)gcj02ToBd09:(CLLocationCoordinate2D)location
+{
+    return  [self bd09Encrypt:location.latitude bdLon:location.longitude];
+}
+
++ (CLLocationCoordinate2D)bd09ToGcj02:(CLLocationCoordinate2D)location
+{
+    return [self bd09Decrypt:location.latitude bdLon:location.longitude];
+}
+
++ (CLLocationCoordinate2D)bd09ToWgs84:(CLLocationCoordinate2D)location
+{
+    CLLocationCoordinate2D gcj02 = [self bd09ToGcj02:location];
+    return [self gcj02Decrypt:gcj02.latitude gjLon:gcj02.longitude];
+}
+
+@end

+ 4 - 0
SLAiELTS/SLAiELTS/ViewControllers/FriendsVC/Model/SLRecomFriendModel.h

@@ -23,6 +23,10 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, copy) NSString *interests;
 
+@property (nonatomic, copy) NSString *distance;
+
+@property (nonatomic, copy) NSString *sex;
+
 @property (nonatomic, assign) BOOL addSuccess;
 
 - (NSString *)getUserHeadUrl;

+ 36 - 2
SLAiELTS/SLAiELTS/ViewControllers/FriendsVC/SLNearbyPeopleVc.m

@@ -7,10 +7,14 @@
 
 #import "SLNearbyPeopleVc.h"
 #import "SLNearbyPeopleCell.h"
+#import "SLLocationManager.h"
+#import "SLFriensInfoVc.h"
 
 @interface SLNearbyPeopleVc ()<UITableViewDelegate, UITableViewDataSource>
+
 @property (weak, nonatomic) IBOutlet UITableView *tableView;
 
+@property (nonatomic, strong)NSMutableArray *nearbyPeoples;
 @end
 
 @implementation SLNearbyPeopleVc
@@ -24,6 +28,25 @@
     YMBarButtonItem *rightBarItem =[[YMBarButtonItem alloc]initWithImage:creatImage style:YMBarButtonItemPlain target:self action:@selector(moreBtnClick)];
     rightBarItem.titleInsets = UIEdgeInsetsMake(0, 0, 0, 20);
     self.navigationBar.rightBarButtonItem = rightBarItem;
+    WS(weakSelf);
+    [[SLLocationManager shareInstance] getLocationComplete:^(CLLocation * _Nullable currentLocation) {
+        NSLog(@"%f--%f",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude);
+        if (currentLocation) {
+            NSDictionary *parameter = @{@"province" : [SLLocationManager shareInstance].province ,
+                                        @"city" : [SLLocationManager shareInstance].city ,
+                                        @"lon" : @(currentLocation.coordinate.longitude) ,
+                                        @"lat" : @(currentLocation.coordinate.latitude)
+            };
+            [[SLHttpCenter SharedInstance] getWithUrl:@"/api/Contacts/PeopleNearby" parameter:parameter success:^(id responseObject) {
+                NSArray *datas = [responseObject objectForKey:@"data"];
+                NSArray *friendsModel = [SLFriendsModel mj_objectArrayWithKeyValuesArray:datas];
+                [weakSelf.nearbyPeoples addObjectsFromArray:friendsModel];
+                [weakSelf.tableView reloadData];
+            } failure:^(SPRequestError *error) {
+
+            }];
+        }
+    }];
 }
 
 - (void)moreBtnClick {
@@ -36,11 +59,13 @@
 }
 
 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
-    return 10;
+    return self.nearbyPeoples.count;
 }
 
 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
     SLNearbyPeopleCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(SLNearbyPeopleCell.class)];
+    SLFriendsModel *model = [self.nearbyPeoples objectAtIndex:indexPath.row];
+    [cell confignCellWith:model];
     return cell;
 }
 
@@ -49,7 +74,10 @@
 }
 
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
-    
+    SLFriendsModel *model = [self.nearbyPeoples objectAtIndex:indexPath.row];
+    SLFriensInfoVc *vc = [SLFriensInfoVc loadViewControllewWithNib];
+    vc.friendModel = model;
+    [self navPushViewController:vc animated:YES];
 }
 
 -(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
@@ -60,5 +88,11 @@
     return 0.001f;
 }
 
+- (NSMutableArray *)nearbyPeoples {
+    if (!_nearbyPeoples) {
+        _nearbyPeoples = [NSMutableArray array];
+    }
+    return _nearbyPeoples;
+}
 
 @end

+ 12 - 0
SLAiELTS/SLAiELTS/ViewControllers/FriendsVC/Views/SLNearbyPeopleCell.h

@@ -11,6 +11,18 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface SLNearbyPeopleCell : UITableViewCell
 
+@property (weak, nonatomic) IBOutlet UIImageView *headImageView;
+
+@property (weak, nonatomic) IBOutlet UILabel *userNameLabel;
+
+@property (weak, nonatomic) IBOutlet UIImageView *sexImageView;
+
+@property (weak, nonatomic) IBOutlet UILabel *distanceLabel;
+
+@property (nonatomic, strong) UIScrollView *interestcrollView;
+
+- (void)confignCellWith:(SLFriendsModel *)model;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 46 - 0
SLAiELTS/SLAiELTS/ViewControllers/FriendsVC/Views/SLNearbyPeopleCell.m

@@ -12,6 +12,12 @@
 - (void)awakeFromNib {
     [super awakeFromNib];
     // Initialization code
+    [self.interestcrollView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.top.equalTo(self.userNameLabel.mas_bottom).offset(4);
+        make.left.equalTo(self.userNameLabel.mas_left).offset(-2);
+        make.height.mas_equalTo(24);
+        make.right.equalTo(self.contentView.mas_right).offset(-16);
+    }];
 }
 
 - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
@@ -20,4 +26,44 @@
     // Configure the view for the selected state
 }
 
+- (void)confignCellWith:(SLFriendsModel *)model {
+    [self.headImageView sd_setImageWithURL:[NSURL URLWithString:[model getUserHeadUrl]]];
+    self.userNameLabel.text = model.userName;
+    self.distanceLabel.text = model.distance;
+    self.sexImageView.image = [model.sex isEqualToString:@"女"] ? ImageName(@"icon_sex_woman_r") : ImageName(@"icon_sex_man_b");
+    [self.interestcrollView.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        [obj removeFromSuperview];
+        obj = nil;
+    }];
+    NSArray *interests = [model.interests componentsSeparatedByString:@","];
+    __block CGFloat x = 0;
+    [interests enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        CGRect rect = YMBoundWidth(obj, [UIFont systemFontOfSize:12]);
+        CGFloat width = rect.size.width;
+        UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
+        label.text = obj;
+        label.frame = CGRectMake(x, 0, width + 24, 24);
+        label.textColor = SLColor(@"#636366");
+        label.font = [UIFont systemFontOfSize:12];
+        label.backgroundColor = SLColor(@"#F2F2F7");
+        label.layer.cornerRadius = 12.0;
+        label.textAlignment = NSTextAlignmentCenter;
+        label.clipsToBounds = YES;
+        [self.interestcrollView addSubview:label];
+        x += width + 28;
+    }];
+    self.interestcrollView.contentSize = CGSizeMake(x, 24);
+}
+
+- (UIScrollView *)interestcrollView {
+    if (!_interestcrollView) {
+        _interestcrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
+        _interestcrollView.bounces = NO;
+        _interestcrollView.showsVerticalScrollIndicator = NO;
+        _interestcrollView.showsHorizontalScrollIndicator = NO;
+        [self.contentView addSubview:_interestcrollView];
+    }
+    return _interestcrollView;
+}
+
 @end

+ 12 - 1
SLAiELTS/SLAiELTS/ViewControllers/FriendsVC/Views/SLNearbyPeopleCell.xib

@@ -16,12 +16,17 @@
                 <rect key="frame" x="0.0" y="0.0" width="354" height="99"/>
                 <autoresizingMask key="autoresizingMask"/>
                 <subviews>
-                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_ellipse" translatesAutoresizingMaskIntoConstraints="NO" id="LMr-Xc-pRl">
+                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_ellipse" translatesAutoresizingMaskIntoConstraints="NO" id="LMr-Xc-pRl">
                         <rect key="frame" x="16" y="25.666666666666671" width="48" height="48"/>
                         <constraints>
                             <constraint firstAttribute="width" constant="48" id="HNh-Wv-U35"/>
                             <constraint firstAttribute="height" constant="48" id="Xlb-uO-yTJ"/>
                         </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
+                                <integer key="value" value="24"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
                     </imageView>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="用户名称" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FQH-An-920">
                         <rect key="frame" x="80" y="25.666666666666671" width="65.333333333333314" height="19.333333333333329"/>
@@ -50,6 +55,12 @@
                     <constraint firstItem="3Tw-rh-f0k" firstAttribute="leading" secondItem="FQH-An-920" secondAttribute="trailing" constant="6" id="sHM-TK-3M1"/>
                 </constraints>
             </tableViewCellContentView>
+            <connections>
+                <outlet property="distanceLabel" destination="80A-AO-lwb" id="1Ps-Mj-mam"/>
+                <outlet property="headImageView" destination="LMr-Xc-pRl" id="rQy-vf-jxR"/>
+                <outlet property="sexImageView" destination="3Tw-rh-f0k" id="mnM-bl-4s9"/>
+                <outlet property="userNameLabel" destination="FQH-An-920" id="jbd-Kt-VIc"/>
+            </connections>
             <point key="canvasLocation" x="110.76923076923076" y="18.127962085308056"/>
         </tableViewCell>
     </objects>

+ 1 - 1
SLAiELTS/SLAiELTS/ViewControllers/FriendsVC/Views/SLRecomFriendsCell.m

@@ -19,7 +19,7 @@
     // Initialization code
     [self.interestcrollView mas_makeConstraints:^(MASConstraintMaker *make) {
         make.top.equalTo(self.friendNumLabel.mas_bottom).offset(4);
-        make.left.equalTo(self.friendNumLabel.mas_left);
+        make.left.equalTo(self.friendNumLabel.mas_left).offset(-2);
         make.height.mas_equalTo(24);
         make.right.equalTo(self.contentView.mas_right).offset(-16);
     }];