一.iPhone X尺寸问题
1. 高度增加了145pt,变成812pt.
2.屏幕圆角显示,注意至少留10pt边距。
3. 状态栏高度由20pt变成44pt,留意这个距离就能避开“刘海”的尴尬,相应的导航栏以上变化64--->88。
4.底部工具栏需要为home indicator留出34pt边距。 5.物理分辨率为1125px * 2436px
非iPhone X :
StatusBar高20px,NavigationBar高44px,底部TabBar高49px
iPhone X:
StatusBar高44px,NavigationBar高44px,底部TabBar高83px
二.适配用到的宏
// status bar height.
#define kStatusBarHeight (IS_iPhoneX ? 44.f : 20.f)
// Navigation bar height.
#define kNavigationBarHeight 44.f
// Tabbar height.
#define kTabbarHeight (IS_iPhoneX ? (49.f+34.f) : 49.f)
// Tabbar safe bottom margin.
#define kTabbarSafeBottomMargin (IS_iPhoneX ? 34.f : 0.f)
// Status bar & navigation bar height.
#define kStatusBarAndNavigationBarHeight (IS_iPhoneX ? 88.f : 64.f)
//判断是否iPhone X
#define IS_iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO)
三.APP启动样式适配,屏幕未充满
1.启动页屏幕未充满
APP在iPhone X上占满整个屏幕, 而是保持着原有的高度 在屏幕中心位置, 屏幕的顶部和底部都有黑边.
![](https://img.haomeiwen.com/i2102697/3b00b684af1bd432.png)
![](https://img.haomeiwen.com/i2102697/22c52a70f9a51019.png)
通过LaunchScreen.storyboard方式启动
如果使用的是Assets中的LaunchImage, 在增加了iPhone X尺寸的图片配置后.
LaunchScreen.storyboard方式不用多说, 这里说一下如何在LaunchImage中增加iPhone X尺寸的图片配置.
方法一:
准备一张尺寸:1125 * 2436的 3x启动图片, 移动到LaunchImage的Finder目录中, 并在LaunchImage中的Contents.json文件中增加 (注意Json格式):
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "2436h",
"filename" : "图片名.png",
"minimum-system-version" : "11.0",
"orientation" : "portrait",
"scale" : "3x"
}
![](https://img.haomeiwen.com/i2102697/e130977fd78d566d.png)
方法二:
![](https://img.haomeiwen.com/i2102697/a5077275c7fb37ae.png)
![](https://img.haomeiwen.com/i2102697/a6986e0bc45a1958.png)
![](https://img.haomeiwen.com/i2102697/11bcd10adb2522ff.png)
![](https://img.haomeiwen.com/i2102697/0a7a9b9cfe7ae976.png)
![](https://img.haomeiwen.com/i2102697/366ccbf92c9cc706.png)
2.引导页iPhone X图片变形
![](https://img.haomeiwen.com/i2102697/b24da7749b9679ed.png)
![](https://img.haomeiwen.com/i2102697/160043e87dac298f.png)
由于iPhone X高度发生变化,图片铺满整个屏幕时候造成图片拉伸,现在需要UI切一个1125*2436的3x图片和以前做iPhone X机型判断1124*2001图片,并且对图片contentMode属性进行设置
if (IS_iPhoneX) {
coverImageNames = [NSArray arrayWithObjects:@"img_big_1_ipx.jpg", @"img_big_2_ipx.jpg",@"img_big_3_ipx.jpg", @"img_big_4_ipx.jpg",nil];
}else{
coverImageNames = [NSArray arrayWithObjects:@"img_big_1.jpg", @"img_big_2.jpg",@"img_big_3.jpg", @"img_big_4.jpg",nil];
}
imageView.clipsToBounds = YES;//超出区域裁剪
imageView.contentMode = UIViewContentModeScaleAspectFill;//图片等比例拉伸,会填充整个区域,但是会有一部分过大而超出整个区域
四:UITableview UICollectionView MJRefresh下拉刷新错乱
![](https://img.haomeiwen.com/i2102697/fbe6dd8d09e552fa.png)
iOS11表格用MJRefresh框架下拉刷新的时候界面会闪,显示紊乱,
原因是iOS11弃用了automaticallyAdjustsScrollViewInsets属性,新增contentInsetAdjustmentBehavior来替代它
tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
解决方法:MJRefresh作者已经针对iOS 11和iPhone X做了适配,把MJRefresh更新最新的版本
//声明tableView的位置 添加下面代码
if (@available(iOS 11.0, *)) {
_tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
_tableView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0);
_tableView.scrollIndicatorInsets = _tableView.contentInset;
}
五.纯代码适配齐刘海
iPhone X导航栏由以前的固定64变成现在88,Statebar的高度由20变成44,增加24,项目中以前用导航栏64地方都进行是否iPhoneX判断,用到宏#define kStatusBarAndNavigationBarHeight (IS_iPhoneX ? 88.f : 64.f)
项目中导航栏自定义导航栏会遇到很多奇葩的问题如下图
![](https://img.haomeiwen.com/i2102697/dae6eabecbc0725f.png)
(1)在iPhone X中导航栏高度变成88,项目中自定义导航栏高度64,需要对导航栏高度进行判断
_navigationBar = [[MCCustomNavigationBar alloc]initWithFrame:CGRectMake(0, 0, SCREENW, 64) andType:CustomBarType_Home];
_navigationBar = [[MCCustomNavigationBar alloc]initWithFrame:CGRectMake(0, 0, SCREENW, kStatusBarAndNavigationBarHeight) andType:CustomBarType_Home];
(2)搜索框和左右两边按钮高度有问题,因为iPhone X中状态栏高度由20增加24变成44,所以搜索框和左右两边按钮高度在iPhone X上距顶部高度加上24高度,
#define itemTopOffset (IS_iPhoneX ? (26+24) : 26)
[self.leftBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.offset(itemHorOffset);
make.height.equalTo(@(itemHeight));
make.width.equalTo(@(itemHeight));
make.top.offset(itemTopOffset);
}];
(3)iOS11上searchBar高度明显变大,
![](https://img.haomeiwen.com/i2102697/2bf65b0bc2a41a82.png)
系统的searchBar
UISearchBar的中子控件及其布局
UIView(直接子控件) frame 等于 searchBar的bounds,view的子控件及其布局
UISearchBarBackground(间接子控件) frame 等于searchBar的bounds
UISearchBarTextField(间接子控件) frame.origin等于(8.0, 6.0),即不等于searchBar的bounds
改变searchBar的frame只会影响其中搜索框的宽度,不会影响其高度,原因如下:
系统searchBar中的UISearchBarTextField的高度默认固定为28
左右边距固定为8,上下边距是父控件view的高度减去28除以2
改变UISearchBar的高度
方案
重写UISearchBar的子类(MCSearchBar),重新布局UISearchBar子控件的布局
增加成员属性contentInset,控制UISearchBarTextField距离父控件的边距
若用户没有设置contentInset,则计算出默认的contentInset
若用户设置了contentInset,则根据最新的contentInset布局UISearchBarTextField
新建UISearchBar的子类,增加成员属性contentInset,用来调整UISearchBarTextField距离父控件的边距。contentInset的setter方法
#pragma mark - setter method
- (void)setContentInset:(UIEdgeInsets)contentInset {
_contentInset.top = contentInset.top;
_contentInset.bottom = contentInset.bottom;
_contentInset.left = contentInset.left;
_contentInset.right = contentInset.right;
self.isChangeFrame = YES;
[self layoutSubviews];
}
- (void)layoutSubviews {
[super layoutSubviews];
for (UIView *subView in self.subviews[0].subviews) {
if ([subView isKindOfClass:[UIImageView class]]) {
//移除UISearchBarBackground
[subView removeFromSuperview];
}
if ([subView isKindOfClass:[UITextField class]]) {
CGFloat height = self.bounds.size.height;
CGFloat width = self.bounds.size.width;
if (_isChangeFrame) {
//说明contentInset已经被赋值
// 根据contentInset改变UISearchBarTextField的布局
subView.frame = CGRectMake(_contentInset.left, _contentInset.top, width - 2 * _contentInset.left, height - 2 * _contentInset.top);
} else {
// contentSet未被赋值
// 设置UISearchBar中UISearchBarTextField的默认边距
CGFloat top = (height - 28.0) / 2.0;
CGFloat bottom = top;
CGFloat left = 8.0;
CGFloat right = left;
_contentInset = UIEdgeInsetsMake(top, left, bottom, right);
subView.frame = CGRectMake(_contentInset.left, _contentInset.top, width - 2 * _contentInset.left, height - 2 * _contentInset.top);
}
}
}
}
在项目中使用自定义的MCSearchBar,SearchBar的高度可以改变
(4)iOS11中UISearchBar没有居中居左显示,并且icon和placeholder间距太窄
![](https://img.haomeiwen.com/i2102697/08acefd1884c4c7e.png)
现在实现居中显示
![](https://img.haomeiwen.com/i2102697/b4cc1a78c2dd1abb.png)
@property(nonatomic,assign)CGFloatwidth;
//判断版本
if(@available(iOS11.0, *)){
UITextField *textField = [self.searchBar valueForKey:@"searchField"];
[textField sizeToFit];
//记录一下这个时候的宽度
_width= textField.frame.size.width;
[_searchBar setPositionAdjustment:UIOffsetMake((_searchBar.width-_width)/2.0,0)forSearchBarIcon:UISearchBarIconSearch];
}
然后在代理方法 searchBarTextDidBeginEditing:(UISearchBar*)searchBar 调整位置
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
if (@available(iOS 11.0, *)) {
if(!_searchBar.text.length) {
[_searchBar setPositionAdjustment:UIOffsetMake(0,0)forSearchBarIcon:UISearchBarIconSearch];
}
}
}
结束的方法 searchBarTextDidEndEditing:(UISearchBar*)searchBar 判断是否有内容
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar{
if (@available(iOS 11.0, *)) {
if(!_searchBar.text.length) {
[_searchBar setPositionAdjustment:UIOffsetMake((_searchBar.width-self.width)/2.0,0) forSearchBarIcon:UISearchBarIconSearch];
}
}
}
如果有占位文字后台返的,UITextField在搜索框默认文字大小17,可以根据文字个数和大小算出占位文字宽度,然后算出搜索图标的偏移量.
![](https://img.haomeiwen.com/i2102697/315c418335974a3c.png)
(5)搜索页面导航栏中搜索框距离返回按钮太近
![](https://img.haomeiwen.com/i2102697/ef639111fbcf9ca9.png)
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, testView.width - (SCREENW > 320 ? 90: 100)*SCREEN_Proportion, testView.height)];
由于搜索框距离左边距离导致的,现在需要定义一个宏做判断
#define marginLeft (IS_iPhoneX ? 10 : 0)
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(marginLeft, 0, testView.width - (SCREENW > 320 ? 90: 100)*SCREEN_Proportion, testView.height)];
![](https://img.haomeiwen.com/i2102697/e42e3c6569596d75.png)
六.纯代码适配底部工具栏
在iPhone X中底部工具栏需要为home indicator留出34pt边距,iPhone X以前机型TarBar高度49,iPhone X中Tarbar高度加上34变成83.由于项目中Tabbar是用自定义的,需要对Tabbar的高度做适配,用到宏#define kTabbarHeight (IS_iPhoneX ? (49.f+34.f) : 49.f)
![](https://img.haomeiwen.com/i2102697/441040bb5d18c225.png)
适配前代码
_customBarView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREENH - 49,SCREENW, 49)];
适配后的代码_customBarView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREENH - kTabbarHeight,SCREENW, kTabbarHeight)];
![](https://img.haomeiwen.com/i2102697/4f40e623a6f6cf15.png)
图标和文字和其他机型相比偏下,现在需要对图标和文字高度进行调整,做iPhone X和非iPhone X机型适配
![](https://img.haomeiwen.com/i2102697/b7d47cfa99d7c6b8.png)
![](https://img.haomeiwen.com/i2102697/4f89b24c3846dd7a.png)
七.底部view出现问题
(1)购物车View适配,涉及页面商品详情页,搜索页面,购物车页面
![](https://img.haomeiwen.com/i2102697/a9788b66416e94a7.png)
![](https://img.haomeiwen.com/i2102697/22bc620cab900baf.png)
![](https://img.haomeiwen.com/i2102697/2eac9f6f9c717786.png)
![](https://img.haomeiwen.com/i2102697/ba1519faac0b1716.png)
![](https://img.haomeiwen.com/i2102697/826150d1696dc2c6.png)
![](https://img.haomeiwen.com/i2102697/fe53ae1378ba8db9.png)
![](https://img.haomeiwen.com/i2102697/3f20bb883b1ac6e4.png)
![](https://img.haomeiwen.com/i2102697/7bfc169192044432.png)
-(void)updateUIFrame
{
if (_fromType == ToShoppingTrolleyType_New_Other) {
[[MCNavigationLeftView shareManager] initWithTitle:nil andNavi:self andSEL:@selector(back)];
[[MCTabbarTool shareManager]hideTabbarView:NO];
self.view.frame = CGRectMake(0, 0, SCREENW, SCREENH-kStatusBarAndNavigationBarHeight-(IS_iPhoneX?34:0));
}else{
[[MCTabbarTool shareManager]showTabbarView:YES];
self.view.frame = CGRectMake(0, 0, SCREENW, SCREENH-kStatusBarAndNavigationBarHeight-kTabbarHeight);
}
self.cartBottomView.frame = CGRectMake(0, self.view.height-49, SCREENW, 49);
}
(2)自定义数字键盘适配
![](https://img.haomeiwen.com/i2102697/b8a7fe5bbb0ed41c.png)
![](https://img.haomeiwen.com/i2102697/ec10b514f2d9fc43.png)
适配底部用的一个宏#define kTabbarSafeBottomMargin (IS_iPhoneX ? 34.f : 0.f)用于计算距离屏幕顶部高度,如果iPhone X,留出距离屏幕底部34安全距离,控件不能显示34安全距离上
![](https://img.haomeiwen.com/i2102697/037cd48091edc864.png)
![](https://img.haomeiwen.com/i2102697/dbfbedf11825bf52.png)
(3)筛选views适配
![](https://img.haomeiwen.com/i2102697/da074e5ded50857d.png)
![](https://img.haomeiwen.com/i2102697/a0078afb8d2932d2.png)
![](https://img.haomeiwen.com/i2102697/0c70bff117c2f9c6.png)
运行程序发现底部按钮高度偏高,如图所示,现在需要调整底部按钮距离屏幕顶部高度
![](https://img.haomeiwen.com/i2102697/56bfad465e078a90.png)
![](https://img.haomeiwen.com/i2102697/dce5f242cca57847.png)
![](https://img.haomeiwen.com/i2102697/be8eb4b657d9500e.png)
![](https://img.haomeiwen.com/i2102697/336e2395af380024.png)
(4)适配查看优惠券
![](https://img.haomeiwen.com/i2102697/d489cf605754a0f3.png)
![](https://img.haomeiwen.com/i2102697/ebb3e17e0d99b8a5.png)
![](https://img.haomeiwen.com/i2102697/54257ee56a856bad.png)
![](https://img.haomeiwen.com/i2102697/0267a1398f61db5b.png)
![](https://img.haomeiwen.com/i2102697/a70c6ec56af34f59.png)
(5)适配填写订单
![](https://img.haomeiwen.com/i2102697/358ccdb83e680478.png)
![](https://img.haomeiwen.com/i2102697/aa34a16e957107bd.png)
![](https://img.haomeiwen.com/i2102697/c1508e7f532e9256.png)
![](https://img.haomeiwen.com/i2102697/f1d23462e1bd9625.png)
(6)Tabbar没有完全遮住
![](https://img.haomeiwen.com/i2102697/b5f4f7abf95fdaea.png)
为了遮住TabBar,在iPhone X上tabbar高度增加34,需要调整遮罩tabbar窗口的高度
![](https://img.haomeiwen.com/i2102697/d142382f32a651de.png)
![](https://img.haomeiwen.com/i2102697/80fe89bf215645ca.png)
![](https://img.haomeiwen.com/i2102697/1faf8069931f30ae.png)
八.继承自UIScrollView的视图偏移问题
我们可以发现collectionview在iOS11向下偏移64,什原因导致偏移?在iOS11之前,如果想要scrollView不偏移64p,则需设置automaticallyAdjustsScrollViewInsets=NO,但是这个属性在iOS11直接被遗弃了😳:使用scrollView的属性contentInsetAdjustmentBehavior来防止偏移。
UIScrollViewContentInsetAdjustmentAutomatic
UIScrollViewContentInsetAdjustmentScrollableAxes
UIScrollViewContentInsetAdjustmentNever
UIScrollViewContentInsetAdjustmentAlways
这里我们直接选Never就可以了
if (@available(iOS 11.0, *)) {
_collectionView.contentInsetAdjustmentBehavior = UIApplicationBackgroundFetchIntervalNever;
}
但是在iOS11以前系统编译崩溃,原来@available(iOS 11.0, *)是iOS 11新增加的,在iOS11以下系统找不到崩溃,为了解决这个问题需要用到条件编译指令解决这个问题
#ifdef __IPHONE_11_0
if (@available(iOS 11.0, *)) {
_collectionView.contentInsetAdjustmentBehavior = UIApplicationBackgroundFetchIntervalNever;
}
#endif
![](https://img.haomeiwen.com/i2102697/60bc7f2b84cf900d.png)
![](https://img.haomeiwen.com/i2102697/440e3c12da0e3dc1.png)
九.自定义分割线处理
1.iOS 11分割线颜色加深
iOS 11中有的自定义分割线颜色莫名奇妙变深,很难看,如下图所示,不符合设计规范,尝试其他方法没有解决这个问题,最后通过改变分割线的透明度来解决
![](https://img.haomeiwen.com/i2102697/e5b6cdd076510432.png)
![](https://img.haomeiwen.com/i2102697/8b0f2d2eb265435f.png)
![](https://img.haomeiwen.com/i2102697/7b54204bfe18910b.png)
![](https://img.haomeiwen.com/i2102697/f1fbbc071559b335.png)
2.没有文字显示分割线
![](https://img.haomeiwen.com/i2102697/5f0b0d4a98cbf560.png)
// 这些界面以下使用代理方法来设置,发现并没有生效
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
// 这样的原理是因为之前只是实现了高度的代理方法,却没有实现View的代理方法,iOS10及以前这么写是没问题的,iOS11开启了行高估算机制引起的bug,因此有以下几种解决方法:
// 解决方法一:添加实现View的代理方法,只有实现下面两个方法,方法 (CGFloat)tableView: heightForFooterInSection: 才会生效
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return nil;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
return nil;
}
// 解决方法二:直接使用tableView属性进行设置,修复该UI错乱
self.tableView.sectionHeaderHeight = 0;
self.tableView.sectionFooterHeight = 5;
[_optionTableView setContentInset:UIEdgeInsetsMake(-35, 0, 0, 0)];
// 解决方法三:添加以下代码关闭估算行高
self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;
![](https://img.haomeiwen.com/i2102697/bc60c2787da38e2b.png)
十.顶部菜单上移,挡住文字适配
![](https://img.haomeiwen.com/i2102697/e0bb9fb87f400556.png)
![](https://img.haomeiwen.com/i2102697/2e75e4e82736f445.png)
![](https://img.haomeiwen.com/i2102697/efa87936f9cf7147.png)
![](https://img.haomeiwen.com/i2102697/69a94fce0b7e0a9f.png)
十一.适配xib页面
![](https://img.haomeiwen.com/i2102697/0c3f510ed6785665.png)
注册页面用xib写的,页面tableview距离顶部高度64,写死的,由于导航栏高度在iPhone X和非iPhone X高度不一致,如果都写成64出现下图问题,为了解决这个问题,用到系统自动布局NSLayoutConstraint视图上面,在storyboard 中,通过拖拽方式,将一个IBOutlet 拖拽到 .m 文件中如图所示
![](https://img.haomeiwen.com/i2102697/2119b8a9079b71aa.png)
![](https://img.haomeiwen.com/i2102697/8925c452aec8449a.png)
![](https://img.haomeiwen.com/i2102697/9a98155d472c198b.png)
十二:信号栏的字体颜色无法改变
![](https://img.haomeiwen.com/i2102697/09d898153518c9d7.png)
![](https://img.haomeiwen.com/i2102697/988848f010fc4938.png)
改变信号栏方法使用,如果某个页面状态栏颜色改变自己定义颜色用这个方法,针对iOS11以前使用
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[MCHelpTool changeSignalFormatWithColor:[UIColor whiteColor]];
}
但是在iOS11上状态栏的颜色通过这个方法无法改变,状态栏机制发生变化导致,需要对该方法进行iOS11适配.
![](https://img.haomeiwen.com/i2102697/371a19143539a650.png)
![](https://img.haomeiwen.com/i2102697/cc24b3b54dd40939.png)
![](https://img.haomeiwen.com/i2102697/093d975c8750d14b.png)
/**
* 改变信号栏字体颜色
*
* @param color 颜色参数
*/
+ (void)changeSignalFormatWithColor:(UIColor *)color{
UIApplication * app = [UIApplication sharedApplication];
id obj = [app valueForKeyPath:@"statusBar"];
if (@available(iOS 11.0, *)) {
if (IS_iPhoneX) {
id obc = [obj valueForKeyPath:@"statusBar"];
unsigned int propertyCount;
objc_property_t * properties = class_copyPropertyList([obc class], &propertyCount);
NSMutableArray * arr = [NSMutableArray arrayWithCapacity:1];
for (int i = 0; i < propertyCount; i++){
objc_property_t property = properties[i];
NSString * propertyStr = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
if ([propertyStr isEqualToString:@"foregroundColor"]){
[obj setValue:color forKey:propertyStr];
}
[arr sui_addObj:propertyStr];
}
free(properties);
}else{
id ob = [obj valueForKeyPath:@"superclass"];
unsigned int propertyCount;
objc_property_t * properties = class_copyPropertyList([ob class], &propertyCount);
NSMutableArray * arr = [NSMutableArray arrayWithCapacity:1];
for (int i = 0; i < propertyCount; i++){
objc_property_t property = properties[i];
NSString * propertyStr = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
if ([propertyStr isEqualToString:@"foregroundColor"]){
[obj setValue:color forKey:propertyStr];
}
[arr sui_addObj:propertyStr];
}
free(properties);
}
}else{
unsigned int propertyCount;
objc_property_t * properties = class_copyPropertyList([obj class], &propertyCount);
NSMutableArray * arr = [NSMutableArray arrayWithCapacity:1];
for (int i = 0; i < propertyCount; i++){
objc_property_t property = properties[i];
NSString * propertyStr = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
if ([propertyStr isEqualToString:@"foregroundColor"]){
[obj setValue:color forKey:propertyStr];
}
[arr sui_addObj:propertyStr];
}
free(properties);
}
}
未完待续....
参考文章:
iOS11-UISearchBar居中placeholder和icon
UIsearchBar iOS11 像之前的版本那样没有内容居中 有内容居左
WWDC17: What's New in Location Technologies ?
网友评论