├── .gitignore ├── App Plugin ├── App Plugin.xctemplate │ ├── Info.plist │ ├── PrefixHeader.pch │ ├── TemplateIcon.icns │ ├── TemplateInfo.plist │ ├── ___PACKAGENAME___.h │ ├── ___PACKAGENAME___.m │ └── ___PACKAGENAME___Header.h └── Cocoa App Plugin.xctemplate │ ├── Info.plist │ ├── PrefixHeader.pch │ ├── TemplateIcon.icns │ ├── TemplateInfo.plist │ ├── ___PACKAGENAME___.h │ ├── ___PACKAGENAME___.m │ └── ___PACKAGENAME___Header.h ├── Example └── TestPlugin │ ├── Podfile │ ├── Podfile.lock │ ├── Test.app │ ├── Base.lproj │ │ ├── LaunchScreen.storyboardc │ │ │ ├── 01J-lp-oVM-view-Ze5-6b-2t3.nib │ │ │ ├── Info.plist │ │ │ └── UIViewController-01J-lp-oVM.nib │ │ └── Main.storyboardc │ │ │ ├── BYZ-38-t0r-view-8bC-Xf-vdC.nib │ │ │ ├── Info.plist │ │ │ └── UIViewController-BYZ-38-t0r.nib │ ├── Info.plist │ ├── PkgInfo │ ├── Test │ └── _CodeSignature │ │ └── CodeResources │ ├── TestPlugin.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── TestPlugin.xcworkspace │ └── contents.xcworkspacedata │ └── TestPlugin │ ├── Info.plist │ ├── PrefixHeader.pch │ ├── TestPlugin.h │ ├── TestPlugin.m │ └── TestPluginHeader.h └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # svn 2 | *.svn* 3 | 4 | # mac 5 | *.DS_Store* 6 | *._* 7 | *.Spotlight-V100 8 | *.Trashes 9 | *ehthumbs.db 10 | *Thumbs.db 11 | 12 | # Xcode 13 | */build/ 14 | *.pbxuser 15 | !default.pbxuser 16 | *.mode1v3 17 | !default.mode1v3 18 | *.mode2v3 19 | !default.mode2v3 20 | *.perspectivev3 21 | !default.perspectivev3 22 | xcuserdata 23 | *.xccheckout 24 | *.moved-aside 25 | DerivedData 26 | *.hmap 27 | *.ipa 28 | *.xcuserstate 29 | 30 | # generated files 31 | */bin/* 32 | */gen/* 33 | 34 | # built application files 35 | *.apk 36 | *.ap_ 37 | 38 | # files for the dex VM 39 | *.dex 40 | 41 | # Java class files 42 | *.class 43 | 44 | # Local configuration file (sdk path, etc) 45 | local.properties 46 | 47 | # Eclipse project files 48 | #.classpath 49 | #.project 50 | #.settings 51 | 52 | # Proguard folder generated by Eclipse 53 | proguard/ 54 | 55 | # Intellij project files 56 | *.iml 57 | *.ipr 58 | *.iws 59 | .idea/ 60 | 61 | #Pod 62 | *Pods/ 63 | -------------------------------------------------------------------------------- /App Plugin/App Plugin.xctemplate/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /App Plugin/App Plugin.xctemplate/PrefixHeader.pch: -------------------------------------------------------------------------------- 1 | // 2 | // ___FILENAME___ 3 | // ___PROJECTNAME___ 4 | // 5 | // Created by ___FULLUSERNAME___ on ___DATE___. 6 | //___COPYRIGHT___ 7 | // 8 | 9 | #ifndef ___PACKAGENAME____PrefixHeader_pch 10 | #define ___PACKAGENAME____PrefixHeader_pch 11 | 12 | #import 13 | #import 14 | #import 15 | #import 16 | 17 | #define CBGetClass(classname) objc_getClass(#classname) 18 | #define CBRegisterClass(superclassname, subclassname) { Class class = objc_allocateClassPair(CBGetClass(superclassname), #subclassname, 0);objc_registerClassPair(class); } 19 | #define CBHookInstanceMethod(classname, ori_sel, new_sel) { NSError *error; [CBGetClass(classname) jr_swizzleMethod:ori_sel withMethod:new_sel error:&error]; if(error) NSLog(@"%@", error); } 20 | #define CBHookClassMethod(classname, ori_sel, new_sel) { NSError *error; [CBGetClass(classname) jr_swizzleClassMethod:ori_sel withClassMethod:new_sel error:&error]; if(error) NSLog(@"%@", error); } 21 | #define CBGetInstanceValue(obj, valuename) object_getIvar(obj, class_getInstanceVariable([obj class], #valuename)) 22 | #define CBSetInstanceValue(obj, valuename, value) object_setIvar(obj, class_getInstanceVariable([obj class], #valuename), value) 23 | 24 | #endif 25 | 26 | -------------------------------------------------------------------------------- /App Plugin/App Plugin.xctemplate/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlayshChen/XcodeAppPluginTemplate/9014d1d3b77b86f7111db3c7a8f4e46a8c26dc74/App Plugin/App Plugin.xctemplate/TemplateIcon.icns -------------------------------------------------------------------------------- /App Plugin/App Plugin.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Kind 6 | Xcode.Xcode3.ProjectTemplateUnitKind 7 | Identifier 8 | com.corbin.pluginFramework 9 | Concrete 10 | 11 | Description 12 | This template builds a plugin framework that links against the Foundation and UIKit frameworks. 13 | Platforms 14 | 15 | com.apple.platform.iphoneos 16 | 17 | Ancestors 18 | 19 | com.apple.dt.unit.frameworkBase 20 | 21 | Project 22 | 23 | SharedSettings 24 | 25 | TARGETED_DEVICE_FAMILY 26 | 1,2 27 | GCC_WARN_ABOUT_MISSING_PROTOTYPES 28 | YES 29 | GCC_WARN_UNUSED_VARIABLE 30 | YES 31 | GCC_WARN_ABOUT_RETURN_TYPE 32 | YES 33 | GCC_C_LANGUAGE_STANDARD 34 | gnu99 35 | EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES 36 | *.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj 37 | IPHONEOS_DEPLOYMENT_TARGET 38 | latest_iphoneos 39 | 40 | SDK 41 | iphoneos 42 | Configurations 43 | 44 | Debug 45 | 46 | VALIDATE_PRODUCT 47 | NO 48 | GCC_OPTIMIZATION_LEVEL 49 | 0 50 | GCC_PREPROCESSOR_DEFINITIONS 51 | DEBUG=1 $(inherited) 52 | GCC_SYMBOLS_PRIVATE_EXTERN 53 | NO 54 | COPY_PHASE_STRIP 55 | NO 56 | GCC_DYNAMIC_NO_PIC 57 | NO 58 | 59 | Release 60 | 61 | COPY_PHASE_STRIP 62 | YES 63 | VALIDATE_PRODUCT 64 | YES 65 | 66 | 67 | 68 | Targets 69 | 70 | 71 | ProductType 72 | com.apple.product-type.framework 73 | TargetIdentifier 74 | plugin 75 | SharedSettings 76 | 77 | INSTALL_PATH 78 | $(LOCAL_LIBRARY_DIR)/Frameworks 79 | SKIP_INSTALL 80 | YES 81 | DYLIB_COMPATIBILITY_VERSION 82 | 1 83 | DYLIB_CURRENT_VERSION 84 | 1 85 | DYLIB_INSTALL_NAME_BASE 86 | @rpath 87 | DEFINES_MODULE 88 | YES 89 | GCC_PRECOMPILE_PREFIX_HEADER 90 | YES 91 | GCC_PREFIX_HEADER 92 | ___PACKAGENAME___/PrefixHeader.pch 93 | CODE_SIGN_IDENTITY 94 | iPhone Developer 95 | 96 | BuildPhases 97 | 98 | 99 | 100 | Name 101 | ___VARIABLE_TargetAppName___ 102 | ProductType 103 | com.apple.product-type.application 104 | SharedSettings 105 | 106 | INFOPLIST_FILE 107 | ___PACKAGENAME___/Info.plist 108 | PRODUCT_NAME 109 | ___VARIABLE_TargetAppName___ 110 | PRODUCT_BUNDLE_IDENTIFIER 111 | ___VARIABLE_TargetAppBundleId___ 112 | DEFINES_MODULE 113 | YES 114 | GCC_PRECOMPILE_PREFIX_HEADER 115 | YES 116 | CODE_SIGN_IDENTITY 117 | iPhone Developer 118 | 119 | BuildPhases 120 | 121 | 122 | Class 123 | ShellScript 124 | ShellPath 125 | /bin/sh 126 | ShowEnvVarsInLog 127 | true 128 | ShellScript 129 | APP_PATH="${PROJECT_DIR}/___VARIABLE_TargetAppName___.app" 130 | FRAMEWORK_PATH="${BUILT_PRODUCTS_DIR}/___PACKAGENAME___.framework" 131 | BUNDLE_IDENTIFIER="___VARIABLE_TargetAppBundleId___" 132 | 133 | APP_NAME="___VARIABLE_TargetAppName___.app" 134 | APP_EXECUTABLE="___VARIABLE_TargetAppName___" 135 | 136 | FRAMEWORK_NAME=$(basename "$FRAMEWORK_PATH") 137 | FRAMEWORK_EXECUTABLE="${FRAMEWORK_NAME}/${FRAMEWORK_NAME%.*}" 138 | 139 | TEMP_DIR=$(mktemp -d) 140 | cd ${TEMP_DIR} 141 | 142 | cp -r "${APP_PATH}" ${TEMP_DIR}/ 143 | mkdir -p "${APP_NAME}/Frameworks" 144 | cp -r "${FRAMEWORK_PATH}" "${APP_NAME}/Frameworks" 145 | 146 | plutil -replace CFBundleIdentifier -string ${BUNDLE_IDENTIFIER} "${APP_NAME}/Info.plist" 147 | insert_dylib --all-yes @executable_path/Frameworks/${FRAMEWORK_EXECUTABLE} "${APP_NAME}/${APP_EXECUTABLE}" 148 | mv "${APP_NAME}/${APP_EXECUTABLE}_patched" "$APP_NAME/${APP_EXECUTABLE}" 149 | chmod +x "${APP_NAME}/${APP_EXECUTABLE}" 150 | 151 | rm -rf "${APP_NAME}/PlugIns" 152 | rm -rf "${APP_NAME}/Watch" 153 | 154 | rm -rf "${BUILT_PRODUCTS_DIR}/${APP_NAME}" 155 | mv "${APP_NAME}" ${BUILT_PRODUCTS_DIR} 156 | rm -rf ${TEMP_DIR} 157 | 158 | 159 | Dependencies 160 | 161 | plugin 162 | 163 | 164 | 165 | Options 166 | 167 | 168 | Identifier 169 | TargetAppName 170 | Required 171 | 172 | Name 173 | Target App Name: 174 | Description 175 | Target App Name. 176 | Type 177 | text 178 | Placeholder 179 | AppStore 180 | 181 | 182 | Identifier 183 | TargetAppBundleId 184 | Required 185 | 186 | Name 187 | Target App Bundle Id: 188 | Description 189 | Target App Bundle Id. 190 | Type 191 | text 192 | Placeholder 193 | com.apple.appStore 194 | 195 | 196 | Nodes 197 | 198 | ___PACKAGENAME___.h 199 | ___PACKAGENAME___.m 200 | ___PACKAGENAME___Header.h 201 | PrefixHeader.pch 202 | ../Podfile 203 | Info.plist 204 | 205 | Definitions 206 | 207 | ../Podfile 208 | 209 | Group 210 | 211 | Supporting Files 212 | 213 | Path 214 | Podfile 215 | Beginning 216 | platform :ios, '8.0' 217 | 218 | target '___PACKAGENAME___' do 219 | pod 'JRSwizzle', '~> 1.0' 220 | pod 'fishhook', '~> 0.2' 221 | end 222 | End 223 | 224 | 225 | ___PACKAGENAME___.h 226 | 227 | Path 228 | ___PACKAGENAME___.h 229 | 230 | ___PACKAGENAME___.m 231 | 232 | Path 233 | ___PACKAGENAME___.m 234 | 235 | ___PACKAGENAME___Header.h 236 | 237 | Path 238 | ___PACKAGENAME___Header.h 239 | 240 | PrefixHeader.pch 241 | 242 | Group 243 | 244 | Supporting Files 245 | 246 | Path 247 | PrefixHeader.pch 248 | 249 | Info.plist 250 | 251 | Group 252 | 253 | Supporting Files 254 | 255 | Path 256 | Info.plist 257 | 258 | 259 | 260 | 261 | -------------------------------------------------------------------------------- /App Plugin/App Plugin.xctemplate/___PACKAGENAME___.h: -------------------------------------------------------------------------------- 1 | // 2 | // ___FILENAME___ 3 | // ___PACKAGENAME___ 4 | // 5 | // Created by ___FULLUSERNAME___ on ___DATE___. 6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | -------------------------------------------------------------------------------- /App Plugin/App Plugin.xctemplate/___PACKAGENAME___.m: -------------------------------------------------------------------------------- 1 | // 2 | // ___FILENAME___ 3 | // ___PACKAGENAME___ 4 | // 5 | // Created by ___FULLUSERNAME___ on ___DATE___. 6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved. 7 | // 8 | 9 | #import "___FILEBASENAME___.h" 10 | #import "___PACKAGENAME___Header.h" 11 | 12 | #pragma mark - Plugin 13 | 14 | @implementation NSObject (___PACKAGENAME___) 15 | 16 | @end 17 | 18 | @implementation UIView (___PACKAGENAME___) 19 | 20 | @end 21 | 22 | @implementation UIViewController (___PACKAGENAME___) 23 | 24 | @end 25 | 26 | static void __attribute__((constructor)) initialize(void) { 27 | NSLog(@"++++++++ ___FILEBASENAME___ loaded ++++++++"); 28 | } -------------------------------------------------------------------------------- /App Plugin/App Plugin.xctemplate/___PACKAGENAME___Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // ___FILENAME___ 3 | // ___PACKAGENAME___ 4 | // 5 | // Created by ___FULLUSERNAME___ on ___DATE___. 6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | -------------------------------------------------------------------------------- /App Plugin/Cocoa App Plugin.xctemplate/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /App Plugin/Cocoa App Plugin.xctemplate/PrefixHeader.pch: -------------------------------------------------------------------------------- 1 | // 2 | // ___FILENAME___ 3 | // ___PROJECTNAME___ 4 | // 5 | // Created by ___FULLUSERNAME___ on ___DATE___. 6 | //___COPYRIGHT___ 7 | // 8 | 9 | #ifndef ___PACKAGENAME____PrefixHeader_pch 10 | #define ___PACKAGENAME____PrefixHeader_pch 11 | 12 | #import 13 | #import 14 | #import 15 | 16 | #define CBGetClass(classname) objc_getClass(#classname) 17 | #define CBRegisterClass(superclassname, subclassname) { Class class = objc_allocateClassPair(CBGetClass(superclassname), #subclassname, 0);objc_registerClassPair(class); } 18 | #define CBHookInstanceMethod(classname, ori_sel, new_sel) { NSError *error; [CBGetClass(classname) jr_swizzleMethod:ori_sel withMethod:new_sel error:&error]; if(error) NSLog(@"%@", error); } 19 | #define CBHookClassMethod(classname, ori_sel, new_sel) { NSError *error; [CBGetClass(classname) jr_swizzleClassMethod:ori_sel withClassMethod:new_sel error:&error]; if(error) NSLog(@"%@", error); } 20 | #define CBGetInstanceValue(obj, valuename) object_getIvar(obj, class_getInstanceVariable([obj class], #valuename)) 21 | #define CBSetInstanceValue(obj, valuename, value) object_setIvar(obj, class_getInstanceVariable([obj class], #valuename), value) 22 | 23 | #endif 24 | 25 | -------------------------------------------------------------------------------- /App Plugin/Cocoa App Plugin.xctemplate/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlayshChen/XcodeAppPluginTemplate/9014d1d3b77b86f7111db3c7a8f4e46a8c26dc74/App Plugin/Cocoa App Plugin.xctemplate/TemplateIcon.icns -------------------------------------------------------------------------------- /App Plugin/Cocoa App Plugin.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Kind 6 | Xcode.Xcode3.ProjectTemplateUnitKind 7 | Identifier 8 | com.corbin.pluginFramework-mac 9 | Concrete 10 | 11 | Description 12 | This template builds a plugin framework that links against the Foundation and UIKit frameworks. 13 | Platforms 14 | 15 | com.apple.platform.macosx 16 | 17 | Ancestors 18 | 19 | com.apple.dt.unit.frameworkBase 20 | com.apple.dt.unit.macBase 21 | 22 | Project 23 | 24 | SharedSettings 25 | 26 | TARGETED_DEVICE_FAMILY 27 | 1,2 28 | GCC_WARN_ABOUT_MISSING_PROTOTYPES 29 | YES 30 | GCC_WARN_UNUSED_VARIABLE 31 | YES 32 | GCC_WARN_ABOUT_RETURN_TYPE 33 | YES 34 | GCC_C_LANGUAGE_STANDARD 35 | gnu99 36 | EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES 37 | *.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj 38 | 39 | Configurations 40 | 41 | Debug 42 | 43 | VALIDATE_PRODUCT 44 | NO 45 | GCC_OPTIMIZATION_LEVEL 46 | 0 47 | GCC_PREPROCESSOR_DEFINITIONS 48 | DEBUG=1 $(inherited) 49 | GCC_SYMBOLS_PRIVATE_EXTERN 50 | NO 51 | COPY_PHASE_STRIP 52 | NO 53 | GCC_DYNAMIC_NO_PIC 54 | NO 55 | 56 | Release 57 | 58 | COPY_PHASE_STRIP 59 | YES 60 | VALIDATE_PRODUCT 61 | YES 62 | 63 | 64 | 65 | Targets 66 | 67 | 68 | ProductType 69 | com.apple.product-type.framework 70 | TargetIdentifier 71 | plugin 72 | SharedSettings 73 | 74 | INSTALL_PATH 75 | $(LOCAL_LIBRARY_DIR)/Frameworks 76 | SKIP_INSTALL 77 | YES 78 | DYLIB_COMPATIBILITY_VERSION 79 | 1 80 | DYLIB_CURRENT_VERSION 81 | 1 82 | DYLIB_INSTALL_NAME_BASE 83 | @rpath 84 | DEFINES_MODULE 85 | YES 86 | GCC_PRECOMPILE_PREFIX_HEADER 87 | YES 88 | GCC_PREFIX_HEADER 89 | ___PACKAGENAME___/PrefixHeader.pch 90 | 91 | BuildPhases 92 | 93 | 94 | 95 | Name 96 | ___VARIABLE_TargetAppName___ 97 | ProductType 98 | com.apple.product-type.application 99 | SharedSettings 100 | 101 | INFOPLIST_FILE 102 | ___PACKAGENAME___/Info.plist 103 | PRODUCT_NAME 104 | ___VARIABLE_TargetAppName___ 105 | DEFINES_MODULE 106 | YES 107 | GCC_PRECOMPILE_PREFIX_HEADER 108 | YES 109 | 110 | BuildPhases 111 | 112 | 113 | Class 114 | ShellScript 115 | ShellPath 116 | /bin/sh 117 | ShowEnvVarsInLog 118 | true 119 | ShellScript 120 | APP_NAME="___VARIABLE_TargetAppName___" 121 | FRAMEWORK_NAME="___PACKAGENAME___" 122 | 123 | rm -rf "${BUILT_PRODUCTS_DIR}/${APP_NAME}.app" 124 | cp -r "${PROJECT_DIR}/${APP_NAME}.app" "${BUILT_PRODUCTS_DIR}/" 125 | 126 | APP_BUNDLE_PATH="${BUILT_PRODUCTS_DIR}/${APP_NAME}.app/Contents/MacOS" 127 | APP_EXECUTABLE_PATH="${APP_BUNDLE_PATH}/${APP_NAME}" 128 | 129 | cp -r "${BUILT_PRODUCTS_DIR}/${FRAMEWORK_NAME}.framework" ${APP_BUNDLE_PATH} 130 | 131 | insert_dylib --all-yes "@loader_path/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "$APP_EXECUTABLE_PATH" "$APP_EXECUTABLE_PATH" 132 | 133 | 134 | Dependencies 135 | 136 | plugin 137 | 138 | 139 | 140 | Options 141 | 142 | 143 | Identifier 144 | TargetAppName 145 | Required 146 | 147 | Name 148 | Target App Name: 149 | Description 150 | Target App Name. 151 | Type 152 | text 153 | Placeholder 154 | AppStore 155 | 156 | 157 | Nodes 158 | 159 | ___PACKAGENAME___.h 160 | ___PACKAGENAME___.m 161 | ___PACKAGENAME___Header.h 162 | PrefixHeader.pch 163 | ../Podfile 164 | Info.plist 165 | 166 | Definitions 167 | 168 | ../Podfile 169 | 170 | Group 171 | 172 | Supporting Files 173 | 174 | Path 175 | Podfile 176 | Beginning 177 | platform :osx, '10.11' 178 | 179 | target '___PACKAGENAME___' do 180 | pod 'JRSwizzle', '~> 1.0' 181 | end 182 | End 183 | 184 | 185 | ___PACKAGENAME___.h 186 | 187 | Path 188 | ___PACKAGENAME___.h 189 | 190 | ___PACKAGENAME___.m 191 | 192 | Path 193 | ___PACKAGENAME___.m 194 | 195 | ___PACKAGENAME___Header.h 196 | 197 | Path 198 | ___PACKAGENAME___Header.h 199 | 200 | PrefixHeader.pch 201 | 202 | Group 203 | 204 | Supporting Files 205 | 206 | Path 207 | PrefixHeader.pch 208 | 209 | Info.plist 210 | 211 | Group 212 | 213 | Supporting Files 214 | 215 | Path 216 | Info.plist 217 | 218 | 219 | 220 | 221 | -------------------------------------------------------------------------------- /App Plugin/Cocoa App Plugin.xctemplate/___PACKAGENAME___.h: -------------------------------------------------------------------------------- 1 | // 2 | // ___FILENAME___ 3 | // ___PACKAGENAME___ 4 | // 5 | // Created by ___FULLUSERNAME___ on ___DATE___. 6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | -------------------------------------------------------------------------------- /App Plugin/Cocoa App Plugin.xctemplate/___PACKAGENAME___.m: -------------------------------------------------------------------------------- 1 | // 2 | // ___FILENAME___ 3 | // ___PACKAGENAME___ 4 | // 5 | // Created by ___FULLUSERNAME___ on ___DATE___. 6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved. 7 | // 8 | 9 | #import "___FILEBASENAME___.h" 10 | #import "___PACKAGENAME___Header.h" 11 | 12 | #pragma mark - Plugin 13 | 14 | @implementation NSObject (___PACKAGENAME___) 15 | 16 | @end 17 | 18 | @implementation NSView (___PACKAGENAME___) 19 | 20 | @end 21 | 22 | @implementation NSViewController (___PACKAGENAME___) 23 | 24 | @end 25 | 26 | static void __attribute__((constructor)) initialize(void) { 27 | NSLog(@"++++++++ ___FILEBASENAME___ loaded ++++++++"); 28 | } -------------------------------------------------------------------------------- /App Plugin/Cocoa App Plugin.xctemplate/___PACKAGENAME___Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // ___FILENAME___ 3 | // ___PACKAGENAME___ 4 | // 5 | // Created by ___FULLUSERNAME___ on ___DATE___. 6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | -------------------------------------------------------------------------------- /Example/TestPlugin/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '8.0' 2 | 3 | target 'TestPlugin' do 4 | pod 'JRSwizzle', '~> 1.0' 5 | pod 'fishhook', '~> 0.2' 6 | end 7 | -------------------------------------------------------------------------------- /Example/TestPlugin/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - fishhook (0.2) 3 | - JRSwizzle (1.0) 4 | 5 | DEPENDENCIES: 6 | - fishhook (~> 0.2) 7 | - JRSwizzle (~> 1.0) 8 | 9 | SPEC CHECKSUMS: 10 | fishhook: ea19933abfe8f2f52c55fd8b6e2718467d3ebc89 11 | JRSwizzle: dd5ead5d913a0f29e7f558200165849f006bb1e3 12 | 13 | PODFILE CHECKSUM: abd12c5fc38d668ca7630a16f7b39bb17db384a3 14 | 15 | COCOAPODS: 1.2.0 16 | -------------------------------------------------------------------------------- /Example/TestPlugin/Test.app/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlayshChen/XcodeAppPluginTemplate/9014d1d3b77b86f7111db3c7a8f4e46a8c26dc74/Example/TestPlugin/Test.app/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib -------------------------------------------------------------------------------- /Example/TestPlugin/Test.app/Base.lproj/LaunchScreen.storyboardc/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlayshChen/XcodeAppPluginTemplate/9014d1d3b77b86f7111db3c7a8f4e46a8c26dc74/Example/TestPlugin/Test.app/Base.lproj/LaunchScreen.storyboardc/Info.plist -------------------------------------------------------------------------------- /Example/TestPlugin/Test.app/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlayshChen/XcodeAppPluginTemplate/9014d1d3b77b86f7111db3c7a8f4e46a8c26dc74/Example/TestPlugin/Test.app/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib -------------------------------------------------------------------------------- /Example/TestPlugin/Test.app/Base.lproj/Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlayshChen/XcodeAppPluginTemplate/9014d1d3b77b86f7111db3c7a8f4e46a8c26dc74/Example/TestPlugin/Test.app/Base.lproj/Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib -------------------------------------------------------------------------------- /Example/TestPlugin/Test.app/Base.lproj/Main.storyboardc/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlayshChen/XcodeAppPluginTemplate/9014d1d3b77b86f7111db3c7a8f4e46a8c26dc74/Example/TestPlugin/Test.app/Base.lproj/Main.storyboardc/Info.plist -------------------------------------------------------------------------------- /Example/TestPlugin/Test.app/Base.lproj/Main.storyboardc/UIViewController-BYZ-38-t0r.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlayshChen/XcodeAppPluginTemplate/9014d1d3b77b86f7111db3c7a8f4e46a8c26dc74/Example/TestPlugin/Test.app/Base.lproj/Main.storyboardc/UIViewController-BYZ-38-t0r.nib -------------------------------------------------------------------------------- /Example/TestPlugin/Test.app/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlayshChen/XcodeAppPluginTemplate/9014d1d3b77b86f7111db3c7a8f4e46a8c26dc74/Example/TestPlugin/Test.app/Info.plist -------------------------------------------------------------------------------- /Example/TestPlugin/Test.app/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /Example/TestPlugin/Test.app/Test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlayshChen/XcodeAppPluginTemplate/9014d1d3b77b86f7111db3c7a8f4e46a8c26dc74/Example/TestPlugin/Test.app/Test -------------------------------------------------------------------------------- /Example/TestPlugin/Test.app/_CodeSignature/CodeResources: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | files 6 | 7 | Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib 8 | 9 | 1p3j7kQQGyd4PDctW3DHSsdHFVA= 10 | 11 | Base.lproj/LaunchScreen.storyboardc/Info.plist 12 | 13 | n2t8gsDpfE6XkhG31p7IQJRxTxU= 14 | 15 | Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib 16 | 17 | dwBjPNAc3ySSVIpTjRUMQV0gC6k= 18 | 19 | Base.lproj/Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib 20 | 21 | eE/O2TZDTnLzaJw1IPRxX+aKs7A= 22 | 23 | Base.lproj/Main.storyboardc/Info.plist 24 | 25 | MDrKFvFWroTb0+KEbQShBcoBvo4= 26 | 27 | Base.lproj/Main.storyboardc/UIViewController-BYZ-38-t0r.nib 28 | 29 | +OQVNsy4kqmBB/DuvGWeDrbODjs= 30 | 31 | Info.plist 32 | 33 | kbRZtbKfaWoh+uBJzTvQlhxbrVE= 34 | 35 | PkgInfo 36 | 37 | n57qDP4tZfLD1rCS43W0B4LQjzE= 38 | 39 | 40 | files2 41 | 42 | Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib 43 | 44 | hash 45 | 46 | 1p3j7kQQGyd4PDctW3DHSsdHFVA= 47 | 48 | hash2 49 | 50 | eqoNaYGYsHJUQNngO5jmSYhgH4O6wCaq31bbkGRLYng= 51 | 52 | 53 | Base.lproj/LaunchScreen.storyboardc/Info.plist 54 | 55 | hash 56 | 57 | n2t8gsDpfE6XkhG31p7IQJRxTxU= 58 | 59 | hash2 60 | 61 | HyVdXMU7Ux4/KalAao30mpWOK/lEPT4gvYN09wf31cg= 62 | 63 | 64 | Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib 65 | 66 | hash 67 | 68 | dwBjPNAc3ySSVIpTjRUMQV0gC6k= 69 | 70 | hash2 71 | 72 | 96gGwVNRSvx6g/7g1CSlGk5yBDq0fadCe7hXurFeZZ8= 73 | 74 | 75 | Base.lproj/Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib 76 | 77 | hash 78 | 79 | eE/O2TZDTnLzaJw1IPRxX+aKs7A= 80 | 81 | hash2 82 | 83 | 22XLhh5AXZq2DRXdOHiabBJLDkjRBBC+qPwDvfSu+0Y= 84 | 85 | 86 | Base.lproj/Main.storyboardc/Info.plist 87 | 88 | hash 89 | 90 | MDrKFvFWroTb0+KEbQShBcoBvo4= 91 | 92 | hash2 93 | 94 | PpvapAjR62rl6Ym4E6hkTgpKmBICxTaQXeUqcpHmmqQ= 95 | 96 | 97 | Base.lproj/Main.storyboardc/UIViewController-BYZ-38-t0r.nib 98 | 99 | hash 100 | 101 | +OQVNsy4kqmBB/DuvGWeDrbODjs= 102 | 103 | hash2 104 | 105 | yRAV5uepyymANpFYbO5etNP4QC0NRMcn3R5zipqcsV4= 106 | 107 | 108 | 109 | rules 110 | 111 | ^ 112 | 113 | ^.*\.lproj/ 114 | 115 | optional 116 | 117 | weight 118 | 1000 119 | 120 | ^.*\.lproj/locversion.plist$ 121 | 122 | omit 123 | 124 | weight 125 | 1100 126 | 127 | ^Base\.lproj/ 128 | 129 | weight 130 | 1010 131 | 132 | ^version.plist$ 133 | 134 | 135 | rules2 136 | 137 | .*\.dSYM($|/) 138 | 139 | weight 140 | 11 141 | 142 | ^ 143 | 144 | weight 145 | 20 146 | 147 | ^(.*/)?\.DS_Store$ 148 | 149 | omit 150 | 151 | weight 152 | 2000 153 | 154 | ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ 155 | 156 | nested 157 | 158 | weight 159 | 10 160 | 161 | ^.* 162 | 163 | ^.*\.lproj/ 164 | 165 | optional 166 | 167 | weight 168 | 1000 169 | 170 | ^.*\.lproj/locversion.plist$ 171 | 172 | omit 173 | 174 | weight 175 | 1100 176 | 177 | ^Base\.lproj/ 178 | 179 | weight 180 | 1010 181 | 182 | ^Info\.plist$ 183 | 184 | omit 185 | 186 | weight 187 | 20 188 | 189 | ^PkgInfo$ 190 | 191 | omit 192 | 193 | weight 194 | 20 195 | 196 | ^[^/]+$ 197 | 198 | nested 199 | 200 | weight 201 | 10 202 | 203 | ^embedded\.provisionprofile$ 204 | 205 | weight 206 | 20 207 | 208 | ^version\.plist$ 209 | 210 | weight 211 | 20 212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /Example/TestPlugin/TestPlugin.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 18DC9D4A977DF59C2AEA92AD /* libPods-TestPlugin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F10EC0C23534B84167907F2 /* libPods-TestPlugin.a */; }; 11 | 800A11801E909CAA00263C7F /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 800A117F1E909CAA00263C7F /* Info.plist */; }; 12 | 800A11821E909CAA00263C7F /* TestPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 800A11811E909CAA00263C7F /* TestPlugin.h */; }; 13 | 800A11841E909CAA00263C7F /* TestPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 800A11831E909CAA00263C7F /* TestPlugin.m */; }; 14 | 800A11861E909CAA00263C7F /* TestPluginHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 800A11851E909CAA00263C7F /* TestPluginHeader.h */; }; 15 | 800A11881E909CAA00263C7F /* PrefixHeader.pch in Headers */ = {isa = PBXBuildFile; fileRef = 800A11871E909CAA00263C7F /* PrefixHeader.pch */; }; 16 | 800A118A1E909CAA00263C7F /* Podfile in Resources */ = {isa = PBXBuildFile; fileRef = 800A11891E909CAA00263C7F /* Podfile */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | 800A117B1E909CAA00263C7F /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = 800A116D1E909CAA00263C7F /* Project object */; 23 | proxyType = 1; 24 | remoteGlobalIDString = 800A11751E909CAA00263C7F; 25 | remoteInfo = TestPlugin; 26 | }; 27 | /* End PBXContainerItemProxy section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 2536D5D86E931C9CD1032C09 /* Pods-TestPlugin.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestPlugin.debug.xcconfig"; path = "Pods/Target Support Files/Pods-TestPlugin/Pods-TestPlugin.debug.xcconfig"; sourceTree = ""; }; 31 | 5C4E6C51D1A6C8084786A621 /* Pods-TestPlugin.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestPlugin.release.xcconfig"; path = "Pods/Target Support Files/Pods-TestPlugin/Pods-TestPlugin.release.xcconfig"; sourceTree = ""; }; 32 | 6F10EC0C23534B84167907F2 /* libPods-TestPlugin.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-TestPlugin.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | 800A11761E909CAA00263C7F /* TestPlugin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TestPlugin.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 800A117A1E909CAA00263C7F /* Test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Test.app; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 800A117F1E909CAA00263C7F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 36 | 800A11811E909CAA00263C7F /* TestPlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestPlugin.h; sourceTree = ""; }; 37 | 800A11831E909CAA00263C7F /* TestPlugin.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestPlugin.m; sourceTree = ""; }; 38 | 800A11851E909CAA00263C7F /* TestPluginHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestPluginHeader.h; sourceTree = ""; }; 39 | 800A11871E909CAA00263C7F /* PrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrefixHeader.pch; sourceTree = ""; }; 40 | 800A11891E909CAA00263C7F /* Podfile */ = {isa = PBXFileReference; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = ""; }; 41 | /* End PBXFileReference section */ 42 | 43 | /* Begin PBXFrameworksBuildPhase section */ 44 | 800A11721E909CAA00263C7F /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | 18DC9D4A977DF59C2AEA92AD /* libPods-TestPlugin.a in Frameworks */, 49 | ); 50 | runOnlyForDeploymentPostprocessing = 0; 51 | }; 52 | CF7462966C6E17C92BE578D7 /* Frameworks */ = { 53 | isa = PBXFrameworksBuildPhase; 54 | buildActionMask = 2147483647; 55 | files = ( 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | /* End PBXFrameworksBuildPhase section */ 60 | 61 | /* Begin PBXGroup section */ 62 | 3321C313F8D0D00C77236E85 /* Pods */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | 2536D5D86E931C9CD1032C09 /* Pods-TestPlugin.debug.xcconfig */, 66 | 5C4E6C51D1A6C8084786A621 /* Pods-TestPlugin.release.xcconfig */, 67 | ); 68 | name = Pods; 69 | sourceTree = ""; 70 | }; 71 | 800A116C1E909CAA00263C7F = { 72 | isa = PBXGroup; 73 | children = ( 74 | 800A117D1E909CAA00263C7F /* TestPlugin */, 75 | 800A11771E909CAA00263C7F /* Products */, 76 | 3321C313F8D0D00C77236E85 /* Pods */, 77 | F8C10F3C556717356686FDDE /* Frameworks */, 78 | ); 79 | sourceTree = ""; 80 | }; 81 | 800A11771E909CAA00263C7F /* Products */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 800A11761E909CAA00263C7F /* TestPlugin.framework */, 85 | 800A117A1E909CAA00263C7F /* Test.app */, 86 | ); 87 | name = Products; 88 | sourceTree = ""; 89 | }; 90 | 800A117D1E909CAA00263C7F /* TestPlugin */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 800A11811E909CAA00263C7F /* TestPlugin.h */, 94 | 800A11831E909CAA00263C7F /* TestPlugin.m */, 95 | 800A11851E909CAA00263C7F /* TestPluginHeader.h */, 96 | 800A117E1E909CAA00263C7F /* Supporting Files */, 97 | ); 98 | path = TestPlugin; 99 | sourceTree = ""; 100 | }; 101 | 800A117E1E909CAA00263C7F /* Supporting Files */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 800A117F1E909CAA00263C7F /* Info.plist */, 105 | 800A11871E909CAA00263C7F /* PrefixHeader.pch */, 106 | 800A11891E909CAA00263C7F /* Podfile */, 107 | ); 108 | name = "Supporting Files"; 109 | sourceTree = ""; 110 | }; 111 | F8C10F3C556717356686FDDE /* Frameworks */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 6F10EC0C23534B84167907F2 /* libPods-TestPlugin.a */, 115 | ); 116 | name = Frameworks; 117 | sourceTree = ""; 118 | }; 119 | /* End PBXGroup section */ 120 | 121 | /* Begin PBXHeadersBuildPhase section */ 122 | 800A11731E909CAA00263C7F /* Headers */ = { 123 | isa = PBXHeadersBuildPhase; 124 | buildActionMask = 2147483647; 125 | files = ( 126 | 800A11861E909CAA00263C7F /* TestPluginHeader.h in Headers */, 127 | 800A11821E909CAA00263C7F /* TestPlugin.h in Headers */, 128 | 800A11881E909CAA00263C7F /* PrefixHeader.pch in Headers */, 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | /* End PBXHeadersBuildPhase section */ 133 | 134 | /* Begin PBXNativeTarget section */ 135 | 800A11751E909CAA00263C7F /* TestPlugin */ = { 136 | isa = PBXNativeTarget; 137 | buildConfigurationList = 800A118D1E909CAA00263C7F /* Build configuration list for PBXNativeTarget "TestPlugin" */; 138 | buildPhases = ( 139 | EE63407BFA7688E0E803408A /* [CP] Check Pods Manifest.lock */, 140 | 800A11711E909CAA00263C7F /* Sources */, 141 | 800A11721E909CAA00263C7F /* Frameworks */, 142 | 800A11731E909CAA00263C7F /* Headers */, 143 | 800A11741E909CAA00263C7F /* Resources */, 144 | 1849EB0A85ED5E45EAA5DBD8 /* [CP] Copy Pods Resources */, 145 | ); 146 | buildRules = ( 147 | ); 148 | dependencies = ( 149 | ); 150 | name = TestPlugin; 151 | productName = TestPlugin; 152 | productReference = 800A11761E909CAA00263C7F /* TestPlugin.framework */; 153 | productType = "com.apple.product-type.framework"; 154 | }; 155 | 800A11791E909CAA00263C7F /* Test */ = { 156 | isa = PBXNativeTarget; 157 | buildConfigurationList = 800A11901E909CAA00263C7F /* Build configuration list for PBXNativeTarget "Test" */; 158 | buildPhases = ( 159 | 800A11781E909CAA00263C7F /* ShellScript */, 160 | CF7462966C6E17C92BE578D7 /* Frameworks */, 161 | ); 162 | buildRules = ( 163 | ); 164 | dependencies = ( 165 | 800A117C1E909CAA00263C7F /* PBXTargetDependency */, 166 | ); 167 | name = Test; 168 | productName = Test; 169 | productReference = 800A117A1E909CAA00263C7F /* Test.app */; 170 | productType = "com.apple.product-type.application"; 171 | }; 172 | /* End PBXNativeTarget section */ 173 | 174 | /* Begin PBXProject section */ 175 | 800A116D1E909CAA00263C7F /* Project object */ = { 176 | isa = PBXProject; 177 | attributes = { 178 | LastUpgradeCheck = 0820; 179 | ORGANIZATIONNAME = CorbinChen; 180 | TargetAttributes = { 181 | 800A11751E909CAA00263C7F = { 182 | CreatedOnToolsVersion = 8.2; 183 | ProvisioningStyle = Automatic; 184 | }; 185 | 800A11791E909CAA00263C7F = { 186 | CreatedOnToolsVersion = 8.2; 187 | DevelopmentTeam = TW89Q8SE37; 188 | ProvisioningStyle = Automatic; 189 | }; 190 | }; 191 | }; 192 | buildConfigurationList = 800A11701E909CAA00263C7F /* Build configuration list for PBXProject "TestPlugin" */; 193 | compatibilityVersion = "Xcode 3.2"; 194 | developmentRegion = English; 195 | hasScannedForEncodings = 0; 196 | knownRegions = ( 197 | en, 198 | ); 199 | mainGroup = 800A116C1E909CAA00263C7F; 200 | productRefGroup = 800A11771E909CAA00263C7F /* Products */; 201 | projectDirPath = ""; 202 | projectRoot = ""; 203 | targets = ( 204 | 800A11751E909CAA00263C7F /* TestPlugin */, 205 | 800A11791E909CAA00263C7F /* Test */, 206 | ); 207 | }; 208 | /* End PBXProject section */ 209 | 210 | /* Begin PBXResourcesBuildPhase section */ 211 | 800A11741E909CAA00263C7F /* Resources */ = { 212 | isa = PBXResourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | 800A118A1E909CAA00263C7F /* Podfile in Resources */, 216 | 800A11801E909CAA00263C7F /* Info.plist in Resources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXResourcesBuildPhase section */ 221 | 222 | /* Begin PBXShellScriptBuildPhase section */ 223 | 1849EB0A85ED5E45EAA5DBD8 /* [CP] Copy Pods Resources */ = { 224 | isa = PBXShellScriptBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | ); 228 | inputPaths = ( 229 | ); 230 | name = "[CP] Copy Pods Resources"; 231 | outputPaths = ( 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | shellPath = /bin/sh; 235 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-TestPlugin/Pods-TestPlugin-resources.sh\"\n"; 236 | showEnvVarsInLog = 0; 237 | }; 238 | 800A11781E909CAA00263C7F /* ShellScript */ = { 239 | isa = PBXShellScriptBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | ); 243 | inputPaths = ( 244 | ); 245 | outputPaths = ( 246 | ); 247 | runOnlyForDeploymentPostprocessing = 0; 248 | shellPath = /bin/sh; 249 | shellScript = "APP_PATH=\"${PROJECT_DIR}/Test.app\"\nFRAMEWORK_PATH=\"${BUILT_PRODUCTS_DIR}/TestPlugin.framework\"\nBUNDLE_IDENTIFIER=\"com.corbin.Test\"\n\nAPP_NAME=\"Test.app\"\nAPP_EXECUTABLE=\"Test\"\n\nFRAMEWORK_NAME=$(basename \"$FRAMEWORK_PATH\")\nFRAMEWORK_EXECUTABLE=\"${FRAMEWORK_NAME}/${FRAMEWORK_NAME%.*}\"\n\nTEMP_DIR=$(mktemp -d)\ncd ${TEMP_DIR}\n\ncp -r \"${APP_PATH}\" ${TEMP_DIR}/\nmkdir -p \"${APP_NAME}/Frameworks\"\ncp -r \"${FRAMEWORK_PATH}\" \"${APP_NAME}/Frameworks\"\n\nplutil -replace CFBundleIdentifier -string ${BUNDLE_IDENTIFIER} \"${APP_NAME}/Info.plist\"\ninsert_dylib --all-yes @executable_path/Frameworks/${FRAMEWORK_EXECUTABLE} \"${APP_NAME}/${APP_EXECUTABLE}\"\nmv \"${APP_NAME}/${APP_EXECUTABLE}_patched\" \"$APP_NAME/${APP_EXECUTABLE}\"\nchmod +x \"${APP_NAME}/${APP_EXECUTABLE}\"\n\nrm -rf \"${APP_NAME}/PlugIns\"\nrm -rf \"${APP_NAME}/Watch\"\n\nrm -rf \"${BUILT_PRODUCTS_DIR}/${APP_NAME}\"\nmv \"${APP_NAME}\" ${BUILT_PRODUCTS_DIR}\nrm -rf ${TEMP_DIR}"; 250 | }; 251 | EE63407BFA7688E0E803408A /* [CP] Check Pods Manifest.lock */ = { 252 | isa = PBXShellScriptBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | ); 256 | inputPaths = ( 257 | ); 258 | name = "[CP] Check Pods Manifest.lock"; 259 | outputPaths = ( 260 | ); 261 | runOnlyForDeploymentPostprocessing = 0; 262 | shellPath = /bin/sh; 263 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 264 | showEnvVarsInLog = 0; 265 | }; 266 | /* End PBXShellScriptBuildPhase section */ 267 | 268 | /* Begin PBXSourcesBuildPhase section */ 269 | 800A11711E909CAA00263C7F /* Sources */ = { 270 | isa = PBXSourcesBuildPhase; 271 | buildActionMask = 2147483647; 272 | files = ( 273 | 800A11841E909CAA00263C7F /* TestPlugin.m in Sources */, 274 | ); 275 | runOnlyForDeploymentPostprocessing = 0; 276 | }; 277 | /* End PBXSourcesBuildPhase section */ 278 | 279 | /* Begin PBXTargetDependency section */ 280 | 800A117C1E909CAA00263C7F /* PBXTargetDependency */ = { 281 | isa = PBXTargetDependency; 282 | target = 800A11751E909CAA00263C7F /* TestPlugin */; 283 | targetProxy = 800A117B1E909CAA00263C7F /* PBXContainerItemProxy */; 284 | }; 285 | /* End PBXTargetDependency section */ 286 | 287 | /* Begin XCBuildConfiguration section */ 288 | 800A118B1E909CAA00263C7F /* Debug */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | ALWAYS_SEARCH_USER_PATHS = NO; 292 | CLANG_ANALYZER_NONNULL = YES; 293 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 294 | CLANG_CXX_LIBRARY = "libc++"; 295 | CLANG_ENABLE_MODULES = YES; 296 | CLANG_ENABLE_OBJC_ARC = YES; 297 | CLANG_WARN_BOOL_CONVERSION = YES; 298 | CLANG_WARN_CONSTANT_CONVERSION = YES; 299 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 300 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 301 | CLANG_WARN_EMPTY_BODY = YES; 302 | CLANG_WARN_ENUM_CONVERSION = YES; 303 | CLANG_WARN_INFINITE_RECURSION = YES; 304 | CLANG_WARN_INT_CONVERSION = YES; 305 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 306 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 307 | CLANG_WARN_UNREACHABLE_CODE = YES; 308 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 309 | COPY_PHASE_STRIP = NO; 310 | CURRENT_PROJECT_VERSION = 1; 311 | DEBUG_INFORMATION_FORMAT = dwarf; 312 | ENABLE_STRICT_OBJC_MSGSEND = YES; 313 | ENABLE_TESTABILITY = YES; 314 | EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj"; 315 | GCC_C_LANGUAGE_STANDARD = gnu99; 316 | GCC_DYNAMIC_NO_PIC = NO; 317 | GCC_NO_COMMON_BLOCKS = YES; 318 | GCC_OPTIMIZATION_LEVEL = 0; 319 | GCC_PREPROCESSOR_DEFINITIONS = ( 320 | "DEBUG=1", 321 | "$(inherited)", 322 | ); 323 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 324 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 325 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 326 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 327 | GCC_WARN_UNDECLARED_SELECTOR = YES; 328 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 329 | GCC_WARN_UNUSED_FUNCTION = YES; 330 | GCC_WARN_UNUSED_VARIABLE = YES; 331 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 332 | MTL_ENABLE_DEBUG_INFO = YES; 333 | ONLY_ACTIVE_ARCH = YES; 334 | SDKROOT = iphoneos; 335 | TARGETED_DEVICE_FAMILY = "1,2"; 336 | VALIDATE_PRODUCT = NO; 337 | VERSIONING_SYSTEM = "apple-generic"; 338 | VERSION_INFO_PREFIX = ""; 339 | }; 340 | name = Debug; 341 | }; 342 | 800A118C1E909CAA00263C7F /* Release */ = { 343 | isa = XCBuildConfiguration; 344 | buildSettings = { 345 | ALWAYS_SEARCH_USER_PATHS = NO; 346 | CLANG_ANALYZER_NONNULL = YES; 347 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 348 | CLANG_CXX_LIBRARY = "libc++"; 349 | CLANG_ENABLE_MODULES = YES; 350 | CLANG_ENABLE_OBJC_ARC = YES; 351 | CLANG_WARN_BOOL_CONVERSION = YES; 352 | CLANG_WARN_CONSTANT_CONVERSION = YES; 353 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 354 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 355 | CLANG_WARN_EMPTY_BODY = YES; 356 | CLANG_WARN_ENUM_CONVERSION = YES; 357 | CLANG_WARN_INFINITE_RECURSION = YES; 358 | CLANG_WARN_INT_CONVERSION = YES; 359 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 360 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 361 | CLANG_WARN_UNREACHABLE_CODE = YES; 362 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 363 | COPY_PHASE_STRIP = YES; 364 | CURRENT_PROJECT_VERSION = 1; 365 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 366 | ENABLE_NS_ASSERTIONS = NO; 367 | ENABLE_STRICT_OBJC_MSGSEND = YES; 368 | EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj"; 369 | GCC_C_LANGUAGE_STANDARD = gnu99; 370 | GCC_NO_COMMON_BLOCKS = YES; 371 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 372 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 373 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 374 | GCC_WARN_UNDECLARED_SELECTOR = YES; 375 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 376 | GCC_WARN_UNUSED_FUNCTION = YES; 377 | GCC_WARN_UNUSED_VARIABLE = YES; 378 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 379 | MTL_ENABLE_DEBUG_INFO = NO; 380 | SDKROOT = iphoneos; 381 | TARGETED_DEVICE_FAMILY = "1,2"; 382 | VALIDATE_PRODUCT = YES; 383 | VERSIONING_SYSTEM = "apple-generic"; 384 | VERSION_INFO_PREFIX = ""; 385 | }; 386 | name = Release; 387 | }; 388 | 800A118E1E909CAA00263C7F /* Debug */ = { 389 | isa = XCBuildConfiguration; 390 | baseConfigurationReference = 2536D5D86E931C9CD1032C09 /* Pods-TestPlugin.debug.xcconfig */; 391 | buildSettings = { 392 | CODE_SIGN_IDENTITY = "iPhone Developer"; 393 | DEFINES_MODULE = YES; 394 | DEVELOPMENT_TEAM = ""; 395 | DYLIB_COMPATIBILITY_VERSION = 1; 396 | DYLIB_CURRENT_VERSION = 1; 397 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 398 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 399 | GCC_PREFIX_HEADER = TestPlugin/PrefixHeader.pch; 400 | INFOPLIST_FILE = TestPlugin/Info.plist; 401 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 402 | PRODUCT_BUNDLE_IDENTIFIER = com.corbin.TestPlugin; 403 | PRODUCT_NAME = "$(TARGET_NAME)"; 404 | SKIP_INSTALL = YES; 405 | }; 406 | name = Debug; 407 | }; 408 | 800A118F1E909CAA00263C7F /* Release */ = { 409 | isa = XCBuildConfiguration; 410 | baseConfigurationReference = 5C4E6C51D1A6C8084786A621 /* Pods-TestPlugin.release.xcconfig */; 411 | buildSettings = { 412 | CODE_SIGN_IDENTITY = "iPhone Developer"; 413 | DEFINES_MODULE = YES; 414 | DEVELOPMENT_TEAM = ""; 415 | DYLIB_COMPATIBILITY_VERSION = 1; 416 | DYLIB_CURRENT_VERSION = 1; 417 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 418 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 419 | GCC_PREFIX_HEADER = TestPlugin/PrefixHeader.pch; 420 | INFOPLIST_FILE = TestPlugin/Info.plist; 421 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 422 | PRODUCT_BUNDLE_IDENTIFIER = com.corbin.TestPlugin; 423 | PRODUCT_NAME = "$(TARGET_NAME)"; 424 | SKIP_INSTALL = YES; 425 | }; 426 | name = Release; 427 | }; 428 | 800A11911E909CAA00263C7F /* Debug */ = { 429 | isa = XCBuildConfiguration; 430 | buildSettings = { 431 | CODE_SIGN_IDENTITY = "iPhone Developer"; 432 | DEFINES_MODULE = YES; 433 | DEVELOPMENT_TEAM = TW89Q8SE37; 434 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 435 | INFOPLIST_FILE = TestPlugin/Info.plist; 436 | PRODUCT_BUNDLE_IDENTIFIER = com.corbin.Test; 437 | PRODUCT_NAME = Test; 438 | }; 439 | name = Debug; 440 | }; 441 | 800A11921E909CAA00263C7F /* Release */ = { 442 | isa = XCBuildConfiguration; 443 | buildSettings = { 444 | CODE_SIGN_IDENTITY = "iPhone Developer"; 445 | DEFINES_MODULE = YES; 446 | DEVELOPMENT_TEAM = TW89Q8SE37; 447 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 448 | INFOPLIST_FILE = TestPlugin/Info.plist; 449 | PRODUCT_BUNDLE_IDENTIFIER = com.corbin.Test; 450 | PRODUCT_NAME = Test; 451 | }; 452 | name = Release; 453 | }; 454 | /* End XCBuildConfiguration section */ 455 | 456 | /* Begin XCConfigurationList section */ 457 | 800A11701E909CAA00263C7F /* Build configuration list for PBXProject "TestPlugin" */ = { 458 | isa = XCConfigurationList; 459 | buildConfigurations = ( 460 | 800A118B1E909CAA00263C7F /* Debug */, 461 | 800A118C1E909CAA00263C7F /* Release */, 462 | ); 463 | defaultConfigurationIsVisible = 0; 464 | defaultConfigurationName = Release; 465 | }; 466 | 800A118D1E909CAA00263C7F /* Build configuration list for PBXNativeTarget "TestPlugin" */ = { 467 | isa = XCConfigurationList; 468 | buildConfigurations = ( 469 | 800A118E1E909CAA00263C7F /* Debug */, 470 | 800A118F1E909CAA00263C7F /* Release */, 471 | ); 472 | defaultConfigurationIsVisible = 0; 473 | defaultConfigurationName = Release; 474 | }; 475 | 800A11901E909CAA00263C7F /* Build configuration list for PBXNativeTarget "Test" */ = { 476 | isa = XCConfigurationList; 477 | buildConfigurations = ( 478 | 800A11911E909CAA00263C7F /* Debug */, 479 | 800A11921E909CAA00263C7F /* Release */, 480 | ); 481 | defaultConfigurationIsVisible = 0; 482 | defaultConfigurationName = Release; 483 | }; 484 | /* End XCConfigurationList section */ 485 | }; 486 | rootObject = 800A116D1E909CAA00263C7F /* Project object */; 487 | } 488 | -------------------------------------------------------------------------------- /Example/TestPlugin/TestPlugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/TestPlugin/TestPlugin.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/TestPlugin/TestPlugin/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/TestPlugin/TestPlugin/PrefixHeader.pch: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixHeader.pch 3 | // TestPlugin 4 | // 5 | // Created by CorbinChen on 2017/4/2. 6 | // Copyright © 2017年 CorbinChen. All rights reserved. 7 | // 8 | 9 | #ifndef TestPlugin_PrefixHeader_pch 10 | #define TestPlugin_PrefixHeader_pch 11 | 12 | #import 13 | #import 14 | #import 15 | #import 16 | 17 | #define CBGetClass(classname) objc_getClass(#classname) 18 | #define CBRegisterClass(superclassname, subclassname) { Class class = objc_allocateClassPair(CBGetClass(superclassname), #subclassname, 0);objc_registerClassPair(class); } 19 | #define CBHookInstanceMethod(classname, ori_sel, new_sel) { NSError *error; [CBGetClass(classname) jr_swizzleMethod:ori_sel withMethod:new_sel error:&error]; if(error) NSLog(@"%@", error); } 20 | #define CBHookClassMethod(classname, ori_sel, new_sel) { NSError *error; [CBGetClass(classname) jr_swizzleClassMethod:ori_sel withClassMethod:new_sel error:&error]; if(error) NSLog(@"%@", error); } 21 | #define CBGetInstanceValue(obj, valuename) object_getIvar(obj, class_getInstanceVariable([obj class], #valuename)) 22 | #define CBSetInstanceValue(obj, valuename, value) object_setIvar(obj, class_getInstanceVariable([obj class], #valuename), value) 23 | 24 | #endif 25 | 26 | -------------------------------------------------------------------------------- /Example/TestPlugin/TestPlugin/TestPlugin.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestPlugin.h 3 | // TestPlugin 4 | // 5 | // Created by CorbinChen on 2017/4/2. 6 | // Copyright (c) 2017年 CorbinChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | -------------------------------------------------------------------------------- /Example/TestPlugin/TestPlugin/TestPlugin.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestPlugin.m 3 | // TestPlugin 4 | // 5 | // Created by CorbinChen on 2017/4/2. 6 | // Copyright (c) 2017年 CorbinChen. All rights reserved. 7 | // 8 | 9 | #import "TestPlugin.h" 10 | #import "TestPluginHeader.h" 11 | 12 | #pragma mark - Plugin 13 | 14 | @implementation NSObject (TestPlugin) 15 | 16 | @end 17 | 18 | @implementation UIView (TestPlugin) 19 | 20 | @end 21 | 22 | @implementation UIViewController (TestPlugin) 23 | 24 | - (void)cb_viewDidLoad { 25 | [self cb_viewDidLoad]; 26 | self.view.backgroundColor = [UIColor orangeColor]; 27 | } 28 | 29 | @end 30 | 31 | static void __attribute__((constructor)) initialize(void) { 32 | NSLog(@"++++++++ TestPlugin loaded ++++++++"); 33 | CBHookInstanceMethod(UIViewController, @selector(viewDidLoad), @selector(cb_viewDidLoad)); 34 | } 35 | -------------------------------------------------------------------------------- /Example/TestPlugin/TestPlugin/TestPluginHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestPluginHeader.h 3 | // TestPlugin 4 | // 5 | // Created by CorbinChen on 2017/4/2. 6 | // Copyright (c) 2017年 CorbinChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XcodeAppPluginTemplate 2 | 3 | ![](http://ofg6kncyv.bkt.clouddn.com/Icon.png) 4 | App Plugin Project Template For iOS App and Mac App. 5 | 6 | 说明:我将过去文章中涉及到的工程整理出工程模版,方便对第三方app进行hook. 7 | 文章链接:[我是如何利用Xcode调试开发微信消息预览插件的](http://alayshchen.github.io/2016/02/26/我是如何利用Xcode调试开发微信消息预览插件的/) 8 | 9 | ## 前提 10 | 11 | [insert_dylib](https://github.com/Tyilo/insert_dylib) 12 | 13 | 14 | ## 如何安装 15 | 16 | * 将 `App Plugin` 文件夹拷贝到 `~/Library/Developer/Xcode/Templates/Project Templates`. 17 | 18 | ## 如何卸载 19 | 20 | * 删除文件夹:`~/Library/Developer/Xcode/Templates/Project Templates/App Plugin`. 21 | 22 | ## 如何使用 23 | 24 | * 在Xcode中选择新建工程,选择iOS中的`App Plugin`或者macOS中的`Mac App Plugin`工程模版. 25 | 26 | ![](http://ofg6kncyv.bkt.clouddn.com/0.png) 27 | 28 | * 填写工程选项.(Target app name 是要hook的第三方app名称,Target app bundle id打包后的app bundle id, 脚本会自动修改原app bundle id为此值) 29 | 30 | ![](http://ofg6kncyv.bkt.clouddn.com/2.png) 31 | 32 | * 最后,将要hook的app放在工程文件夹中,注意这里的文件名要与上一步中的Target app name一致,并执行命令`pod install`. 33 | 34 | ![](http://ofg6kncyv.bkt.clouddn.com/4.png) 35 | 36 | 37 | ## 原理 38 | 使用模版创建工程后,会有一个动态库target和空app target. 选择app scheme进行build,Xcode首先会build 动态库,然后执行脚本,将动态库注入app中,生成新的app,放在product目录。接着Xcode会进行签名等一系列操作,启动app,连接调试器,这样,我们就可以debug插件和原app了。 39 | 40 | * 注入动态库 41 | ![](http://ofg6kncyv.bkt.clouddn.com/5.png) 42 | * Xcode Build流程 43 | ![](http://ofg6kncyv.bkt.clouddn.com/6.png) 44 | * 效果图 45 | ![](http://ofg6kncyv.bkt.clouddn.com/7.png) 46 | --------------------------------------------------------------------------------