├── .gitignore ├── AutoCreateSpamCode.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── AutoCreateSpamCode └── main.m └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | -------------------------------------------------------------------------------- /AutoCreateSpamCode.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 52B8CA6B2040FFFA00098D48 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B8CA6A2040FFFA00098D48 /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 52B8CA652040FFFA00098D48 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 52B8CA672040FFFA00098D48 /* AutoCreateSpamCode */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = AutoCreateSpamCode; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 52B8CA6A2040FFFA00098D48 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 52B8CA642040FFFA00098D48 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 52B8CA5E2040FFFA00098D48 = { 42 | isa = PBXGroup; 43 | children = ( 44 | 52B8CA692040FFFA00098D48 /* AutoCreateSpamCode */, 45 | 52B8CA682040FFFA00098D48 /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | 52B8CA682040FFFA00098D48 /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 52B8CA672040FFFA00098D48 /* AutoCreateSpamCode */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | 52B8CA692040FFFA00098D48 /* AutoCreateSpamCode */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 52B8CA6A2040FFFA00098D48 /* main.m */, 61 | ); 62 | path = AutoCreateSpamCode; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | 52B8CA662040FFFA00098D48 /* AutoCreateSpamCode */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = 52B8CA6E2040FFFA00098D48 /* Build configuration list for PBXNativeTarget "AutoCreateSpamCode" */; 71 | buildPhases = ( 72 | 52B8CA632040FFFA00098D48 /* Sources */, 73 | 52B8CA642040FFFA00098D48 /* Frameworks */, 74 | 52B8CA652040FFFA00098D48 /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = AutoCreateSpamCode; 81 | productName = AutoCreateSpamCode; 82 | productReference = 52B8CA672040FFFA00098D48 /* AutoCreateSpamCode */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | 52B8CA5F2040FFFA00098D48 /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0830; 92 | ORGANIZATIONNAME = "曾春军"; 93 | TargetAttributes = { 94 | 52B8CA662040FFFA00098D48 = { 95 | CreatedOnToolsVersion = 8.3.3; 96 | DevelopmentTeam = 68AX242FR4; 97 | ProvisioningStyle = Automatic; 98 | }; 99 | }; 100 | }; 101 | buildConfigurationList = 52B8CA622040FFFA00098D48 /* Build configuration list for PBXProject "AutoCreateSpamCode" */; 102 | compatibilityVersion = "Xcode 3.2"; 103 | developmentRegion = English; 104 | hasScannedForEncodings = 0; 105 | knownRegions = ( 106 | en, 107 | ); 108 | mainGroup = 52B8CA5E2040FFFA00098D48; 109 | productRefGroup = 52B8CA682040FFFA00098D48 /* Products */; 110 | projectDirPath = ""; 111 | projectRoot = ""; 112 | targets = ( 113 | 52B8CA662040FFFA00098D48 /* AutoCreateSpamCode */, 114 | ); 115 | }; 116 | /* End PBXProject section */ 117 | 118 | /* Begin PBXSourcesBuildPhase section */ 119 | 52B8CA632040FFFA00098D48 /* Sources */ = { 120 | isa = PBXSourcesBuildPhase; 121 | buildActionMask = 2147483647; 122 | files = ( 123 | 52B8CA6B2040FFFA00098D48 /* main.m in Sources */, 124 | ); 125 | runOnlyForDeploymentPostprocessing = 0; 126 | }; 127 | /* End PBXSourcesBuildPhase section */ 128 | 129 | /* Begin XCBuildConfiguration section */ 130 | 52B8CA6C2040FFFA00098D48 /* Debug */ = { 131 | isa = XCBuildConfiguration; 132 | buildSettings = { 133 | ALWAYS_SEARCH_USER_PATHS = NO; 134 | CLANG_ANALYZER_NONNULL = YES; 135 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 136 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 137 | CLANG_CXX_LIBRARY = "libc++"; 138 | CLANG_ENABLE_MODULES = YES; 139 | CLANG_ENABLE_OBJC_ARC = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_CONSTANT_CONVERSION = YES; 142 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 143 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 144 | CLANG_WARN_EMPTY_BODY = YES; 145 | CLANG_WARN_ENUM_CONVERSION = YES; 146 | CLANG_WARN_INFINITE_RECURSION = YES; 147 | CLANG_WARN_INT_CONVERSION = YES; 148 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 149 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 150 | CLANG_WARN_UNREACHABLE_CODE = YES; 151 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 152 | CODE_SIGN_IDENTITY = "-"; 153 | COPY_PHASE_STRIP = NO; 154 | DEBUG_INFORMATION_FORMAT = dwarf; 155 | ENABLE_STRICT_OBJC_MSGSEND = YES; 156 | ENABLE_TESTABILITY = YES; 157 | GCC_C_LANGUAGE_STANDARD = gnu99; 158 | GCC_DYNAMIC_NO_PIC = NO; 159 | GCC_NO_COMMON_BLOCKS = YES; 160 | GCC_OPTIMIZATION_LEVEL = 0; 161 | GCC_PREPROCESSOR_DEFINITIONS = ( 162 | "DEBUG=1", 163 | "$(inherited)", 164 | ); 165 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 166 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 167 | GCC_WARN_UNDECLARED_SELECTOR = YES; 168 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 169 | GCC_WARN_UNUSED_FUNCTION = YES; 170 | GCC_WARN_UNUSED_VARIABLE = YES; 171 | MACOSX_DEPLOYMENT_TARGET = 10.13; 172 | MTL_ENABLE_DEBUG_INFO = YES; 173 | ONLY_ACTIVE_ARCH = YES; 174 | SDKROOT = macosx; 175 | }; 176 | name = Debug; 177 | }; 178 | 52B8CA6D2040FFFA00098D48 /* Release */ = { 179 | isa = XCBuildConfiguration; 180 | buildSettings = { 181 | ALWAYS_SEARCH_USER_PATHS = NO; 182 | CLANG_ANALYZER_NONNULL = YES; 183 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 184 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 185 | CLANG_CXX_LIBRARY = "libc++"; 186 | CLANG_ENABLE_MODULES = YES; 187 | CLANG_ENABLE_OBJC_ARC = YES; 188 | CLANG_WARN_BOOL_CONVERSION = YES; 189 | CLANG_WARN_CONSTANT_CONVERSION = YES; 190 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 191 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 192 | CLANG_WARN_EMPTY_BODY = YES; 193 | CLANG_WARN_ENUM_CONVERSION = YES; 194 | CLANG_WARN_INFINITE_RECURSION = YES; 195 | CLANG_WARN_INT_CONVERSION = YES; 196 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 197 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 198 | CLANG_WARN_UNREACHABLE_CODE = YES; 199 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 200 | CODE_SIGN_IDENTITY = "-"; 201 | COPY_PHASE_STRIP = NO; 202 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 203 | ENABLE_NS_ASSERTIONS = NO; 204 | ENABLE_STRICT_OBJC_MSGSEND = YES; 205 | GCC_C_LANGUAGE_STANDARD = gnu99; 206 | GCC_NO_COMMON_BLOCKS = YES; 207 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 208 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 209 | GCC_WARN_UNDECLARED_SELECTOR = YES; 210 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 211 | GCC_WARN_UNUSED_FUNCTION = YES; 212 | GCC_WARN_UNUSED_VARIABLE = YES; 213 | MACOSX_DEPLOYMENT_TARGET = 10.13; 214 | MTL_ENABLE_DEBUG_INFO = NO; 215 | SDKROOT = macosx; 216 | }; 217 | name = Release; 218 | }; 219 | 52B8CA6F2040FFFA00098D48 /* Debug */ = { 220 | isa = XCBuildConfiguration; 221 | buildSettings = { 222 | DEVELOPMENT_TEAM = 68AX242FR4; 223 | MACOSX_DEPLOYMENT_TARGET = 10.10; 224 | PRODUCT_NAME = "$(TARGET_NAME)"; 225 | }; 226 | name = Debug; 227 | }; 228 | 52B8CA702040FFFA00098D48 /* Release */ = { 229 | isa = XCBuildConfiguration; 230 | buildSettings = { 231 | DEVELOPMENT_TEAM = 68AX242FR4; 232 | MACOSX_DEPLOYMENT_TARGET = 10.10; 233 | PRODUCT_NAME = "$(TARGET_NAME)"; 234 | }; 235 | name = Release; 236 | }; 237 | /* End XCBuildConfiguration section */ 238 | 239 | /* Begin XCConfigurationList section */ 240 | 52B8CA622040FFFA00098D48 /* Build configuration list for PBXProject "AutoCreateSpamCode" */ = { 241 | isa = XCConfigurationList; 242 | buildConfigurations = ( 243 | 52B8CA6C2040FFFA00098D48 /* Debug */, 244 | 52B8CA6D2040FFFA00098D48 /* Release */, 245 | ); 246 | defaultConfigurationIsVisible = 0; 247 | defaultConfigurationName = Release; 248 | }; 249 | 52B8CA6E2040FFFA00098D48 /* Build configuration list for PBXNativeTarget "AutoCreateSpamCode" */ = { 250 | isa = XCConfigurationList; 251 | buildConfigurations = ( 252 | 52B8CA6F2040FFFA00098D48 /* Debug */, 253 | 52B8CA702040FFFA00098D48 /* Release */, 254 | ); 255 | defaultConfigurationIsVisible = 0; 256 | }; 257 | /* End XCConfigurationList section */ 258 | }; 259 | rootObject = 52B8CA5F2040FFFA00098D48 /* Project object */; 260 | } 261 | -------------------------------------------------------------------------------- /AutoCreateSpamCode.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AutoCreateSpamCode/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AutoCreateSpamCode 4 | // 5 | // Created by zengchunjun on 2018/2/24. 6 | // Copyright © 2018年 曾春军. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //引入的头文件 12 | NSString *PublicHeader = @"APublicHeader.h"; 13 | //外部(delegate)调用的类 14 | NSString *publicCallClassName = @"ASpamCode_Public"; 15 | //垃圾代码输出路径 16 | NSString *outDirectory = @"/Users/zengchunjun/workspace/SDK_Tools/SpamCode2"; 17 | //NSString *outDirectory = @"/Users/zengchunjun/Desktop/123456/123456/Test"; 18 | 19 | 20 | void generateSpamCodeFile(); //生成垃圾代码 21 | 22 | NSString * getRandromString(); 23 | 24 | NSString *getRandomClassName(NSString *prefixStr);//获取随机类名 25 | 26 | NSString *beforeClass = nil; //上一个类名 27 | NSString *beforeClassMethod = nil; //上一个类的方法名 前半段 28 | NSString *beforeClassArg = nil;//上一个类的参数 后半段方法名 29 | 30 | 31 | 32 | void runSystemCommand(NSString *cmd) 33 | { 34 | [[NSTask launchedTaskWithLaunchPath:@"/bin/sh" 35 | arguments:@[@"-c", cmd]] 36 | waitUntilExit]; 37 | } 38 | 39 | int main(int argc, const char * argv[]) { 40 | @autoreleasepool { 41 | // insert code here... 42 | 43 | NSArray *arguments = [[NSProcessInfo processInfo] arguments]; 44 | for (int i = 0; i < arguments.count; i++) { 45 | NSLog(@"arguments[%d]:%@",i,arguments[i]); 46 | } 47 | 48 | int count = 300; 49 | while (count > 0) { 50 | NSString *className = getRandomClassName(@"WHH_");//随机字符串 51 | 52 | generateSpamCodeFile(outDirectory,className); 53 | 54 | count--; 55 | } 56 | 57 | generateSpamCodeFile(outDirectory, publicCallClassName);//生成一个唯一的类,用来外界调用 58 | 59 | 60 | // runSystemCommand(@"/Users/zengchunjun/Desktop/123456/test.rb"); 61 | 62 | } 63 | return 0; 64 | } 65 | 66 | #pragma mark:************公共方法**************** 67 | 68 | #pragma mark:获取随机指定位数的字符串 小写 69 | NSString * getRandomStringsWithLow(int length){ 70 | char data[length]; 71 | 72 | for (int x=0;x < length; data[x++] = (char)('A' + (arc4random_uniform(26)))); 73 | 74 | NSString *randomStr = [[NSString alloc] initWithBytes:data length:length encoding:NSUTF8StringEncoding]; 75 | 76 | NSString *string = [NSString stringWithFormat:@"%@",randomStr]; 77 | 78 | return string; 79 | } 80 | #pragma mark:随机获取类前缀 81 | NSString *getClassPrefixString(){ 82 | 83 | NSString *string = @"BAG_Class_"; 84 | NSArray *strings = @[@"A_A02_E",@"B_A01_F",@"C_A14_G",@"D_A13_H",@"E_A03_I",@"F_A04_J",@"G_A15_K",@"H_A05_L",@"I_A14_M",@"J_A06_N",@"K_A11_O",@"L_A15_P",@"M_A13_Q",@"N_A07_U",@"O_A12_W",@"P_A13_V",@"Q_A14_Y",@"S_A15_Z",@"T_16_S",@"Y_A17_T",@"Z_A18_A"]; 85 | string = strings[(int)(arc4random() % strings.count)]; 86 | 87 | return string; 88 | } 89 | 90 | #pragma mark:随机获取方法名前缀 91 | NSString *getMethodPrefixString(){ 92 | 93 | NSString *string = @"BAG_method_"; 94 | NSArray *strings = @[@"bpg_X01_",@"bag_X11_",@"bmg_X12_",@"qpg_X03_",@"fag_X05_",@"wme_X13_",@"tpy_X06_",@"uad_X15_",@"msg_X13_",@"msb_X14_",@"nsg_X18_",@"okg_X12_",@"sbg_X19_",@"snk_X15_",@"ssw_X11_",@"ac_X19_",@"ef_X20_",@"cd_X09_",@"of_X12_",@"tt_X01_",@"st_X08_"]; 95 | string = strings[(int)(arc4random() % strings.count)]; 96 | return string; 97 | } 98 | 99 | 100 | 101 | #pragma mark:获取随机 类名 102 | NSString *getRandomClassName(NSString *prefixStr) 103 | { 104 | int length = (arc4random() % 6) + 2; 105 | 106 | //获取随机字符串 107 | NSString *randomStr = getRandomStringsWithLow(length); 108 | 109 | NSString *string = [NSString stringWithFormat:@"%@_%@",randomStr,getRandromString()]; 110 | string = [[string lowercaseString] capitalizedString];//转换首字母大写 111 | 112 | // return [getClassPrefixString() stringByAppendingString:string]; 113 | string = [prefixStr stringByAppendingString:string]; 114 | return string; 115 | } 116 | 117 | #pragma mark:随机获取字符串 118 | NSString * getRandromString(){ 119 | 120 | NSString *string = @"temp"; 121 | 122 | NSArray *strings = @[@"parameter",@"viewController",@"apple",@"wangyi",@"view",@"tableviewController",@"tencent",@"abcd",@"game",@"flipped",@"crush",@"nostalgia",@"viewController",@"ephemeral",@"effervescence",@"evanescence",@"rendezvous",@"reminisce",@"bazinga",@"viewController",@"serendipity",@"mellifluous",@"petrichor",@"viewController",@"eudemonia",@"mother",@"passion",@"eternity",@"fantastic",@"freedom",@"tranquility",@"sweetheart",@"gorgeous",@"viewController",@"sophisticated",@"renaissance",@"viewController",@"cosmopolitan",@"bumblebee",@"umbrella",@"viewController",@"flabbergasted",@"hippopotamus",@"viewController",@"smashing",@"loquacious",@"smithereens",@"hodgepodge",@"shipshape",@"viewController",@"viewController",@"explosion",@"fuselage",@"zing",@"believe",@"Smithereens",@"final",@"Galaxy",@"Butterfly",@"Rainbow",@"Destiny"]; 123 | 124 | string = strings[(int)(arc4random() % strings.count)]; 125 | 126 | // string = [string stringByAppendingString:[NSString stringWithFormat:@"_X%.2d_",(int)(arc4random() % 18) + 1]]; 127 | 128 | return string; 129 | } 130 | 131 | #pragma mark:生成随机注释字符串 132 | NSString * getRandromNoteString(){ 133 | 134 | NSString *string = @"登录,注册,测试"; 135 | 136 | NSArray *strings = @[@"使用iOS原生来实现",@"监听web内容加载进度、是否加载完成",@"先创建配置对象,用于做一些配置",@"都使用默认的就可以了",@"在iOS上默认为NO,表示不能自动通过窗口打开",@"其实我们没有必要去创建它,因为它根本没有属性和方法",@"WKUserContentController是用于给JS注入对象的",@"传数据统一通过body传,可以是多种类型",@"只支持NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull类型",@"通过JS与webview内容交互",@"当JS通过AppModel发送数据到iOS端时,会在代理中收到",@"可以注入多个名称(JS对象),用于区分功能",@"这里只是监听loading、title、estimatedProgress属性",@"链接跳转、接收响应、在导航开始、成功、失败等时要做些处理,就可以通过实现相关的代理方法",@"页面内容到达main frame时回调",@"导航完成时,会回调(也就是页面载入完成了)",@"对于HTTPS的都会触发此代理,如果不要求验证,传默认就行",@"9.0才能使用,web内容处理中断时会触发",@"这样一个 drawable 文件则可以通过它的名字识别",@"代码的注释经常被人忽略,其实注解有很多好处",@"方便使用,会提示注解说明",@"方便日后自己阅读代码",@"方便别人阅读自己代码",@"降低后期维护成本",@"可以快速生成开发文档",@"代码的注释方式五花八门",@"好的代码注解应该是这样的",@"可以使用[Option + 单击]查看注解",@"此方法只有头文件中属性/方法的注解才会提示",@"首先我们来看一下html部分的代码",@"首先要实例化一个WKWebView",@"这里如果没有JS调用OC的功能的话",@"需要配置WKWebViewConfiguration",@"对于WKWebView的实例化这里就不再赘述",@"我们在需要调用JS方法的位置加上下面代码",@"这样就能实现OC调用JS 方法",@"但是当我们运行的时候我们会发现",@"在前面的WKWebView使用之WKUIDelegate中",@"html的弹窗将不会再显示,那想显示弹窗,我们需要实现WKUIDelegate的代理方法",@"接下来实现代理方法",@"弹窗就会显示出来了,而且是iOS自己的原生弹窗",@"看一下iPhone X的模拟器样式",@"纯代码适配iPhone X脚底",@"纯代码的宽高比适配",@"UIBarButtonItem的适配",@"iPhone X的设计图",@"无线真机测试",@"真机地图适配",@"表示设置layer上面设置图片的的拉伸方式",@"表示当前layer设置的图片像素尺寸和试图大小的比例",@"layer上面显示的图片就是寄宿图片左上角四分之一",@"定义一个固定的边框和一个在图层上面可以拉伸的区域",@"需要设置阴影的时候,必须设置shadowOpacity的值是在0.0到1.0之间",@"当设置阴影和裁剪的时候,会把阴影的裁剪掉",@"shadowRadius控制着阴影的模糊度,当为0的时候,阴影和layer就会有一个明显的分界线,当值越来越大的时候,就会越来越自然和模糊",@"layer上面的触摸判断hitTest来判断",@"shadowPath设置阴影的图形",@"mask遮盖来设置图层显示的形状",@"layer三种拉伸过滤模式"]; 137 | 138 | NSString *temp1 = strings[(int)(arc4random() % strings.count)]; 139 | NSString *temp2 = strings[(int)(arc4random() % strings.count)]; 140 | 141 | string = [temp1 stringByAppendingString:temp2]; 142 | 143 | return string; 144 | } 145 | 146 | #pragma mark:获取当前时间string格式 147 | NSString * getCurrentDateString(){ 148 | 149 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 150 | formatter.dateFormat = @"yyyy/MM/dd"; 151 | 152 | return [formatter stringFromDate:[NSDate date]]; 153 | } 154 | #pragma mark:获取当前年 155 | NSString * getCurrentYearString(){ 156 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 157 | formatter.dateFormat = @"yyyy"; 158 | 159 | return [formatter stringFromDate:[NSDate date]]; 160 | } 161 | 162 | 163 | 164 | 165 | #pragma mark:方法名集合 166 | NSSet * getMethodNamesSet(){ 167 | 168 | NSMutableSet *set = [NSMutableSet set]; 169 | 170 | int count = 10; 171 | while (count > 0) { 172 | 173 | NSString *methodPre = getMethodPrefixString(); 174 | NSString *methodName = [methodPre stringByAppendingString:getRandromString()]; 175 | if (methodName == nil || [methodName isEqualToString:@""]) { 176 | methodName = @"bird_method_"; 177 | } 178 | 179 | methodName = [@"G9X_" stringByAppendingString:methodName]; 180 | methodName = [methodName stringByAppendingString:@"_A8P"]; 181 | 182 | [set addObject:methodName]; 183 | count--; 184 | } 185 | 186 | 187 | 188 | return set; 189 | } 190 | 191 | 192 | 193 | 194 | #pragma mark : 生成垃圾代码 195 | 196 | static NSString *const kHClassFileTemplate = @"\ 197 | // \n\ 198 | // %@\n\ 199 | // Created by apple on %@\n\ 200 | // \n\ 201 | // Copyright © %@年 apple. All rights reserved.\n\ 202 | //\n\n\n\ 203 | %@\n\ 204 | @interface %@ : NSObject \n\ 205 | %@\n\ 206 | @end\n"; 207 | static NSString *const kMClassFileTemplate = @"\ 208 | // \n\ 209 | // %@\n\ 210 | // Created by apple on %@\n\ 211 | // \n\ 212 | // Copyright © %@年 apple. All rights reserved.\n\ 213 | //\n\n\n\ 214 | #import \"%@.h\"\n\ 215 | #import %@ \n\ 216 | @implementation %@ \n\ 217 | %@\n\ 218 | @end\n"; 219 | 220 | 221 | #pragma mark:tools 222 | //创建文件夹 223 | void createDirectory(NSString *outDirectory){ 224 | //创建目录 225 | NSFileManager *fileManager = [NSFileManager defaultManager]; 226 | if (![fileManager fileExistsAtPath:outDirectory isDirectory:NO]) { 227 | [fileManager createDirectoryAtPath:outDirectory withIntermediateDirectories:YES attributes:nil error:nil]; 228 | } 229 | } 230 | 231 | //创建文件 232 | void createFile(NSString *filePath,NSString *initData){ 233 | NSFileManager *fileManager = [NSFileManager defaultManager]; 234 | if (![fileManager fileExistsAtPath:filePath isDirectory:NO]) { 235 | //第一次创建写入importString 236 | [initData writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil]; 237 | } 238 | } 239 | 240 | //在文件末尾换号写入数据 241 | void writeDataToEndOfFile(NSString *filePath,NSString *dataString){ 242 | NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath]; 243 | if (fileHandle == nil) { 244 | NSLog(@"Open of file for writing failed"); 245 | }else{ 246 | [fileHandle seekToEndOfFile]; 247 | [fileHandle writeData:[dataString dataUsingEncoding:NSUTF8StringEncoding]]; 248 | [fileHandle closeFile]; 249 | } 250 | } 251 | 252 | 253 | #pragma mark:生成有调用关系的辣鸡代码 254 | 255 | void generateSpamCodeFile(NSString *outDirectory,NSString *className){ 256 | 257 | NSString *importString = @"#import \n"; 258 | 259 | //创建输出目录 260 | createDirectory(outDirectory); 261 | 262 | //一个.h头文件 263 | NSString *headerFilePath = [outDirectory stringByAppendingPathComponent:PublicHeader]; 264 | createFile(headerFilePath, importString); //创建导入所有 .h 的头文件 265 | 266 | NSString *classH = [className stringByAppendingString:@".h"]; 267 | NSString *importClassH = [NSString stringWithFormat:@"#import \"%@\" \n",classH]; 268 | 269 | //往对外的头文件中写入 #import "xxxxx.h"数据 270 | writeDataToEndOfFile(headerFilePath, importClassH); 271 | 272 | 273 | //初始化一个.h .m文件的内容 274 | NSMutableString *hFileMethodsString = [NSMutableString string]; 275 | NSMutableString *mFileMethodsString = [NSMutableString string]; 276 | 277 | //方法的第二个参数名,与第二个参数前的方法名相同 278 | NSString *gOutParameterName = getMethodPrefixString(); 279 | 280 | 281 | NSString *beforeMethod = nil; //正在写入方法的上一个方法(本类中) 282 | NSInteger index = 0; //正在写入第 index 个方法 283 | 284 | //每个类的方法集合,对外的类只用一个方法,用来调用 285 | NSSet *methodSets = getMethodNamesSet(); 286 | if ([className isEqualToString:publicCallClassName]) { 287 | methodSets = [NSSet setWithObjects:@"main_X10_Call", nil]; 288 | 289 | } 290 | 291 | NSInteger length = methodSets.count; //每个类的方法数 292 | for (NSString *methodName in methodSets) { 293 | //.h文件中新增注释 // mark: 294 | [hFileMethodsString appendFormat:@"//mark:%@ \n %@ (void)%@:(NSString *)%@ %@:(NSString *)%@;\n\n",getRandromNoteString(), @"+", methodName,@"arg1",gOutParameterName,gOutParameterName]; 295 | 296 | 297 | //.m文件中新增注释 #pragma mark: 298 | [mFileMethodsString appendFormat:@"#pragma mark:%@ \n %@ (void)%@:(NSString *)%@ %@:(NSString *)%@ {\n",getRandromNoteString(), @"+", methodName,@"arg1",gOutParameterName,gOutParameterName]; 299 | 300 | //方法内的代码 301 | [mFileMethodsString appendFormat:@" NSLog(@\"function:%%s line:\", %@);\n\n", @"__FUNCTION__"]; 302 | [mFileMethodsString appendFormat:@" [%@ substringFromIndex:1];\n\n", gOutParameterName]; 303 | [mFileMethodsString appendFormat:@" [%@ isEqualToString:@\"%@\"];\n\n", gOutParameterName,getRandromString()]; 304 | [mFileMethodsString appendFormat:@" NSLog(@\"%%@===%%@\", %@,%@);\n\n", gOutParameterName,[NSString stringWithFormat:@"@\"%@\"",getRandromString()]]; 305 | 306 | //文件内 不是第一个方法 用self调用上一个方法 307 | if (beforeMethod) { 308 | 309 | [mFileMethodsString appendFormat:@" //调用%@ \n [self %@:%@ %@:%@];\n\n", beforeMethod,beforeMethod,@"arg1",gOutParameterName,gOutParameterName]; 310 | 311 | if (index == length - 1) { //最后一个方法 312 | if (beforeClass && beforeClassMethod && beforeClassArg) {//不是生成的第一个类,开始调用上一个类的第一个方法 313 | [mFileMethodsString appendFormat:@" //调用%@ \n [%@ %@:%@ %@:%@];\n\n", beforeClass,beforeClass,beforeClassMethod,@"arg1",beforeClassArg,gOutParameterName]; 314 | } 315 | 316 | beforeClassMethod = methodName;//上一个类的最后一个方法名 317 | // beforeClass 在写入文件后再赋值 318 | beforeClassArg = gOutParameterName;//上个类的最后一个方法的参数名 319 | 320 | } 321 | 322 | } 323 | 324 | //对 对外的那个类单独处理 325 | if ([className isEqualToString:publicCallClassName]) { 326 | if (index == length - 1) { //最后一个方法 327 | if (beforeClass && beforeClassMethod && beforeClassArg) {//不是生成的第一个类,开始调用上一个类的第一个方法 328 | [mFileMethodsString appendFormat:@" //调用%@ \n [%@ %@:%@ %@:%@];\n\n", beforeClass,beforeClass,beforeClassMethod,@"arg1",beforeClassArg,gOutParameterName]; 329 | } 330 | 331 | } 332 | } 333 | 334 | //.m 类文件 结尾 335 | [mFileMethodsString appendString:@"}\n\n"]; 336 | 337 | beforeMethod = methodName;//赋值上一个方法名 338 | 339 | index++; //方法数递增 340 | } 341 | 342 | 343 | //写.h文件 344 | NSString *fileName = [NSString stringWithFormat:@"%@.h", className]; 345 | NSString *fileContent = [NSString stringWithFormat:kHClassFileTemplate, fileName,getCurrentDateString(),getCurrentYearString(), importString, className, hFileMethodsString]; 346 | [fileContent writeToFile:[outDirectory stringByAppendingPathComponent:fileName] atomically:YES encoding:NSUTF8StringEncoding error:nil]; 347 | 348 | //插入要导入的上一个类的头文件 349 | NSString *importClass = @""; 350 | if (beforeClass) { 351 | importClass = [NSString stringWithFormat:@"\"%@\"",[beforeClass stringByAppendingString:@".h"]]; 352 | } 353 | //写.m文件 354 | fileName = [NSString stringWithFormat:@"%@.m", className]; 355 | fileContent = [NSString stringWithFormat:kMClassFileTemplate, fileName, getCurrentDateString(),getCurrentYearString(), className,importClass, className, mFileMethodsString]; 356 | [fileContent writeToFile:[outDirectory stringByAppendingPathComponent:fileName] atomically:YES encoding:NSUTF8StringEncoding error:nil]; 357 | 358 | 359 | //重新赋值 上一个类名 360 | beforeClass = className;//赋值上一个类名 361 | } 362 | 363 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 使用说明: 4 | main.m文件最顶部参数设定,修改输出路径 5 | 6 | //引入的头文件 7 | NSString *PublicHeader = @"APublicHeader.h"; 8 | //外部(delegate)调用的类 9 | NSString *publicCallClassName = @"ASpamCode_Public"; 10 | //垃圾代码输出路径 11 | NSString *outDirectory = @"/Users/zengchunjun/workspace/SDK_Tools/SpamCode2"; 12 | 13 | 14 | 在Xcode工程 delegate中添加如下方法 15 | 16 | - (void)addSpamCodeMethod 17 | { 18 | CFAbsoluteTime startTime =CFAbsoluteTimeGetCurrent(); 19 | 20 | int random = 1234567; 21 | if (random % 2 == 0) { //没有必要调用 22 | [ASpamCode_Public main_X10_Call:@"ios" bmg_X12_:@"android"]; 23 | } 24 | 25 | CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime); 26 | 27 | NSLog(@"Linked in %f ms", linkTime *1000.0); 28 | } 29 | 30 | 并在didFinishLaunchingWithOptions方法中调用 31 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 32 | { 33 | 34 | 35 | 36 | [self addSpamCodeMethod];//添加额外的code 37 | 38 | return YES; 39 | } --------------------------------------------------------------------------------