Giter Site home page Giter Site logo

ios12adaptationtips's Introduction

ChenYilong 👋

😄 I'm @ChenYilong, living in Auckland, New Zealand, and a programmer who knows a bit about Objective-C, Swift, and Java and has written apps and frameworks.
👯 I'm currently writing some Swift, flutter, and Java code in my spare time at iTeaTime(源码派). Welcome to join the group.
📫 If you want to chat, you can send me an email, direct Twitter DM, and other ways to contact me.
📺 Welcome to fellow my YouTube channel: @iTeaTime Tech | 技术清谈

ios12adaptationtips's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ios12adaptationtips's Issues

iOS12.1 使用 UINavigationController + UITabBarController( UITabBar 磨砂),设置hidesBottomBarWhenPushed后,在 pop 后,会引起TabBar布局异常

如果使用系统OS12.1 UINavigationController + UITabBarController( UITabBar 磨砂),在popViewControllerAnimated 会遇到tabbar布局错乱的问题:

其中触发该问题的代码如下:

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
   
   if (self.childViewControllers.count > 0) {
       //如果没这行代码,是正常显示的
       viewController.hidesBottomBarWhenPushed = YES;
   }
   
   [super pushViewController:viewController animated:animated];
}

经过 @YaoJuan @MoLice 的提示,可以使用 QMUI_iOS/issues 提到的解决方案解决:

这个问题是 iOS 12.1 Beta 2 引入的问题,只要 UITabBar 是磨砂的,并且 push viewController 时 hidesBottomBarWhenPushed = YES 则手势返回的时候就会触发。

出现这个现象的直接原因是 tabBar 内的按钮 UITabBarButton 被设置了错误的 frame,frame.size 变为 (0, 0) 导致的。如果12.1正式版Apple修复了这个bug可以移除调这段代码(来源于QMUIKit的处理方式),如果12.1正式版本Apple Fix了这个bug,可以移除掉这个bug

在这里有讨论:
ChenYilong/CYLTabBarController#312

具体的解决方案是:

需要进行如下设置:

// .h
@interface CYLTabBar : UITabBar
@end

// .m
#import "CYLTabBar.h"

/**
*  用 block 重写某个 class 的指定方法
*  @param targetClass 要重写的 class
*  @param targetSelector 要重写的 class 里的实例方法,注意如果该方法不存在于 targetClass 里,则什么都不做
*  @param implementationBlock 该 block 必须返回一个 block,返回的 block 将被当成 targetSelector 的新实现,所以要在内部自己处理对 super 的调用,以及对当前调用方法的 self 的 class 的保护判断(因为如果 targetClass 的 targetSelector 是继承自父类的,targetClass 内部并没有重写这个方法,则我们这个函数最终重写的其实是父类的 targetSelector,所以会产生预期之外的 class 的影响,例如 targetClass 传进来  UIButton.class,则最终可能会影响到 UIView.class),implementationBlock 的参数里第一个为你要修改的 class,也即等同于 targetClass,第二个参数为你要修改的 selector,也即等同于 targetSelector,第三个参数是 targetSelector 原本的实现,由于 IMP 可以直接当成 C 函数调用,所以可利用它来实现“调用 super”的效果,但由于 targetSelector 的参数个数、参数类型、返回值类型,都会影响 IMP 的调用写法,所以这个调用只能由业务自己写。
*/
CG_INLINE BOOL
OverrideImplementation(Class targetClass, SEL targetSelector, id (^implementationBlock)(Class originClass, SEL originCMD, IMP originIMP)) {
   Method originMethod = class_getInstanceMethod(targetClass, targetSelector);
   if (!originMethod) {
       return NO;
   }
   IMP originIMP = method_getImplementation(originMethod);
   method_setImplementation(originMethod, imp_implementationWithBlock(implementationBlock(targetClass, targetSelector, originIMP)));
   return YES;
}
@implementation CYLTabBar

+ (void)load {
   /* 这个问题是 iOS 12.1 Beta 2 的问题,只要 UITabBar 是磨砂的,并且 push viewController 时 hidesBottomBarWhenPushed = YES 则手势返回的时候就会触发。
    
    出现这个现象的直接原因是 tabBar 内的按钮 UITabBarButton 被设置了错误的 frame,frame.size 变为 (0, 0) 导致的。如果12.1正式版Apple修复了这个bug可以移除调这段代码(来源于QMUIKit的处理方式)*/
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
       if (@available(iOS 12.1, *)) {
           OverrideImplementation(NSClassFromString(@"UITabBarButton"), @selector(setFrame:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP originIMP) {
               return ^(UIView *selfObject, CGRect firstArgv) {
                   
                   if ([selfObject isKindOfClass:originClass]) {
                       // 如果发现即将要设置一个 size 为空的 frame,则屏蔽掉本次设置
                       if (!CGRectIsEmpty(selfObject.frame) && CGRectIsEmpty(firstArgv)) {
                           return;
                       }
                   }
                   
                   // call super
                   void (*originSelectorIMP)(id, SEL, CGRect);
                   originSelectorIMP = (void (*)(id, SEL, CGRect))originIMP;
                   originSelectorIMP(selfObject, originCMD, firstArgv);
               };
           });
       }
   });
}
@end

目前我已经在我写的这个库 CYLTabBarController
进行了修改兼容。

相关代码修改:ChenYilong/CYLTabBarController@2c741c8

更多change log见:https://github.com/ChenYilong/CYLTabBarController/releases

领悟到 NSCoding 是一个坑,Apple 花了10年时间

本文主要阐述以下观点,如果你早已知晓,请忽略本条内容:

  • Apple 在 2008年7月11日 推出的 iOS2 里,带来了 NSKeyedArchiver、NSKeyedUnarchiver,2018年9月10日发布的 iOS12 几乎废弃了 NSKeyedArchiver、NSKeyedUnarchiver 中所有的方法,甚至包括 init 方法。Apple花了10年时间,发现 NSCoding 是一个坑。
  • iOS6 推出的 NSSecureCoding 是高配版本的 NSCoding,NSCoding 并不适合你用,请及早弃坑。而这不是你的问题,是 NSCoder、NSKeyedArchiver、NSKeyedUnarchiver 内部实现有问题。iOS6 修复了 NSCoder 的问题,iOS12 修复的是 NSKeyedArchiver、NSKeyedUnarchiver。
  • UIKit 出厂时还在用 NSCoding,Foundation 出厂时,标配 NSSecureCoding。
  • Foundation 中任何类都可以遵循 NSCoding,但是 NSObject 出厂时,并没有遵循。所以实现 -initWithCoder: 时,不能总是调用父类的 [super initWithCoder:],有时要调 [super init]
  • Nib 与 Storyboard 方式加载的 UIViewController ,是通过 -initWithNibName:bundle: 来声明文件路径,-initWithCoder: 与 NSKeyedUnarchiver 来加载的。了解这一点,有助于理解 UIViewController 生命周期。
  • 当一个对象被初始化时,init 方法可能并不会被执行,可能是通过执行 -initWithCoder: 初始化,所以只在 init 进行初始化,可能会丢失数据、属性。 -initWithCoder: 常常被忽略。

另外,本文示例代码基于 Objective-C, 对于 Swift 开发者,可以查看新出的 Codable 文档,本文请谨慎浏览。

NSCoding 简介

NSCoding 是为了 NSData 与对象转换而设计的协议。命名也是进行时态,很形象。

任何想要与 NSData 自由转换身份的对象,都需要遵从 NSCoding。当时 Apple 设计 NSCoding 的时候,可能没想到自己埋了很多坑。

坑被发现后,在 iOS6 推出 NSSecureCoding,解决 NSCoder 解码异常问题

关于 NSCoder 里的坑,Apple 官网讲得很清楚: Documentation-Foundation-Archives and Serialization-NSSecureCoding,在此不做赘述。

关于 NSSecureCoding 用法,下面是 AFNetworking 的两个使用场景:

场景一:常规操作

#pragma mark - NSSecureCoding

+ (BOOL)supportsSecureCoding {
   return YES;
}

- (instancetype)initWithCoder:(NSCoder *)decoder {
   self = [self init];
   if (!self) {
       return nil;
   }

   self.acceptableStatusCodes = [decoder decodeObjectOfClass:[NSIndexSet class] forKey:NSStringFromSelector(@selector(acceptableStatusCodes))];
   self.acceptableContentTypes = [decoder decodeObjectOfClass:[NSIndexSet class] forKey:NSStringFromSelector(@selector(acceptableContentTypes))];

   return self;
}

- (void)encodeWithCoder:(NSCoder *)coder {
   [coder encodeObject:self.acceptableStatusCodes forKey:NSStringFromSelector(@selector(acceptableStatusCodes))];
   [coder encodeObject:self.acceptableContentTypes forKey:NSStringFromSelector(@selector(acceptableContentTypes))];
}

场景二:正如上文所属,因为有可能不执行init方法,直接执行 -initWithCoder:,需要在这里做完整的初始化流程。

//AFURLSessionManager
#pragma mark - NSSecureCoding

+ (BOOL)supportsSecureCoding {
   return YES;
}

- (instancetype)initWithCoder:(NSCoder *)decoder {
   NSURLSessionConfiguration *configuration = [decoder decodeObjectOfClass:[NSURLSessionConfiguration class] forKey:@"sessionConfiguration"];

   self = [self initWithSessionConfiguration:configuration];
   if (!self) {
       return nil;
   }

   return self;
}

- (void)encodeWithCoder:(NSCoder *)coder {
   [coder encodeObject:self.session.configuration forKey:@"sessionConfiguration"];
}

iOS12 全面推行安全归档,应对文件替换攻击。

以往 iOS 防止数据篡改,主要重心放在网络传输策略,但是数据处理部分依然存在被攻击风险。而归档,正是短板所在。而所有对象归档、编解码都会走同一个方法,这对攻击者而言也十分方便。

这次 WWDC Apple 提到了文件替换攻击(iOS object substitution attack),指的是攻击者替换本地归档文件,伪造数据。从而达到数据篡改、攻击目的。

推测进程间通信 xpc ,应该是高危环节。XPC介绍可以参考: apple-documentation-xpc《ObjC ** - XPC》

Apple 给出的策略是,为归档的编解码方法添加,类名校验。也就是在编解码前,先检测属性的类是否是指定的类,然后再决定是否编解码。
iOS12 中,Apple 几乎废弃了 NSKeyedArchiver 和 NSKeyedUnarchiver 原有的所有方法,甚至包括init方法,然后全部加入了类名校验。提高了篡改数据的成本。

不过,
Jonathan Zdziarski 在 preventing widespread automated attacks in ios -part-2 一文中曾指出,
如果用户 hook 了 NSKeyedArchiver (或者 NSKeyedUnarchiver) 编解码方法后,runtime 拦截数据(应该也有篡改的风险),因为我对逆向了解较少,不确定本次 iOS12 的改动是否能抵御该风险,但从原理上推测,Jonathan Zdziarski 在文中指出的漏洞 iOS12 依然存在。期待后续会有更安全的应对策略。

TODO List

下面是开发者需要及时跟进的项:

  • 自定义类,Objective-C开发者,使用 NSSecureCoding ,放弃使用 NSCoding ,具体用法上文已给出示例代码。Swift开发者,启用 Codable。
  • NSKeyedArchiver、NSKeyedUnarchiver 使用新的API,让系统在编解码前校验属性类名,注意新API 最低要从iOS11/iOS12起。

附录

相关API变更:

NSCoder:

//	Foundation/NSCoder.h
// Specify what the expected class of the allocated object is. If the coder responds YES to -requiresSecureCoding, then an exception will be thrown if the class to be decoded does not implement NSSecureCoding or is not isKindOfClass: of the argument. If the coder responds NO to -requiresSecureCoding, then the class argument is ignored and no check of the class of the decoded object is performed, exactly as if decodeObjectForKey: had been called.
- (nullable id)decodeObjectOfClass:(Class)aClass forKey:(NSString *)key API_AVAILABLE(macos(10.8), ios(6.0), watchos(2.0), tvos(9.0));

NSKeyedArchiver

//	Foundation/NSKeyedArchiver.h

/**
Initializes the receiver for encoding an archive, optionally disabling secure coding.

If \c NSSecureCoding cannot be used, \c requiresSecureCoding may be turned off here; for improved security, however, \c requiresSecureCoding should be left enabled whenever possible. \c requiresSecureCoding ensures that all encoded objects conform to \c NSSecureCoding, preventing the possibility of encoding objects which cannot be decoded later.

To produce archives whose structure matches those previously encoded using \c +archivedRootDataWithObject, encode the top-level object in your archive for the \c NSKeyedArchiveRootObjectKey.
*/
- (instancetype)initRequiringSecureCoding:(BOOL)requiresSecureCoding API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));

/**
Returns an \c NSData object containing the encoded form of the object graph whose root object is given, optionally disabling secure coding.

If \c NSSecureCoding cannot be used, \c requiresSecureCoding may be turned off here; for improved security, however, \c requiresSecureCoding should be left enabled whenever possible. \c requiresSecureCoding ensures that all encoded objects conform to \c NSSecureCoding, preventing the possibility of encoding objects which cannot be decoded later.

If the object graph cannot be encoded, returns \c nil and sets the \c error out parameter.
*/
+ (nullable NSData *)archivedDataWithRootObject:(id)object requiringSecureCoding:(BOOL)requiresSecureCoding error:(NSError **)error API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));

/// Initialize the archiver with empty data, ready for writing.
- (instancetype)init API_DEPRECATED("Use -initRequiringSecureCoding: instead", macosx(10.12,10.14), ios(10.0,12.0), watchos(3.0,5.0), tvos(10.0,12.0));
- (instancetype)initForWritingWithMutableData:(NSMutableData *)data API_DEPRECATED("Use -initRequiringSecureCoding: instead", macosx(10.2,10.14), ios(2.0,12.0), watchos(2.0,5.0), tvos(9.0,12.0));

+ (NSData *)archivedDataWithRootObject:(id)rootObject API_DEPRECATED("Use +archivedDataWithRootObject:requiringSecureCoding:error: instead", macosx(10.2,10.14), ios(2.0,12.0), watchos(2.0,5.0), tvos(9.0,12.0));
+ (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path API_DEPRECATED("Use +archivedDataWithRootObject:requiringSecureCoding:error: instead", macosx(10.2,10.14), ios(2.0,12.0), watchos(2.0,5.0), tvos(9.0,12.0));
//
@property (readwrite) NSDecodingFailurePolicy decodingFailurePolicy API_AVAILABLE(macos(10.11), ios(9.0), watchos(2.0), tvos(9.0));

NSKeyedUnarchiver

/**
Initializes the receiver for decoding an archive previously encoded by \c NSKeyedUnarchiver.

Enables \c requiresSecureCoding by default. If \c NSSecureCoding cannot be used, \c requiresSecureCoding may be turned off manually; for improved security, \c requiresSecureCoding should be left enabled whenever possible.

Sets the unarchiver's \c decodingFailurePolicy to \c NSDecodingFailurePolicySetErrorAndReturn.

Returns \c nil if the given data is not valid, and sets the \c error out parameter.
*/
- (nullable instancetype)initForReadingFromData:(NSData *)data error:(NSError **)error API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));

/**
Decodes the root object of the given class from the given archive, previously encoded by \c NSKeyedArchiver.

Enables \c requiresSecureCoding and sets the \c decodingFailurePolicy to \c NSDecodingFailurePolicySetErrorAndReturn.

Returns \c nil if the given data is not valid or cannot be decoded, and sets the \c error out parameter.
*/
+ (nullable id)unarchivedObjectOfClass:(Class)cls fromData:(NSData *)data error:(NSError **)error API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0)) NS_REFINED_FOR_SWIFT;


/**
Decodes the root object of one of the given classes from the given archive, previously encoded by \c NSKeyedArchiver.

Enables \c requiresSecureCoding and sets the \c decodingFailurePolicy to \c NSDecodingFailurePolicySetErrorAndReturn.

Returns \c nil if the given data is not valid or cannot be decoded, and sets the \c error out parameter.
*/
+ (nullable id)unarchivedObjectOfClasses:(NSSet<Class> *)classes fromData:(NSData *)data error:(NSError **)error API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0)) NS_REFINED_FOR_SWIFT;

- (instancetype)init API_DEPRECATED("Use -initForReadingFromData:error: instead", macosx(10.2,10.14), ios(2.0,12.0), watchos(2.0,5.0), tvos(9.0,12.0));
- (instancetype)initForReadingWithData:(NSData *)data API_DEPRECATED("Use -initForReadingFromData:error: instead", macosx(10.2,10.14), ios(2.0,12.0), watchos(2.0,5.0), tvos(9.0,12.0));

+ (nullable id)unarchiveObjectWithData:(NSData *)data API_DEPRECATED("Use +unarchivedObjectOfClass:fromData:error: instead", macosx(10.2,10.14), ios(2.0,12.0), watchos(2.0,5.0), tvos(9.0,12.0));
+ (nullable id)unarchiveTopLevelObjectWithData:(NSData *)data error:(NSError **)error API_DEPRECATED("Use +unarchivedObjectOfClass:fromData:error: instead", macosx(10.2,10.14), ios(2.0,12.0), watchos(2.0,5.0), tvos(9.0,12.0)) NS_SWIFT_UNAVAILABLE("Use 'unarchiveTopLevelObjectWithData(_:) throws' instead");
+ (nullable id)unarchiveObjectWithFile:(NSString *)path API_DEPRECATED("Use +unarchivedObjectOfClass:fromData:error: instead", macosx(10.2,10.14), ios(2.0,12.0), watchos(2.0,5.0), tvos(9.0,12.0));

参考文献

AR based on mobile 101

关于移动端 AR 的一些思考与调研

今年 Apple 发布了其历史上两款史上最强(gui)的移动类型设备,其中附加值最高的,不是屏幕、尺寸,应属 A12 和 A12X Bionic 芯片。全程讲硬件,于是发布会并不是像国内的相声专场式发布会那样好看。但这两种发布会重心不同,一个是志在解决未来的问题,一个努力在解决当下的问题。有人说曾几何时苹果发布会是不屑于炫耀自己的芯片是多么强大,可是现如今苹果发布会上不停的说这枚芯片有多么厉害,多么智能。这是 Apple 软件创新乏力,于是用硬件凑。而从开发者角度看,从 2017、2018 的 WWDC 中,机器学习和 AR 的 session 每年都超过10个。说明硬件升级,是 Apple 在为软件层面布局,下一个风口,应该是 Core ML 和 AR。而机器学习在移动端落地,除了图像处理、拍照应用、语音处理,最大的入口就是 AR,其中移动端 AR 落地最好就是如抖音、line等视频直播应用。

巨头新宠

Android 阵营,Google 准备了 TensorFlow Lite,但 Google 不做硬件,这个推广的短板。即使是 Pixel,单就图像识别一项上,iPhone 上经过优化,速度能比它快6倍以上。同时 AR 也成为 BAT 的新战场,吴恩达负责的百度研究院也成立第四大实验室——增强现实实验室(AR Lab),应用在了百度 APP 上,应用场景有 AR 在手机上复原古建筑,实用性有待提升,运用的是完全自研的 AR 技术。阿里巴巴有支付宝 AR 实景红包,淘宝 VR 购物,还投资了 AR 初创公司 Magic Leap; 腾讯有 QQ AR 实景红包、 AR 火炬,据说还要做一个 QAR 的 AR 开放平台。但都没有硬件优势,Apple 是唯一“软硬兼施”,假设 Apple 的目标是击退 Android,引流到自己平台上,那么可以说 Apple 拿得一手好牌,似乎并没打好。

而 Apple ,在发布会上演示的多人对抗 AR 游戏,以及自家应用比如 iMessage 里的换脸功能, AR 技术上的积累就可见一斑,但却没有带来足够的流量,反倒是在抖音被“带”火起来的,不过今年库克还专门去了国内的在 AR 领域已经落地、视频流量之王的抖音、头条访问,可见对 AR 技术落地的关注。明年发布会上 iMessage 换脸一键分享到抖音、或者抖音唤起系统的换脸摄像头、甚至介绍 ARKit 在抖音上的应用,都不是不可能。这个反应出 ARKit 推广还是非常难。

我在近期做的一个项目也使用了 AR 技术,但是由于无法摆脱兼容版本的限制、无法跨平台,于是第一个排除的竟是最强大的 ARKit。于是我想在这里做下调研,想看下国内做的 AR 技术现状。稍后也会基于此写几篇关于 AR 的博文,供大家在做技术选型时做参考。

调研两条内容:

  1. 你正在应用是否涉及 AR 功能,如果涉及,应用场景属于哪种,或者说被训练物体的种类属于哪一类?投票地址微博下方: 【你的APP中AR应用场景属于哪类?】http://t.cn/Ew4TM1b
  2. 你的 APP 中的AR是用什么SDK实现的?微博投票选项有限制,故放在金数据上: https://jinshuju.net/f/uYXFOA

应用场景属于哪一种?

说明:分类方案是引用自《iPhone Game Blueprints》一书:

  • Symbol-based: 也即基准标记物(fiducial markers),是最初级的一类训练物体方式,这类的物体识别基于类似于非常明显的标记,比如边框特征,二维、三维物体的边角。QR 二维码就是非常典型的Symbol-based,所有二维码都有三个角是边框状,以此作为是否是二维码的标准来进行物体追踪。但本次调研,二维码不属于AR范畴。
  • Image-based: 基于图片,比如支付宝 AR 红包。
  • Object-based: 基于实物,比如抖音特效里的川剧变脸、iMessage里的换脸。
  • Map-based: 基于地图;比如采用 SLAM 技术(Simultaneous Localization And Mapping,即时定位与地图构建技术),SLAM 已大量运用在无人机与无人车上用于建立周围环境的三维地图,在 APP 上的应用比如百度APP,镜头对准实物建筑物,在手机上复原古建筑。
  • Location-based: 基于地理位置,比如 2016 年大火的Pokémon Go,实际仅仅是运用地理位置信息信,并未采用其他信息作为marker。
  • other:欢迎留言补充。

原文如下:

  • Symbol-based: This is a basic method. It is the recognition and tracking of special graphic markers that are officially known as fiducial markers or fiducials (from the Latin fiducia, which means trust), but are sometimes referred to as AR tags, tracking marks, artificial landmarks, and so on. In some cases, slightly modified QR code markers can be used as well.
  • Image-based: Graphic images such as photos or illustrations are split into reference points (the simplest way is to find a contrast frame around a picture). For instance, some applications use the one-dollar bill as the real-world basis that AR content will be created on, arguing that bills are the most common pieces of paper with graphics on them that an ordinary person can get their hands on. Such practice is used by programs such as Shimmer Augmented Reality Viewer for iOS (http://ionreality.com/shimmer/), which allows you to view 3D models in the AR space. In some cases, when very accurate recognition tasks are the goal, the image-based method may require very powerful CPU resources, because graphic images are split into thousands of markers that are being tracked in real time. This is why there is a service called Xloudia (http://www.lm3labs.com/xloudia/) that makes such calculations in the cloud computing to recognize complicated images on the server side.
  • Object-based: Special real objects are used as markers. They can be passive (only their geometry and contrast color will be used as markers) or active (they will emit signals as light ones). Usually, they come in the shape of small cubes or spheres. There are also some applications that track a user's face and use their movements as input data.
  • Map-based: A 3D map of the surroundings is created and the elements of a landscape are used as references. For instance, AR applications can use simultaneous localization and mapping (SLAM) tracking, a technology that is utilized by autonomous, movable robots. This is one of the most advanced methods of orientation and navigation in space. It allows us to use real surroundings, and virtual elements can interact with real-world objects in a more natural way.
  • Location-based: This algorithm does not require any graphic markers. It uses the advantages of GPS (or its competitors), the compass, and accelerometer to determine the position and tilt of a device. Usually, such technology is used to add some virtual features to AR geo-information about real physical objects, such as city landmarks, in order to give the virtual representation of the information some textual and graphic description, interactive functionality, and so on. There are also some interesting massively multiplayer online game projects based on accurate location detection.

你的 APP 中的AR是用什么SDK实现的?

列表中的SDK,我并没有全部用过,信息来自于格哈德Reitmayr创建和共享在1inkedin上。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.