Author: Panda Fang
Source: http://www.cnblogs.com/lonkiss/p/6492385.html
Original articles, reprinted please indicate the author and origin, without permission can not be used for commercial profit-making activities
Last year to this year, I did several AIR Native Extension (ANE) on iOS, which was very painful. The way of ANE development has long been wasted by the predecessors' Tucao, which is much inefficient and seriously depressed kpi. After experiencing Unity's plug-in development, it's really much more refreshing and efficient.
To put it right, one of the pains is that it is difficult to achieve the life cycle of AppDelegate. As far as life cycle implementation is concerned, the ane on Android is also difficult. Write it next time. If it's convenient to make a standard iOS App on xcode to write AppDelegate, just fill in the function. But these APIs are not exposed on ANE for you to implement. Air itself is an app running on ios, and adobe implements it using delegate but not exposed to us. We use adobe air sdk as a framework relying on adobe. We can't help cursing Adobe while doing it. Now that adobe air is used, we can rely on hook s. The following article is worth reading.
Get through Android, IOS, ANE production processes - know why - Blog Channel - CSDN.NET
Then I will quote this article for explanation.
Create a new objective-c file named HookUtil in xcode. xocde will generate a HookUtil.m file to delete the code in the file and copy and paste the code below. But the following code can not solve the problem, really want to know why it is still to insist on seeing how I finally solve.
1 // 2 // HookUtils.m 3 // ResearchMethodSwizzl 4 // 5 // Created by Xue Yuan on 15/4/27. 6 // Copyright (c) 2015 Xue Xue. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 #import <UIKit/UIKit.h> 11 #import <objc/runtime.h> 12 13 14 @interface HookUtils : NSObject 15 16 + (void)hookMehod:(SEL)oldSEL andDef:(SEL)defaultSEL andNew:(SEL)newSEL; 17 18 @end 19 20 @implementation HookUtils 21 22 + (void)hookMehod:(SEL)oldSEL andDef:(SEL)defaultSEL andNew:(SEL)newSEL { 23 NSLog(@"hookMehod"); 24 25 Class oldClass = objc_getClass([@"CTAppDelegate" UTF8String]); 26 27 Class newClass = [HookUtils class]; 28 29 //Add the method to the original Class 30 class_addMethod(oldClass, newSEL, class_getMethodImplementation(newClass, newSEL), nil); 31 class_addMethod(oldClass, oldSEL, class_getMethodImplementation(newClass, defaultSEL),nil); 32 33 Method oldMethod = class_getInstanceMethod(oldClass, oldSEL); 34 assert(oldMethod); 35 Method newMethod = class_getInstanceMethod(oldClass, newSEL); 36 assert(newMethod); 37 method_exchangeImplementations(oldMethod, newMethod); 38 39 } 40 41 + (void)load { 42 NSLog(@"load"); 43 [self hookMehod:@selector(application:didFinishLaunchingWithOptions:) andDef:@selector(defaultApplication:didFinishLaunchingWithOptions:) andNew:@selector(hookedApplication:didFinishLaunchingWithOptions:)]; 44 45 [self hookMehod:@selector(applicationWillEnterForeground:) andDef:@selector(defaultApplicationWillEnterForeground:) andNew:@selector(hookedApplicationWillEnterForeground:)]; 46 } 47 48 49 /*Specific code to go*/ 50 -(BOOL)hookedApplication:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)dic 51 { 52 NSLog(@"applicationDidFinishLaunching"); 53 [self hookedApplication:application didFinishLaunchingWithOptions:dic]; 54 return YES; 55 } 56 57 - (void)hookedApplicationWillResignActive:(UIApplication *)application { 58 [self hookedApplicationWillResignActive:application]; 59 } 60 61 - (void)hookedApplicationDidEnterBackground:(UIApplication *)application { 62 [self hookedApplicationDidEnterBackground:application]; 63 } 64 65 - (void)hookedApplicationWillEnterForeground:(UIApplication *)application { 66 [self hookedApplicationWillEnterForeground:application]; 67 } 68 69 - (void)hookedApplicationDidBecomeActive:(UIApplication *)application { 70 [self hookedApplicationDidBecomeActive:application]; 71 } 72 73 - (void)hookedApplicationWillTerminate:(UIApplication *)application { 74 [self hookedApplicationWillTerminate:application]; 75 } 76 77 /*Alipay's corresponding method*/ 78 - (BOOL)hookedApplication:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { 79 [self hookedApplication:application openURL:url sourceApplication:sourceApplication annotation:annotation]; 80 return YES; 81 } 82 83 84 85 -(BOOL)hookedApplication:(UIApplication*)application handleOpenURL:(NSURL*)url { 86 [self hookedApplication:application handleOpenURL:url]; 87 return YES; 88 } 89 90 91 #pragma default 92 /*default The default does not need to be changed*/ 93 - (BOOL)defaultApplication:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)dic { return YES; 94 } 95 96 - (void)defaultApplicationWillResignActive:(UIApplication *)application {} 97 98 - (void)defaultApplicationDidEnterBackground:(UIApplication *)application {} 99 100 - (void)defaultApplicationWillEnterForeground:(UIApplication *)application {} 101 102 - (void)defaultApplicationDidBecomeActive:(UIApplication *)application {} 103 104 - (void)defaultApplicationWillTerminate:(UIApplication *)application {} 105 106 - (BOOL)defaultApplication:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { 107 return YES; 108 } 109 110 - (BOOL)defaultApplication:(UIApplication *)application handleOpenURL:(NSURL *)url { 111 return YES; 112 } 113 @end
Here are some explanations about this HookUtils:
HookUtils is the implementation of the Hook mechanism of IOS, so it is suitable for all IOS development. Here we only do some processing for the Air application.
Hook mechanism needs to get the class name of the application's implementation life cycle, so that Hook can handle it. If you are the code developed by Xcode engineering, you can easily find the class name. This applies to IOS native, Unity and so on. Cocos engine Because they all use Xcode development tools. However, Air development is based on Flash Builder, not directly related to the Xcode project. The class name CTAppDelegate of Air is found by printing the life cycle class of Air application through code. Then the code is set to be modified by other engines. Of course, you can also get it through the configuration file (Info.plist), so that the code does not need to be modified.
Class oldClass = objc_getClass([@"CTAppDelegate" UTF8String]);
(3) You need to implement your specific code in the hooked ** method, and finally call the header file definition method (void) hookMehod:(SEL) oldSEL and Def:(SEL) defaultSEL and New:(SEL) newSEL in the +(void)load() method to achieve the purpose of Hook;
I quoted that blog above, and when I added the code, I wondered where to call it. Ask an experienced iOS developer to understand that it is not necessary to call the function in HookUtil in other functions. This class method load is the entry, as long as it is declared as a class method and named load, it will be automatically called by the system. After making ane and testing it in demo, demo that could have run flickered back after adding HookUtil to it. By observing log, hookMethod was executed. As a matter of fact, the system automatically calls these codes. The ane has not triggered instantiation through buttons in demo yet.
So I added the log to 34 lines of assert (old method); this line was hung up, the old method was null, but I didn't see what was wrong for a long time, then I suspected that 25 lines of oldClass would also be null, so I added the log NSLog (@ "old class%@), oldClass); if it was null, I would like to review that blog, maybe not CTApp Delegate. What's the name? The blog said that the class name CTAppDelegate for Air was found by printing the life cycle class of the Air application in code. So print it in hookMethod.
1 id delegate = [UIApplication sharedApplication].delegate; 2 NSLog(@"delegate %@", delegate);
But it's still null, and then I wonder if it's too early. It is then placed in an api method of ane and triggered by a button in the application layer demo.
1 FREObject initSDK(FREContext ctx, void *data, uint32_t argc, FREObject argv[]) 2 { 3 id delegate = [UIApplication sharedApplication].delegate; 4 NSLog(@"------------delegate %@", delegate); 5 }
Sure enough, it's no longer null, and the printed name is not CTAppDelegate, but CTAppController. My airsdk is 21, and adobe has changed its name. After changing CTAppDelegate from 25 lines of code to CTAppController, the function in delegate is called correctly and the life cycle delegate is solved.