diff --git a/Sources/Amplitude/AMPEventExplorer.m b/Sources/Amplitude/AMPEventExplorer.m index 7ee0e057..2a05d38f 100644 --- a/Sources/Amplitude/AMPEventExplorer.m +++ b/Sources/Amplitude/AMPEventExplorer.m @@ -59,7 +59,7 @@ - (void)showBubbleView { dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { - [[[AMPUtils getSharedApplication] keyWindow] addSubview:self.bubbleView]; + [[AMPUtils getKeyWindow] addSubview:self.bubbleView]; }); [self.bubbleView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showInfoView)]]; @@ -70,7 +70,7 @@ - (void)showBubbleView { - (void)showInfoView { dispatch_async(dispatch_get_main_queue(), ^(void){ if (self.bubbleView != nil) { - UIViewController *rootViewController = [[[AMPUtils getSharedApplication] keyWindow] rootViewController]; + UIViewController *rootViewController = [[AMPUtils getKeyWindow] rootViewController]; NSBundle *bundle = [NSBundle bundleForClass:[AMPInfoViewController class]]; AMPInfoViewController *infoVC = [[AMPInfoViewController alloc] initWithNibName:@"AMPInfoViewController" bundle:bundle]; diff --git a/Sources/Amplitude/AMPUtils.h b/Sources/Amplitude/AMPUtils.h index 7670da64..24455777 100644 --- a/Sources/Amplitude/AMPUtils.h +++ b/Sources/Amplitude/AMPUtils.h @@ -41,6 +41,7 @@ #if TARGET_OS_IOS || TARGET_OS_MACCATALYST + (NSInteger)barBottomOffset; + (CGFloat)statusBarHeight; ++ (UIWindow *)getKeyWindow; #endif @end diff --git a/Sources/Amplitude/AMPUtils.m b/Sources/Amplitude/AMPUtils.m index 3cc75716..3e3fc14c 100644 --- a/Sources/Amplitude/AMPUtils.m +++ b/Sources/Amplitude/AMPUtils.m @@ -172,12 +172,38 @@ + (NSInteger)barBottomOffset { + (CGFloat)statusBarHeight { CGSize statusBarSize; if (@available(iOS 13.0, *)) { - statusBarSize = [[[[AMPUtils getSharedApplication].keyWindow windowScene] statusBarManager] statusBarFrame].size; + statusBarSize = [[[[AMPUtils getKeyWindow] windowScene] statusBarManager] statusBarFrame].size; } else { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + // Even with the availability check above, Xcode would still emit a deprecation warning here. + // Since there's no way that it could be reached on iOS's >= 13.0 + // (where `[UIApplication statusBarFrame]` was deprecated), we simply ignore the warning. statusBarSize = [[AMPUtils getSharedApplication] statusBarFrame].size; +#pragma clang diagnostic pop } return MIN(statusBarSize.width, statusBarSize.height); } + ++ (UIWindow *)getKeyWindow { + if (@available(iOS 13.0, *)) { + for (UIWindow *window in [[AMPUtils getSharedApplication] windows]) { + if ([window isKeyWindow]) { + return window; + } + } + return nil; + } else { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + // Even with the availability check above, Xcode would still emit a deprecation warning here. + // Since there's no way that it could be reached on iOS's >= 13.0 + // (where `[UIApplication keyWindow]` was deprecated), we simply ignore the warning. + return [[AMPUtils getSharedApplication] keyWindow]; +#pragma clang diagnostic pop + } +} + #endif @end diff --git a/Sources/Amplitude/Amplitude.m b/Sources/Amplitude/Amplitude.m index ac95656b..109c3a8a 100644 --- a/Sources/Amplitude/Amplitude.m +++ b/Sources/Amplitude/Amplitude.m @@ -1534,7 +1534,15 @@ - (BOOL)isArgument:(id) argument validType:(Class) class methodName:(NSString*)m - (NSString*)md5HexDigest:(NSString*)input { const char* str = [input UTF8String]; unsigned char result[CC_MD5_DIGEST_LENGTH]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + // As mentioned by @haoliu-amp in // https://github.com/amplitude/Amplitude-iOS/issues/250#issuecomment-655224554, + // > This crypto algorithm is used for our checksum field, actually you don't need to worry about the security concern for that. + // > However, we will see if we wanna switch it to SHA256. + // Based on this, we can silence the compile warning here until a fix is implemented. CC_MD5(str, (CC_LONG) strlen(str), result); +#pragma clang diagnostic pop NSMutableString *ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2]; for(int i = 0; i= 12.0 or tvOS's >= 11.0 + // (where `[NSKeyedUnarchiver unarchiveTopLevelObjectWithData:error:]` was deprecated), + // we simply ignore the warning. + return [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:data error:error]; +#pragma clang diagnostic pop + } +} + - (BOOL)archive:(id) obj toFile:(NSString*)path { - return [NSKeyedArchiver archiveRootObject:obj toFile:path]; + if (@available(tvOS 11.0, iOS 12, *)) { + NSError *archiveError = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:obj requiringSecureCoding:NO error:&archiveError]; + if (archiveError != nil) { + AMPLITUDE_ERROR(@"ERROR: Unable to archive object %@: %@", obj, archiveError); + return NO; + } + if (data == nil) { + AMPLITUDE_ERROR(@"ERROR: Archived data is nil for obj: %@", obj); + return NO; + } + NSError *writeError = nil; + BOOL writeSuccessful = [data writeToFile:path options:NSDataWritingAtomic error:&writeError]; + if (writeError != nil || !writeSuccessful) { + AMPLITUDE_ERROR(@"ERROR: Unable to write data to file for object %@: %@", obj, archiveError); + return NO; + } + return YES; + } else { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + // Even with the availability check above, Xcode would still emit a deprecation warning here. + // Since there's no way that this path could be reached on iOS's >= 12.0 or tvOS's >= 11.0 + // (where `[NSKeyedArchiver archiveRootObject:toFile:]` was deprecated), + // we simply ignore the warning. + return [NSKeyedArchiver archiveRootObject:obj toFile:path]; +#pragma clang diagnostic pop + } } - (BOOL)moveFileIfNotExists:(NSString*)from to:(NSString*)to {