├── BetterXib.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── zhang.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── zhang.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── BetterXib.xcscheme │ ├── BetterXibTest.xcscheme │ └── xcschememanagement.plist ├── BetterXib.xcplugin └── Contents │ ├── Info.plist │ ├── MacOS │ └── BetterXib │ └── Resources │ ├── AddProjectWindowController.nib │ ├── IOSStoryboardTemplate.xml │ ├── IOSTemplate.nib │ ├── IOSTemplate.xml │ ├── MacTemplate.nib │ ├── MacTemplate.xml │ └── en.lproj │ └── InfoPlist.strings ├── BetterXib ├── AddProjectWindowController.h ├── AddProjectWindowController.m ├── AddProjectWindowController.xib ├── BetterXib-Info.plist ├── BetterXib-Prefix.pch ├── BetterXib.h ├── BetterXib.m ├── IOSStoryboardTemplate.xml ├── IOSTemplate.xml ├── MacTemplate.xml ├── Model │ ├── TProject.h │ └── TProject.m └── en.lproj │ └── InfoPlist.strings ├── BetterXibTest ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ └── MainMenu.xib ├── BetterXibTest-Info.plist ├── BetterXibTest-Prefix.pch ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── en.lproj │ ├── Credits.rtf │ └── InfoPlist.strings └── main.m ├── BetterXibTestTests ├── BetterXibTestTests-Info.plist ├── BetterXibTestTests.m └── en.lproj │ └── InfoPlist.strings └── README.md /BetterXib.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1F7ECBED194C757F00C70AAA /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1FDF3896194AE9660000C12B /* MainMenu.xib */; }; 11 | 1F8C1516194FF751006DA9B3 /* IOSStoryboardTemplate.xml in Resources */ = {isa = PBXBuildFile; fileRef = 1F8C1515194FF751006DA9B3 /* IOSStoryboardTemplate.xml */; }; 12 | 1F8C1517194FF751006DA9B3 /* IOSStoryboardTemplate.xml in Resources */ = {isa = PBXBuildFile; fileRef = 1F8C1515194FF751006DA9B3 /* IOSStoryboardTemplate.xml */; }; 13 | 1F9FFE82194C0E9800465172 /* AddProjectWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9FFE80194C0E9800465172 /* AddProjectWindowController.m */; }; 14 | 1F9FFE83194C0E9800465172 /* AddProjectWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1F9FFE81194C0E9800465172 /* AddProjectWindowController.xib */; }; 15 | 1F9FFE84194C131D00465172 /* AddProjectWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9FFE80194C0E9800465172 /* AddProjectWindowController.m */; }; 16 | 1F9FFE85194C132200465172 /* AddProjectWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1F9FFE81194C0E9800465172 /* AddProjectWindowController.xib */; }; 17 | 1F9FFE87194C150100465172 /* MacTemplate.xml in Resources */ = {isa = PBXBuildFile; fileRef = 1F9FFE86194C150100465172 /* MacTemplate.xml */; }; 18 | 1F9FFE88194C150100465172 /* MacTemplate.xml in Resources */ = {isa = PBXBuildFile; fileRef = 1F9FFE86194C150100465172 /* MacTemplate.xml */; }; 19 | 1F9FFE8A194C151400465172 /* IOSTemplate.xml in Resources */ = {isa = PBXBuildFile; fileRef = 1F9FFE89194C151400465172 /* IOSTemplate.xml */; }; 20 | 1F9FFE8B194C151400465172 /* IOSTemplate.xml in Resources */ = {isa = PBXBuildFile; fileRef = 1F9FFE89194C151400465172 /* IOSTemplate.xml */; }; 21 | 1FDF3868194AE1070000C12B /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FDF3867194AE1070000C12B /* AppKit.framework */; }; 22 | 1FDF386A194AE1070000C12B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FDF3869194AE1070000C12B /* Foundation.framework */; }; 23 | 1FDF3870194AE1070000C12B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1FDF386E194AE1070000C12B /* InfoPlist.strings */; }; 24 | 1FDF3873194AE1070000C12B /* BetterXib.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FDF3872194AE1070000C12B /* BetterXib.m */; }; 25 | 1FDF3882194AE9660000C12B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FDF3881194AE9660000C12B /* Cocoa.framework */; }; 26 | 1FDF388C194AE9660000C12B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1FDF388A194AE9660000C12B /* InfoPlist.strings */; }; 27 | 1FDF388E194AE9660000C12B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FDF388D194AE9660000C12B /* main.m */; }; 28 | 1FDF3892194AE9660000C12B /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 1FDF3890194AE9660000C12B /* Credits.rtf */; }; 29 | 1FDF3895194AE9660000C12B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FDF3894194AE9660000C12B /* AppDelegate.m */; }; 30 | 1FDF389A194AE9660000C12B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1FDF3899194AE9660000C12B /* Images.xcassets */; }; 31 | 1FDF38A1194AE9660000C12B /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FDF38A0194AE9660000C12B /* XCTest.framework */; }; 32 | 1FDF38A2194AE9660000C12B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FDF3881194AE9660000C12B /* Cocoa.framework */; }; 33 | 1FDF38AA194AE9660000C12B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1FDF38A8194AE9660000C12B /* InfoPlist.strings */; }; 34 | 1FDF38AC194AE9660000C12B /* BetterXibTestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FDF38AB194AE9660000C12B /* BetterXibTestTests.m */; }; 35 | 1FEE29D319503FDD000AED40 /* TProject.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FEE29D219503FDD000AED40 /* TProject.m */; }; 36 | 1FEE29D519504CF5000AED40 /* TProject.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FEE29D219503FDD000AED40 /* TProject.m */; }; 37 | /* End PBXBuildFile section */ 38 | 39 | /* Begin PBXContainerItemProxy section */ 40 | 1FDF38A3194AE9660000C12B /* PBXContainerItemProxy */ = { 41 | isa = PBXContainerItemProxy; 42 | containerPortal = 1FDF385C194AE1070000C12B /* Project object */; 43 | proxyType = 1; 44 | remoteGlobalIDString = 1FDF387F194AE9660000C12B; 45 | remoteInfo = BetterXibTest; 46 | }; 47 | /* End PBXContainerItemProxy section */ 48 | 49 | /* Begin PBXFileReference section */ 50 | 1F8C1515194FF751006DA9B3 /* IOSStoryboardTemplate.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = IOSStoryboardTemplate.xml; sourceTree = ""; }; 51 | 1F9FFE7F194C0E9800465172 /* AddProjectWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddProjectWindowController.h; sourceTree = ""; }; 52 | 1F9FFE80194C0E9800465172 /* AddProjectWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddProjectWindowController.m; sourceTree = ""; }; 53 | 1F9FFE81194C0E9800465172 /* AddProjectWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AddProjectWindowController.xib; sourceTree = ""; }; 54 | 1F9FFE86194C150100465172 /* MacTemplate.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = MacTemplate.xml; sourceTree = ""; }; 55 | 1F9FFE89194C151400465172 /* IOSTemplate.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = IOSTemplate.xml; sourceTree = ""; }; 56 | 1FDF3864194AE1070000C12B /* BetterXib.xcplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BetterXib.xcplugin; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 1FDF3867194AE1070000C12B /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 58 | 1FDF3869194AE1070000C12B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 59 | 1FDF386D194AE1070000C12B /* BetterXib-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BetterXib-Info.plist"; sourceTree = ""; }; 60 | 1FDF386F194AE1070000C12B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 61 | 1FDF3871194AE1070000C12B /* BetterXib.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BetterXib.h; sourceTree = ""; }; 62 | 1FDF3872194AE1070000C12B /* BetterXib.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BetterXib.m; sourceTree = ""; }; 63 | 1FDF3874194AE1070000C12B /* BetterXib-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BetterXib-Prefix.pch"; sourceTree = ""; }; 64 | 1FDF3880194AE9660000C12B /* BetterXibTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BetterXibTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | 1FDF3881194AE9660000C12B /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 66 | 1FDF3884194AE9660000C12B /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 67 | 1FDF3885194AE9660000C12B /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 68 | 1FDF3886194AE9660000C12B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 69 | 1FDF3889194AE9660000C12B /* BetterXibTest-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BetterXibTest-Info.plist"; sourceTree = ""; }; 70 | 1FDF388B194AE9660000C12B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 71 | 1FDF388D194AE9660000C12B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 72 | 1FDF388F194AE9660000C12B /* BetterXibTest-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BetterXibTest-Prefix.pch"; sourceTree = ""; }; 73 | 1FDF3891194AE9660000C12B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 74 | 1FDF3893194AE9660000C12B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 75 | 1FDF3894194AE9660000C12B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 76 | 1FDF3897194AE9660000C12B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 77 | 1FDF3899194AE9660000C12B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 78 | 1FDF389F194AE9660000C12B /* BetterXibTestTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BetterXibTestTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 79 | 1FDF38A0194AE9660000C12B /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 80 | 1FDF38A7194AE9660000C12B /* BetterXibTestTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BetterXibTestTests-Info.plist"; sourceTree = ""; }; 81 | 1FDF38A9194AE9660000C12B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 82 | 1FDF38AB194AE9660000C12B /* BetterXibTestTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BetterXibTestTests.m; sourceTree = ""; }; 83 | 1FEE29D119503FDD000AED40 /* TProject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TProject.h; sourceTree = ""; }; 84 | 1FEE29D219503FDD000AED40 /* TProject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TProject.m; sourceTree = ""; }; 85 | /* End PBXFileReference section */ 86 | 87 | /* Begin PBXFrameworksBuildPhase section */ 88 | 1FDF3861194AE1070000C12B /* Frameworks */ = { 89 | isa = PBXFrameworksBuildPhase; 90 | buildActionMask = 2147483647; 91 | files = ( 92 | 1FDF3868194AE1070000C12B /* AppKit.framework in Frameworks */, 93 | 1FDF386A194AE1070000C12B /* Foundation.framework in Frameworks */, 94 | ); 95 | runOnlyForDeploymentPostprocessing = 0; 96 | }; 97 | 1FDF387D194AE9660000C12B /* Frameworks */ = { 98 | isa = PBXFrameworksBuildPhase; 99 | buildActionMask = 2147483647; 100 | files = ( 101 | 1FDF3882194AE9660000C12B /* Cocoa.framework in Frameworks */, 102 | ); 103 | runOnlyForDeploymentPostprocessing = 0; 104 | }; 105 | 1FDF389C194AE9660000C12B /* Frameworks */ = { 106 | isa = PBXFrameworksBuildPhase; 107 | buildActionMask = 2147483647; 108 | files = ( 109 | 1FDF38A2194AE9660000C12B /* Cocoa.framework in Frameworks */, 110 | 1FDF38A1194AE9660000C12B /* XCTest.framework in Frameworks */, 111 | ); 112 | runOnlyForDeploymentPostprocessing = 0; 113 | }; 114 | /* End PBXFrameworksBuildPhase section */ 115 | 116 | /* Begin PBXGroup section */ 117 | 1FDF385B194AE1070000C12B = { 118 | isa = PBXGroup; 119 | children = ( 120 | 1FDF386B194AE1070000C12B /* BetterXib */, 121 | 1FDF3887194AE9660000C12B /* BetterXibTest */, 122 | 1FDF38A5194AE9660000C12B /* BetterXibTestTests */, 123 | 1FDF3866194AE1070000C12B /* Frameworks */, 124 | 1FDF3865194AE1070000C12B /* Products */, 125 | ); 126 | sourceTree = ""; 127 | }; 128 | 1FDF3865194AE1070000C12B /* Products */ = { 129 | isa = PBXGroup; 130 | children = ( 131 | 1FDF3864194AE1070000C12B /* BetterXib.xcplugin */, 132 | 1FDF3880194AE9660000C12B /* BetterXibTest.app */, 133 | 1FDF389F194AE9660000C12B /* BetterXibTestTests.xctest */, 134 | ); 135 | name = Products; 136 | sourceTree = ""; 137 | }; 138 | 1FDF3866194AE1070000C12B /* Frameworks */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 1FDF3867194AE1070000C12B /* AppKit.framework */, 142 | 1FDF3869194AE1070000C12B /* Foundation.framework */, 143 | 1FDF3881194AE9660000C12B /* Cocoa.framework */, 144 | 1FDF38A0194AE9660000C12B /* XCTest.framework */, 145 | 1FDF3883194AE9660000C12B /* Other Frameworks */, 146 | ); 147 | name = Frameworks; 148 | sourceTree = ""; 149 | }; 150 | 1FDF386B194AE1070000C12B /* BetterXib */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 1FEE29D0195030B0000AED40 /* Model */, 154 | 1FDF3871194AE1070000C12B /* BetterXib.h */, 155 | 1FDF3872194AE1070000C12B /* BetterXib.m */, 156 | 1FDF386C194AE1070000C12B /* Supporting Files */, 157 | 1F9FFE7F194C0E9800465172 /* AddProjectWindowController.h */, 158 | 1F9FFE80194C0E9800465172 /* AddProjectWindowController.m */, 159 | 1F9FFE81194C0E9800465172 /* AddProjectWindowController.xib */, 160 | 1F9FFE86194C150100465172 /* MacTemplate.xml */, 161 | 1F9FFE89194C151400465172 /* IOSTemplate.xml */, 162 | 1F8C1515194FF751006DA9B3 /* IOSStoryboardTemplate.xml */, 163 | ); 164 | path = BetterXib; 165 | sourceTree = ""; 166 | }; 167 | 1FDF386C194AE1070000C12B /* Supporting Files */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | 1FDF386D194AE1070000C12B /* BetterXib-Info.plist */, 171 | 1FDF386E194AE1070000C12B /* InfoPlist.strings */, 172 | 1FDF3874194AE1070000C12B /* BetterXib-Prefix.pch */, 173 | ); 174 | name = "Supporting Files"; 175 | sourceTree = ""; 176 | }; 177 | 1FDF3883194AE9660000C12B /* Other Frameworks */ = { 178 | isa = PBXGroup; 179 | children = ( 180 | 1FDF3884194AE9660000C12B /* AppKit.framework */, 181 | 1FDF3885194AE9660000C12B /* CoreData.framework */, 182 | 1FDF3886194AE9660000C12B /* Foundation.framework */, 183 | ); 184 | name = "Other Frameworks"; 185 | sourceTree = ""; 186 | }; 187 | 1FDF3887194AE9660000C12B /* BetterXibTest */ = { 188 | isa = PBXGroup; 189 | children = ( 190 | 1FDF3893194AE9660000C12B /* AppDelegate.h */, 191 | 1FDF3894194AE9660000C12B /* AppDelegate.m */, 192 | 1FDF3896194AE9660000C12B /* MainMenu.xib */, 193 | 1FDF3899194AE9660000C12B /* Images.xcassets */, 194 | 1FDF3888194AE9660000C12B /* Supporting Files */, 195 | ); 196 | path = BetterXibTest; 197 | sourceTree = ""; 198 | }; 199 | 1FDF3888194AE9660000C12B /* Supporting Files */ = { 200 | isa = PBXGroup; 201 | children = ( 202 | 1FDF3889194AE9660000C12B /* BetterXibTest-Info.plist */, 203 | 1FDF388A194AE9660000C12B /* InfoPlist.strings */, 204 | 1FDF388D194AE9660000C12B /* main.m */, 205 | 1FDF388F194AE9660000C12B /* BetterXibTest-Prefix.pch */, 206 | 1FDF3890194AE9660000C12B /* Credits.rtf */, 207 | ); 208 | name = "Supporting Files"; 209 | sourceTree = ""; 210 | }; 211 | 1FDF38A5194AE9660000C12B /* BetterXibTestTests */ = { 212 | isa = PBXGroup; 213 | children = ( 214 | 1FDF38AB194AE9660000C12B /* BetterXibTestTests.m */, 215 | 1FDF38A6194AE9660000C12B /* Supporting Files */, 216 | ); 217 | path = BetterXibTestTests; 218 | sourceTree = ""; 219 | }; 220 | 1FDF38A6194AE9660000C12B /* Supporting Files */ = { 221 | isa = PBXGroup; 222 | children = ( 223 | 1FDF38A7194AE9660000C12B /* BetterXibTestTests-Info.plist */, 224 | 1FDF38A8194AE9660000C12B /* InfoPlist.strings */, 225 | ); 226 | name = "Supporting Files"; 227 | sourceTree = ""; 228 | }; 229 | 1FEE29D0195030B0000AED40 /* Model */ = { 230 | isa = PBXGroup; 231 | children = ( 232 | 1FEE29D119503FDD000AED40 /* TProject.h */, 233 | 1FEE29D219503FDD000AED40 /* TProject.m */, 234 | ); 235 | path = Model; 236 | sourceTree = ""; 237 | }; 238 | /* End PBXGroup section */ 239 | 240 | /* Begin PBXNativeTarget section */ 241 | 1FDF3863194AE1070000C12B /* BetterXib */ = { 242 | isa = PBXNativeTarget; 243 | buildConfigurationList = 1FDF3877194AE1070000C12B /* Build configuration list for PBXNativeTarget "BetterXib" */; 244 | buildPhases = ( 245 | 1FDF3860194AE1070000C12B /* Sources */, 246 | 1FDF3861194AE1070000C12B /* Frameworks */, 247 | 1FDF3862194AE1070000C12B /* Resources */, 248 | ); 249 | buildRules = ( 250 | ); 251 | dependencies = ( 252 | ); 253 | name = BetterXib; 254 | productName = BetterXib; 255 | productReference = 1FDF3864194AE1070000C12B /* BetterXib.xcplugin */; 256 | productType = "com.apple.product-type.bundle"; 257 | }; 258 | 1FDF387F194AE9660000C12B /* BetterXibTest */ = { 259 | isa = PBXNativeTarget; 260 | buildConfigurationList = 1FDF38AD194AE9660000C12B /* Build configuration list for PBXNativeTarget "BetterXibTest" */; 261 | buildPhases = ( 262 | 1FDF387C194AE9660000C12B /* Sources */, 263 | 1FDF387D194AE9660000C12B /* Frameworks */, 264 | 1FDF387E194AE9660000C12B /* Resources */, 265 | ); 266 | buildRules = ( 267 | ); 268 | dependencies = ( 269 | ); 270 | name = BetterXibTest; 271 | productName = BetterXibTest; 272 | productReference = 1FDF3880194AE9660000C12B /* BetterXibTest.app */; 273 | productType = "com.apple.product-type.application"; 274 | }; 275 | 1FDF389E194AE9660000C12B /* BetterXibTestTests */ = { 276 | isa = PBXNativeTarget; 277 | buildConfigurationList = 1FDF38B0194AE9660000C12B /* Build configuration list for PBXNativeTarget "BetterXibTestTests" */; 278 | buildPhases = ( 279 | 1FDF389B194AE9660000C12B /* Sources */, 280 | 1FDF389C194AE9660000C12B /* Frameworks */, 281 | 1FDF389D194AE9660000C12B /* Resources */, 282 | ); 283 | buildRules = ( 284 | ); 285 | dependencies = ( 286 | 1FDF38A4194AE9660000C12B /* PBXTargetDependency */, 287 | ); 288 | name = BetterXibTestTests; 289 | productName = BetterXibTestTests; 290 | productReference = 1FDF389F194AE9660000C12B /* BetterXibTestTests.xctest */; 291 | productType = "com.apple.product-type.bundle.unit-test"; 292 | }; 293 | /* End PBXNativeTarget section */ 294 | 295 | /* Begin PBXProject section */ 296 | 1FDF385C194AE1070000C12B /* Project object */ = { 297 | isa = PBXProject; 298 | attributes = { 299 | LastUpgradeCheck = 0500; 300 | ORGANIZATIONNAME = duohuo; 301 | TargetAttributes = { 302 | 1FDF389E194AE9660000C12B = { 303 | TestTargetID = 1FDF387F194AE9660000C12B; 304 | }; 305 | }; 306 | }; 307 | buildConfigurationList = 1FDF385F194AE1070000C12B /* Build configuration list for PBXProject "BetterXib" */; 308 | compatibilityVersion = "Xcode 3.2"; 309 | developmentRegion = English; 310 | hasScannedForEncodings = 0; 311 | knownRegions = ( 312 | en, 313 | Base, 314 | ); 315 | mainGroup = 1FDF385B194AE1070000C12B; 316 | productRefGroup = 1FDF3865194AE1070000C12B /* Products */; 317 | projectDirPath = ""; 318 | projectRoot = ""; 319 | targets = ( 320 | 1FDF3863194AE1070000C12B /* BetterXib */, 321 | 1FDF387F194AE9660000C12B /* BetterXibTest */, 322 | 1FDF389E194AE9660000C12B /* BetterXibTestTests */, 323 | ); 324 | }; 325 | /* End PBXProject section */ 326 | 327 | /* Begin PBXResourcesBuildPhase section */ 328 | 1FDF3862194AE1070000C12B /* Resources */ = { 329 | isa = PBXResourcesBuildPhase; 330 | buildActionMask = 2147483647; 331 | files = ( 332 | 1F8C1516194FF751006DA9B3 /* IOSStoryboardTemplate.xml in Resources */, 333 | 1FDF3870194AE1070000C12B /* InfoPlist.strings in Resources */, 334 | 1F9FFE8A194C151400465172 /* IOSTemplate.xml in Resources */, 335 | 1F9FFE87194C150100465172 /* MacTemplate.xml in Resources */, 336 | 1F9FFE83194C0E9800465172 /* AddProjectWindowController.xib in Resources */, 337 | ); 338 | runOnlyForDeploymentPostprocessing = 0; 339 | }; 340 | 1FDF387E194AE9660000C12B /* Resources */ = { 341 | isa = PBXResourcesBuildPhase; 342 | buildActionMask = 2147483647; 343 | files = ( 344 | 1FDF388C194AE9660000C12B /* InfoPlist.strings in Resources */, 345 | 1F9FFE88194C150100465172 /* MacTemplate.xml in Resources */, 346 | 1FDF389A194AE9660000C12B /* Images.xcassets in Resources */, 347 | 1FDF3892194AE9660000C12B /* Credits.rtf in Resources */, 348 | 1F9FFE85194C132200465172 /* AddProjectWindowController.xib in Resources */, 349 | 1F7ECBED194C757F00C70AAA /* MainMenu.xib in Resources */, 350 | 1F8C1517194FF751006DA9B3 /* IOSStoryboardTemplate.xml in Resources */, 351 | 1F9FFE8B194C151400465172 /* IOSTemplate.xml in Resources */, 352 | ); 353 | runOnlyForDeploymentPostprocessing = 0; 354 | }; 355 | 1FDF389D194AE9660000C12B /* Resources */ = { 356 | isa = PBXResourcesBuildPhase; 357 | buildActionMask = 2147483647; 358 | files = ( 359 | 1FDF38AA194AE9660000C12B /* InfoPlist.strings in Resources */, 360 | ); 361 | runOnlyForDeploymentPostprocessing = 0; 362 | }; 363 | /* End PBXResourcesBuildPhase section */ 364 | 365 | /* Begin PBXSourcesBuildPhase section */ 366 | 1FDF3860194AE1070000C12B /* Sources */ = { 367 | isa = PBXSourcesBuildPhase; 368 | buildActionMask = 2147483647; 369 | files = ( 370 | 1FEE29D319503FDD000AED40 /* TProject.m in Sources */, 371 | 1FDF3873194AE1070000C12B /* BetterXib.m in Sources */, 372 | 1F9FFE82194C0E9800465172 /* AddProjectWindowController.m in Sources */, 373 | ); 374 | runOnlyForDeploymentPostprocessing = 0; 375 | }; 376 | 1FDF387C194AE9660000C12B /* Sources */ = { 377 | isa = PBXSourcesBuildPhase; 378 | buildActionMask = 2147483647; 379 | files = ( 380 | 1FEE29D519504CF5000AED40 /* TProject.m in Sources */, 381 | 1FDF3895194AE9660000C12B /* AppDelegate.m in Sources */, 382 | 1F9FFE84194C131D00465172 /* AddProjectWindowController.m in Sources */, 383 | 1FDF388E194AE9660000C12B /* main.m in Sources */, 384 | ); 385 | runOnlyForDeploymentPostprocessing = 0; 386 | }; 387 | 1FDF389B194AE9660000C12B /* Sources */ = { 388 | isa = PBXSourcesBuildPhase; 389 | buildActionMask = 2147483647; 390 | files = ( 391 | 1FDF38AC194AE9660000C12B /* BetterXibTestTests.m in Sources */, 392 | ); 393 | runOnlyForDeploymentPostprocessing = 0; 394 | }; 395 | /* End PBXSourcesBuildPhase section */ 396 | 397 | /* Begin PBXTargetDependency section */ 398 | 1FDF38A4194AE9660000C12B /* PBXTargetDependency */ = { 399 | isa = PBXTargetDependency; 400 | target = 1FDF387F194AE9660000C12B /* BetterXibTest */; 401 | targetProxy = 1FDF38A3194AE9660000C12B /* PBXContainerItemProxy */; 402 | }; 403 | /* End PBXTargetDependency section */ 404 | 405 | /* Begin PBXVariantGroup section */ 406 | 1FDF386E194AE1070000C12B /* InfoPlist.strings */ = { 407 | isa = PBXVariantGroup; 408 | children = ( 409 | 1FDF386F194AE1070000C12B /* en */, 410 | ); 411 | name = InfoPlist.strings; 412 | sourceTree = ""; 413 | }; 414 | 1FDF388A194AE9660000C12B /* InfoPlist.strings */ = { 415 | isa = PBXVariantGroup; 416 | children = ( 417 | 1FDF388B194AE9660000C12B /* en */, 418 | ); 419 | name = InfoPlist.strings; 420 | sourceTree = ""; 421 | }; 422 | 1FDF3890194AE9660000C12B /* Credits.rtf */ = { 423 | isa = PBXVariantGroup; 424 | children = ( 425 | 1FDF3891194AE9660000C12B /* en */, 426 | ); 427 | name = Credits.rtf; 428 | sourceTree = ""; 429 | }; 430 | 1FDF3896194AE9660000C12B /* MainMenu.xib */ = { 431 | isa = PBXVariantGroup; 432 | children = ( 433 | 1FDF3897194AE9660000C12B /* Base */, 434 | ); 435 | name = MainMenu.xib; 436 | sourceTree = ""; 437 | }; 438 | 1FDF38A8194AE9660000C12B /* InfoPlist.strings */ = { 439 | isa = PBXVariantGroup; 440 | children = ( 441 | 1FDF38A9194AE9660000C12B /* en */, 442 | ); 443 | name = InfoPlist.strings; 444 | sourceTree = ""; 445 | }; 446 | /* End PBXVariantGroup section */ 447 | 448 | /* Begin XCBuildConfiguration section */ 449 | 1FDF3875194AE1070000C12B /* Debug */ = { 450 | isa = XCBuildConfiguration; 451 | buildSettings = { 452 | ALWAYS_SEARCH_USER_PATHS = NO; 453 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 454 | CLANG_CXX_LIBRARY = "libc++"; 455 | CLANG_ENABLE_OBJC_ARC = YES; 456 | CLANG_WARN_BOOL_CONVERSION = YES; 457 | CLANG_WARN_CONSTANT_CONVERSION = YES; 458 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 459 | CLANG_WARN_EMPTY_BODY = YES; 460 | CLANG_WARN_ENUM_CONVERSION = YES; 461 | CLANG_WARN_INT_CONVERSION = YES; 462 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 463 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 464 | COPY_PHASE_STRIP = NO; 465 | GCC_C_LANGUAGE_STANDARD = gnu99; 466 | GCC_DYNAMIC_NO_PIC = NO; 467 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 468 | GCC_OPTIMIZATION_LEVEL = 0; 469 | GCC_PREPROCESSOR_DEFINITIONS = ( 470 | "DEBUG=1", 471 | "$(inherited)", 472 | ); 473 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 474 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 475 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 476 | GCC_WARN_UNDECLARED_SELECTOR = YES; 477 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 478 | GCC_WARN_UNUSED_FUNCTION = YES; 479 | GCC_WARN_UNUSED_VARIABLE = YES; 480 | MACOSX_DEPLOYMENT_TARGET = 10.8; 481 | ONLY_ACTIVE_ARCH = YES; 482 | SDKROOT = macosx; 483 | }; 484 | name = Debug; 485 | }; 486 | 1FDF3876194AE1070000C12B /* Release */ = { 487 | isa = XCBuildConfiguration; 488 | buildSettings = { 489 | ALWAYS_SEARCH_USER_PATHS = NO; 490 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 491 | CLANG_CXX_LIBRARY = "libc++"; 492 | CLANG_ENABLE_OBJC_ARC = YES; 493 | CLANG_WARN_BOOL_CONVERSION = YES; 494 | CLANG_WARN_CONSTANT_CONVERSION = YES; 495 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 496 | CLANG_WARN_EMPTY_BODY = YES; 497 | CLANG_WARN_ENUM_CONVERSION = YES; 498 | CLANG_WARN_INT_CONVERSION = YES; 499 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 500 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 501 | COPY_PHASE_STRIP = YES; 502 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 503 | ENABLE_NS_ASSERTIONS = NO; 504 | GCC_C_LANGUAGE_STANDARD = gnu99; 505 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 506 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 507 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 508 | GCC_WARN_UNDECLARED_SELECTOR = YES; 509 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 510 | GCC_WARN_UNUSED_FUNCTION = YES; 511 | GCC_WARN_UNUSED_VARIABLE = YES; 512 | MACOSX_DEPLOYMENT_TARGET = 10.8; 513 | SDKROOT = macosx; 514 | }; 515 | name = Release; 516 | }; 517 | 1FDF3878194AE1070000C12B /* Debug */ = { 518 | isa = XCBuildConfiguration; 519 | buildSettings = { 520 | COMBINE_HIDPI_IMAGES = YES; 521 | DEPLOYMENT_LOCATION = YES; 522 | DSTROOT = "$(HOME)"; 523 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 524 | GCC_PREFIX_HEADER = "BetterXib/BetterXib-Prefix.pch"; 525 | INFOPLIST_FILE = "BetterXib/BetterXib-Info.plist"; 526 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins"; 527 | PRODUCT_NAME = "$(TARGET_NAME)"; 528 | WRAPPER_EXTENSION = xcplugin; 529 | }; 530 | name = Debug; 531 | }; 532 | 1FDF3879194AE1070000C12B /* Release */ = { 533 | isa = XCBuildConfiguration; 534 | buildSettings = { 535 | COMBINE_HIDPI_IMAGES = YES; 536 | DEPLOYMENT_LOCATION = YES; 537 | DSTROOT = "$(HOME)"; 538 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 539 | GCC_PREFIX_HEADER = "BetterXib/BetterXib-Prefix.pch"; 540 | INFOPLIST_FILE = "BetterXib/BetterXib-Info.plist"; 541 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins"; 542 | PRODUCT_NAME = "$(TARGET_NAME)"; 543 | WRAPPER_EXTENSION = xcplugin; 544 | }; 545 | name = Release; 546 | }; 547 | 1FDF38AE194AE9660000C12B /* Debug */ = { 548 | isa = XCBuildConfiguration; 549 | buildSettings = { 550 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 551 | COMBINE_HIDPI_IMAGES = YES; 552 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 553 | GCC_PREFIX_HEADER = "BetterXibTest/BetterXibTest-Prefix.pch"; 554 | GCC_PREPROCESSOR_DEFINITIONS = ( 555 | "DEBUG=1", 556 | "$(inherited)", 557 | ); 558 | INFOPLIST_FILE = "BetterXibTest/BetterXibTest-Info.plist"; 559 | PRODUCT_NAME = "$(TARGET_NAME)"; 560 | WRAPPER_EXTENSION = app; 561 | }; 562 | name = Debug; 563 | }; 564 | 1FDF38AF194AE9660000C12B /* Release */ = { 565 | isa = XCBuildConfiguration; 566 | buildSettings = { 567 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 568 | COMBINE_HIDPI_IMAGES = YES; 569 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 570 | GCC_PREFIX_HEADER = "BetterXibTest/BetterXibTest-Prefix.pch"; 571 | INFOPLIST_FILE = "BetterXibTest/BetterXibTest-Info.plist"; 572 | PRODUCT_NAME = "$(TARGET_NAME)"; 573 | WRAPPER_EXTENSION = app; 574 | }; 575 | name = Release; 576 | }; 577 | 1FDF38B1194AE9660000C12B /* Debug */ = { 578 | isa = XCBuildConfiguration; 579 | buildSettings = { 580 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/BetterXibTest.app/Contents/MacOS/BetterXibTest"; 581 | COMBINE_HIDPI_IMAGES = YES; 582 | FRAMEWORK_SEARCH_PATHS = ( 583 | "$(DEVELOPER_FRAMEWORKS_DIR)", 584 | "$(inherited)", 585 | ); 586 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 587 | GCC_PREFIX_HEADER = "BetterXibTest/BetterXibTest-Prefix.pch"; 588 | GCC_PREPROCESSOR_DEFINITIONS = ( 589 | "DEBUG=1", 590 | "$(inherited)", 591 | ); 592 | INFOPLIST_FILE = "BetterXibTestTests/BetterXibTestTests-Info.plist"; 593 | PRODUCT_NAME = "$(TARGET_NAME)"; 594 | TEST_HOST = "$(BUNDLE_LOADER)"; 595 | WRAPPER_EXTENSION = xctest; 596 | }; 597 | name = Debug; 598 | }; 599 | 1FDF38B2194AE9660000C12B /* Release */ = { 600 | isa = XCBuildConfiguration; 601 | buildSettings = { 602 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/BetterXibTest.app/Contents/MacOS/BetterXibTest"; 603 | COMBINE_HIDPI_IMAGES = YES; 604 | FRAMEWORK_SEARCH_PATHS = ( 605 | "$(DEVELOPER_FRAMEWORKS_DIR)", 606 | "$(inherited)", 607 | ); 608 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 609 | GCC_PREFIX_HEADER = "BetterXibTest/BetterXibTest-Prefix.pch"; 610 | INFOPLIST_FILE = "BetterXibTestTests/BetterXibTestTests-Info.plist"; 611 | PRODUCT_NAME = "$(TARGET_NAME)"; 612 | TEST_HOST = "$(BUNDLE_LOADER)"; 613 | WRAPPER_EXTENSION = xctest; 614 | }; 615 | name = Release; 616 | }; 617 | /* End XCBuildConfiguration section */ 618 | 619 | /* Begin XCConfigurationList section */ 620 | 1FDF385F194AE1070000C12B /* Build configuration list for PBXProject "BetterXib" */ = { 621 | isa = XCConfigurationList; 622 | buildConfigurations = ( 623 | 1FDF3875194AE1070000C12B /* Debug */, 624 | 1FDF3876194AE1070000C12B /* Release */, 625 | ); 626 | defaultConfigurationIsVisible = 0; 627 | defaultConfigurationName = Release; 628 | }; 629 | 1FDF3877194AE1070000C12B /* Build configuration list for PBXNativeTarget "BetterXib" */ = { 630 | isa = XCConfigurationList; 631 | buildConfigurations = ( 632 | 1FDF3878194AE1070000C12B /* Debug */, 633 | 1FDF3879194AE1070000C12B /* Release */, 634 | ); 635 | defaultConfigurationIsVisible = 0; 636 | defaultConfigurationName = Release; 637 | }; 638 | 1FDF38AD194AE9660000C12B /* Build configuration list for PBXNativeTarget "BetterXibTest" */ = { 639 | isa = XCConfigurationList; 640 | buildConfigurations = ( 641 | 1FDF38AE194AE9660000C12B /* Debug */, 642 | 1FDF38AF194AE9660000C12B /* Release */, 643 | ); 644 | defaultConfigurationIsVisible = 0; 645 | defaultConfigurationName = Release; 646 | }; 647 | 1FDF38B0194AE9660000C12B /* Build configuration list for PBXNativeTarget "BetterXibTestTests" */ = { 648 | isa = XCConfigurationList; 649 | buildConfigurations = ( 650 | 1FDF38B1194AE9660000C12B /* Debug */, 651 | 1FDF38B2194AE9660000C12B /* Release */, 652 | ); 653 | defaultConfigurationIsVisible = 0; 654 | defaultConfigurationName = Release; 655 | }; 656 | /* End XCConfigurationList section */ 657 | }; 658 | rootObject = 1FDF385C194AE1070000C12B /* Project object */; 659 | } 660 | -------------------------------------------------------------------------------- /BetterXib.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BetterXib.xcodeproj/project.xcworkspace/xcuserdata/zhang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github-xiaogang/BetterXib/ccbd13401e7f527a191c36fe479eefe6703f1ce7/BetterXib.xcodeproj/project.xcworkspace/xcuserdata/zhang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /BetterXib.xcodeproj/xcuserdata/zhang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /BetterXib.xcodeproj/xcuserdata/zhang.xcuserdatad/xcschemes/BetterXib.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 44 | 45 | 51 | 52 | 54 | 55 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /BetterXib.xcodeproj/xcuserdata/zhang.xcuserdatad/xcschemes/BetterXibTest.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /BetterXib.xcodeproj/xcuserdata/zhang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | BetterXib.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | BetterXibTest.xcscheme 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 1FDF3863194AE1070000C12B 21 | 22 | primary 23 | 24 | 25 | 1FDF387F194AE9660000C12B 26 | 27 | primary 28 | 29 | 30 | 1FDF389E194AE9660000C12B 31 | 32 | primary 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /BetterXib.xcplugin/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 12F37 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | BetterXib 11 | CFBundleIdentifier 12 | net.duohuo.BetterXib 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | BetterXib 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | DTCompiler 26 | com.apple.compilers.llvm.clang.1_0 27 | DTPlatformBuild 28 | 5A1413 29 | DTPlatformVersion 30 | GM 31 | DTSDKBuild 32 | 12D75 33 | DTSDKName 34 | macosx10.8 35 | DTXcode 36 | 0500 37 | DTXcodeBuild 38 | 5A1413 39 | DVTPlugInCompatibilityUUIDs 40 | 41 | 640F884E-CE55-4B40-87C0-8869546CAB7A 42 | 37B30044-3B14-46BA-ABAA-F01000C27B63 43 | A2E4D43F-41F4-4FB9-BB94-7177011C9AED 44 | 45 | NSPrincipalClass 46 | BetterXib 47 | XC4Compatible 48 | 49 | XC5Compatible 50 | 51 | XCGCReady 52 | 53 | XCPluginHasUI 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /BetterXib.xcplugin/Contents/MacOS/BetterXib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github-xiaogang/BetterXib/ccbd13401e7f527a191c36fe479eefe6703f1ce7/BetterXib.xcplugin/Contents/MacOS/BetterXib -------------------------------------------------------------------------------- /BetterXib.xcplugin/Contents/Resources/AddProjectWindowController.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github-xiaogang/BetterXib/ccbd13401e7f527a191c36fe479eefe6703f1ce7/BetterXib.xcplugin/Contents/Resources/AddProjectWindowController.nib -------------------------------------------------------------------------------- /BetterXib.xcplugin/Contents/Resources/IOSStoryboardTemplate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /BetterXib.xcplugin/Contents/Resources/IOSTemplate.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github-xiaogang/BetterXib/ccbd13401e7f527a191c36fe479eefe6703f1ce7/BetterXib.xcplugin/Contents/Resources/IOSTemplate.nib -------------------------------------------------------------------------------- /BetterXib.xcplugin/Contents/Resources/IOSTemplate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /BetterXib.xcplugin/Contents/Resources/MacTemplate.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github-xiaogang/BetterXib/ccbd13401e7f527a191c36fe479eefe6703f1ce7/BetterXib.xcplugin/Contents/Resources/MacTemplate.nib -------------------------------------------------------------------------------- /BetterXib.xcplugin/Contents/Resources/MacTemplate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /BetterXib.xcplugin/Contents/Resources/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github-xiaogang/BetterXib/ccbd13401e7f527a191c36fe479eefe6703f1ce7/BetterXib.xcplugin/Contents/Resources/en.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /BetterXib/AddProjectWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AddProjectWindowController.h 3 | // BetterXib 4 | // 5 | // Created by 张小刚 on 14-6-14. 6 | // Copyright (c) 2014年 duohuo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AddProjectWindowController : NSWindowController 12 | 13 | @property (nonatomic, copy) void (^completeBlock)(NSString * projectName, BOOL isPlatformIOS, BOOL xibOrStoryboard); 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /BetterXib/AddProjectWindowController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AddProjectWindowController.m 3 | // BetterXib 4 | // 5 | // Created by 张小刚 on 14-6-14. 6 | // Copyright (c) 2014年 duohuo. All rights reserved. 7 | // 8 | 9 | #import "AddProjectWindowController.h" 10 | 11 | @interface AddProjectWindowController () 12 | 13 | @property (weak) IBOutlet NSTextField *projectNameTextfield; 14 | @property (weak) IBOutlet NSMatrix *typeMatrix; 15 | @property (weak) IBOutlet NSMatrix *storyboardMatrix; 16 | 17 | 18 | @end 19 | 20 | @implementation AddProjectWindowController 21 | 22 | - (void)windowDidLoad 23 | { 24 | [super windowDidLoad]; 25 | // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. 26 | } 27 | 28 | - (BOOL)validateInputValues; 29 | { 30 | BOOL isPassed = NO; 31 | NSString * alertString = nil; 32 | do { 33 | alertString = @"projectName不能为空"; 34 | if(self.projectNameTextfield.stringValue.length == 0) break; 35 | isPassed = YES; 36 | } while (false); 37 | if(!isPassed){ 38 | NSAlert * alert = [NSAlert alertWithMessageText:@"提示" defaultButton:@"确定" alternateButton:nil otherButton:nil informativeTextWithFormat:@"%@",alertString]; 39 | [alert runModal]; 40 | } 41 | return isPassed; 42 | } 43 | 44 | - (IBAction)typeMartrixValueChanged:(NSMatrix *)sender { 45 | if(self.typeMatrix.selectedRow == 0){ 46 | //iOS 47 | [self.storyboardMatrix setHidden:NO]; 48 | }else{ 49 | //Mac 50 | [self.storyboardMatrix setHidden:YES]; 51 | } 52 | } 53 | 54 | - (IBAction)doneButtonPressed:(id)sender { 55 | if(![self validateInputValues]) return; 56 | if(_completeBlock){ 57 | _completeBlock(self.projectNameTextfield.stringValue,(self.typeMatrix.selectedRow == 0),(self.storyboardMatrix.selectedRow == 0)); 58 | } 59 | } 60 | 61 | - (IBAction)cancelButtonPressed:(id)sender { 62 | [self close]; 63 | } 64 | 65 | @end 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /BetterXib/AddProjectWindowController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 123 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /BetterXib/BetterXib-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | net.duohuo.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | DVTPlugInCompatibilityUUIDs 26 | 27 | 640F884E-CE55-4B40-87C0-8869546CAB7A 28 | 37B30044-3B14-46BA-ABAA-F01000C27B63 29 | A2E4D43F-41F4-4FB9-BB94-7177011C9AED 30 | 31 | NSPrincipalClass 32 | BetterXib 33 | XC4Compatible 34 | 35 | XC5Compatible 36 | 37 | XCGCReady 38 | 39 | XCPluginHasUI 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /BetterXib/BetterXib-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /BetterXib/BetterXib.h: -------------------------------------------------------------------------------- 1 | // 2 | // BetterXib.h 3 | // BetterXib 4 | // 5 | // Created by 张小刚 on 14-6-13. 6 | // Copyright (c) 2014年 duohuo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BetterXib : NSObject 12 | 13 | @end -------------------------------------------------------------------------------- /BetterXib/BetterXib.m: -------------------------------------------------------------------------------- 1 | // 2 | // BetterXib.m 3 | // BetterXib 4 | // 5 | // Created by 张小刚 on 14-6-13. 6 | // Copyright (c) 2014年 duohuo. All rights reserved. 7 | // 8 | 9 | #import "BetterXib.h" 10 | #import "AddProjectWindowController.h" 11 | #import "TProject.h" 12 | 13 | static NSString * const PLUGIN_NAME = @"BetterXib"; 14 | static NSString * const WORKING_DIR = @".BetterXib"; 15 | static NSString * const PROJECT_DIR = @"Projects"; 16 | static NSString * const HELLO_FILE = @"hello.plist"; 17 | static NSString * const XIB_SUFFIX = @"xib"; 18 | static NSString * const STORYBOARD_SUFFIX = @"storyboard"; 19 | static NSString * const PLIST_LAST_PROJECT = @"lastProjectName"; 20 | 21 | static BetterXib *sharedPlugin; 22 | 23 | @interface BetterXib() 24 | { 25 | NSArray * _projects; 26 | TProject * _currentProject; 27 | AddProjectWindowController * _addProjectWindowController; 28 | } 29 | 30 | @property (nonatomic, strong) NSBundle *bundle; 31 | 32 | @end 33 | 34 | @implementation BetterXib 35 | 36 | + (void)pluginDidLoad:(NSBundle *)plugin 37 | { 38 | static id sharedPlugin = nil; 39 | static dispatch_once_t onceToken; 40 | NSString *currentApplicationName = [[NSBundle mainBundle] infoDictionary][@"CFBundleName"]; 41 | if ([currentApplicationName isEqual:@"Xcode"]) { 42 | dispatch_once(&onceToken, ^{ 43 | sharedPlugin = [[self alloc] initWithBundle:plugin]; 44 | }); 45 | } 46 | } 47 | 48 | - (id)initWithBundle:(NSBundle *)plugin 49 | { 50 | if (self = [super init]) { 51 | // reference to plugin's bundle, for resource acccess 52 | self.bundle = plugin; 53 | [self initEnvironment]; 54 | [self loadData]; 55 | [self createMenu]; 56 | } 57 | return self; 58 | } 59 | 60 | - (void)initEnvironment 61 | { 62 | //创建工作环境 63 | NSFileManager * fileManager = [NSFileManager defaultManager]; 64 | BOOL isDirectory; 65 | BOOL isExists = [fileManager fileExistsAtPath:[self projectsDir] isDirectory:&isDirectory]; 66 | if(!isExists || !isDirectory){ 67 | __autoreleasing NSError * error = nil; 68 | if(![fileManager createDirectoryAtPath:[self projectsDir] withIntermediateDirectories:YES attributes:nil error:&error]){ 69 | NSLog(@"create project dir error : %@",error); 70 | abort(); 71 | } 72 | } 73 | } 74 | 75 | - (void)loadData 76 | { 77 | NSFileManager * fileManager = [NSFileManager defaultManager]; 78 | NSError * error = nil; 79 | NSArray * projectNames = [fileManager contentsOfDirectoryAtPath:[self projectsDir] error:&error]; 80 | NSMutableArray * projects = [NSMutableArray array]; 81 | 82 | NSString * xibSuffix = [NSString stringWithFormat:@".%@",XIB_SUFFIX]; 83 | NSString * storyboardSuffix = [NSString stringWithFormat:@".%@",STORYBOARD_SUFFIX]; 84 | for (NSString * projectName in projectNames) { 85 | if([projectName hasSuffix:xibSuffix] || [projectName hasSuffix:storyboardSuffix]){ 86 | if([projectName hasSuffix:xibSuffix]){ 87 | NSString * name = [projectName stringByReplacingOccurrencesOfString:xibSuffix withString:@""]; 88 | if(name.length > 0){ 89 | TProject * project = [[TProject alloc] init]; 90 | project.name = name; 91 | project.type = ProjectTypeXib; 92 | [projects addObject:project]; 93 | } 94 | }else if([projectName hasSuffix:storyboardSuffix]){ 95 | NSString * name = [projectName stringByReplacingOccurrencesOfString:storyboardSuffix withString:@""]; 96 | if(name.length > 0){ 97 | TProject * project = [[TProject alloc] init]; 98 | project.name = name; 99 | project.type = ProjectTypeStoryboard; 100 | [projects addObject:project]; 101 | } 102 | } 103 | } 104 | } 105 | _projects = projects; 106 | if(_projects.count > 0){ 107 | //current projectName; 108 | NSDictionary * helloData = [NSDictionary dictionaryWithContentsOfFile:[self helloPath]]; 109 | NSString * lastProjectName = helloData[PLIST_LAST_PROJECT]; 110 | TProject * lastProject = nil; 111 | if(lastProjectName.length > 0){ 112 | for (TProject * project in _projects) { 113 | if([project.name isEqualToString:lastProjectName]){ 114 | lastProject = project; 115 | break; 116 | } 117 | } 118 | } 119 | if(!lastProject){ 120 | lastProject = _projects[0]; 121 | } 122 | _currentProject = lastProject; 123 | } 124 | } 125 | 126 | - (void)createMenu 127 | { 128 | NSMenuItem *menuItem = [[NSApp mainMenu] itemWithTitle:@"Window"]; 129 | if (!menuItem){ 130 | NSLog(@"not found Window Menu"); 131 | } 132 | [[menuItem submenu] addItem:[NSMenuItem separatorItem]]; 133 | NSMenuItem *mainMenu = [[NSMenuItem alloc] initWithTitle:[NSString stringWithFormat:@"%@",PLUGIN_NAME] action:@selector(doMainMenu) keyEquivalent:@"g"]; 134 | [mainMenu setKeyEquivalentModifierMask:NSControlKeyMask]; 135 | [mainMenu setTarget:self]; 136 | [[menuItem submenu] addItem:mainMenu]; 137 | if(!mainMenu) return; 138 | NSMenu * subMenu = [[NSMenu alloc] init]; 139 | [mainMenu setSubmenu:subMenu]; 140 | //add project Menu 141 | for (int i=0; i<_projects.count; i++) { 142 | TProject * project = _projects[i]; 143 | NSString * projectName = project.name; 144 | NSMenuItem *projectMenu = [[NSMenuItem alloc] initWithTitle:projectName action:@selector(doProjectMenu:) keyEquivalent:@""]; 145 | if(project == _currentProject){ 146 | [projectMenu setState:NSOnState]; 147 | } 148 | [projectMenu setTarget:self]; 149 | [[mainMenu submenu] addItem:projectMenu]; 150 | } 151 | if(_projects.count > 0){ 152 | [[mainMenu submenu] addItem:[NSMenuItem separatorItem]]; 153 | } 154 | [[mainMenu submenu] addItem:[NSMenuItem separatorItem]]; 155 | //new project menu 156 | NSMenuItem *addMenu = [[NSMenuItem alloc] initWithTitle:@"新建" action:@selector(doAddProject) keyEquivalent:@""]; 157 | [addMenu setTarget:self]; 158 | [[mainMenu submenu] addItem:addMenu]; 159 | //working dir menu 160 | NSMenuItem *homeMenu = [[NSMenuItem alloc] initWithTitle:@"工作目录" action:@selector(doGoHome) keyEquivalent:@""]; 161 | [homeMenu setTarget:self]; 162 | [[mainMenu submenu] addItem:homeMenu]; 163 | } 164 | 165 | - (void)doAddProject 166 | { 167 | __block typeof(self) bself = self; 168 | if(!_addProjectWindowController){ 169 | _addProjectWindowController = [[AddProjectWindowController alloc] initWithWindowNibName:@"AddProjectWindowController"]; 170 | [_addProjectWindowController setCompleteBlock:^(NSString *projectName, BOOL isPlatformIOS, BOOL xibOrStoryboard) { 171 | //projectName exist ? 172 | BOOL projectNameExists = NO; 173 | for (TProject * project in bself->_projects) { 174 | NSString * name = project.name; 175 | if([name isEqualToString:projectName]){ 176 | projectNameExists = YES; 177 | break; 178 | } 179 | } 180 | if(projectNameExists){ 181 | NSAlert * alert = [NSAlert alertWithMessageText:@"提示" defaultButton:@"确定" alternateButton:nil otherButton:nil informativeTextWithFormat:@"%@",@"该项目名已存在"]; 182 | [alert runModal]; 183 | }else{ 184 | NSData * templateData = nil; 185 | NSString * templatePath = [bself templatePathForPlatform:isPlatformIOS xibOrStoryboard:xibOrStoryboard]; 186 | templateData = [NSData dataWithContentsOfFile:templatePath]; 187 | NSString * projectPath = [bself projectPathFor:projectName platform:isPlatformIOS xibOrStoryboard:xibOrStoryboard]; 188 | __autoreleasing NSError * error = nil; 189 | if(![templateData writeToFile:projectPath options:0 error:&error]){ 190 | NSLog(@"%@",error); 191 | }else{ 192 | //add new project menu 193 | TProject * project = [[TProject alloc] initWithName:projectName platform:isPlatformIOS xibType:xibOrStoryboard]; 194 | NSMutableArray * mutableProjects = [NSMutableArray arrayWithArray:bself->_projects ? bself->_projects : @[]]; 195 | [mutableProjects insertObject:project atIndex:0]; 196 | 197 | NSMenu * mainMenu = [bself mainMenu]; 198 | if(!mainMenu) return; 199 | NSMenuItem * newItem = [[NSMenuItem alloc] initWithTitle:projectName action:@selector(doProjectMenu:) keyEquivalent:@""]; 200 | [newItem setTarget:bself]; 201 | [mainMenu insertItem:newItem atIndex:0]; 202 | 203 | [bself setCurrentProject:project]; 204 | [bself doMainMenu]; //手动 205 | [bself->_addProjectWindowController close]; 206 | bself->_addProjectWindowController = nil; 207 | 208 | } 209 | } 210 | }]; 211 | } 212 | NSScreen * screen = [NSScreen mainScreen]; 213 | CGFloat screenWidth = screen.frame.size.width; 214 | CGFloat screenHeight = screen.frame.size.height; 215 | CGFloat windowWidth = _addProjectWindowController.window.frame.size.width; 216 | CGFloat windowHeight = _addProjectWindowController.window.frame.size.height; 217 | [_addProjectWindowController.window setFrameOrigin :NSMakePoint((screenWidth - windowWidth)/2, (screenHeight - windowHeight - 100))]; 218 | [_addProjectWindowController showWindow:nil]; 219 | } 220 | 221 | - (void)doGoHome 222 | { 223 | [[NSWorkspace sharedWorkspace] openFile:[self workingDir] withApplication:@"Finder"]; 224 | } 225 | 226 | - (void)doMainMenu{ 227 | if(!_currentProject){ 228 | [self doAddProject]; 229 | }else{ 230 | NSString * projectPath = [self projectPath:_currentProject]; 231 | if(![[NSWorkspace sharedWorkspace] openFile:projectPath withApplication:@"Xcode"]){ 232 | NSLog(@"open fail"); 233 | } 234 | } 235 | } 236 | 237 | - (void)doProjectMenu: (NSMenuItem *)projectMenu{ 238 | NSString * projectName = projectMenu.title; 239 | TProject * project = [self projectByName:projectName]; 240 | NSString * projectPath = [self projectPath:project]; 241 | if(projectPath.length > 0){ 242 | [[NSWorkspace sharedWorkspace] openFile:projectPath withApplication:@"Xcode"]; 243 | [self setCurrentProject:project]; 244 | } 245 | } 246 | 247 | - (void)setCurrentProject: (TProject *)project 248 | { 249 | if(project != _currentProject){ 250 | _currentProject = project; 251 | //save 252 | NSDictionary * data = @{ 253 | PLIST_LAST_PROJECT : project.name, 254 | }; 255 | [data writeToFile:[self helloPath] atomically:YES]; 256 | 257 | NSArray * subMenus = [[self mainMenu] itemArray]; 258 | for (NSMenuItem * menuItem in subMenus) { 259 | menuItem.state = NSOffState; 260 | } 261 | [[self projectMenuItem:project] setState:NSOnState]; 262 | } 263 | } 264 | 265 | - (NSMenu *)mainMenu 266 | { 267 | NSMenuItem *menuItem = [[NSApp mainMenu] itemWithTitle:@"Window"]; 268 | if (!menuItem){ 269 | NSLog(@"not found Window Menu"); 270 | } 271 | NSMenuItem * mainMenuItem = [[menuItem submenu] itemWithTitle:PLUGIN_NAME]; 272 | if(!mainMenuItem) return nil; 273 | NSMenu * mainMenu = [mainMenuItem submenu]; 274 | return mainMenu; 275 | } 276 | 277 | - (NSMenuItem *)projectMenuItem: (TProject *)project 278 | { 279 | NSMenu * mainMenu = [self mainMenu]; 280 | return [mainMenu itemWithTitle:project.name]; 281 | } 282 | 283 | - (TProject *)projectByName: (NSString *)projectName 284 | { 285 | TProject * targetProject = nil; 286 | for (TProject * project in _projects) { 287 | if([project.name isEqualToString:projectName]){ 288 | targetProject = project; 289 | break; 290 | } 291 | } 292 | return targetProject; 293 | } 294 | 295 | #pragma mark ----------------- util ---------------- 296 | 297 | - (NSString *)workingDir{ 298 | return [NSString stringWithFormat:@"%@/%@",NSHomeDirectory(),WORKING_DIR]; 299 | } 300 | 301 | - (NSString *)projectsDir{ 302 | return [NSString stringWithFormat:@"%@/%@",[self workingDir],PROJECT_DIR]; 303 | } 304 | 305 | - (NSString *)helloPath{ 306 | return [NSString stringWithFormat:@"%@/%@",[self workingDir],HELLO_FILE]; 307 | } 308 | 309 | - (NSString *)projectPath: (TProject *)project{ 310 | if(!project) return nil; 311 | NSString * suffix = project.type == ProjectTypeXib ? XIB_SUFFIX : STORYBOARD_SUFFIX; 312 | return [NSString stringWithFormat:@"%@/%@.%@",[self projectsDir],project.name,suffix]; 313 | } 314 | 315 | - (NSString *)projectPathFor: (NSString *)projectName platform: (BOOL)isPlatformIOS xibOrStoryboard: (BOOL)xibOrStoryboard 316 | { 317 | if(projectName.length == 0) return nil; 318 | NSString * suffix = nil; 319 | { 320 | if(isPlatformIOS){ 321 | //ios 322 | suffix = xibOrStoryboard ? XIB_SUFFIX : STORYBOARD_SUFFIX; 323 | }else{ 324 | //mac 325 | suffix = XIB_SUFFIX; 326 | } 327 | } 328 | return [NSString stringWithFormat:@"%@/%@.%@",[self projectsDir],projectName,suffix]; 329 | } 330 | 331 | - (NSString *)templatePathForPlatform: (BOOL)isPlatformIOS xibOrStoryboard: (BOOL)xibOrStoryboard{ 332 | NSString * resourceName = nil; 333 | { 334 | if(isPlatformIOS){ 335 | //ios 336 | resourceName = xibOrStoryboard ? @"IOSTemplate" : @"IOSStoryboardTemplate"; 337 | }else{ 338 | //mac 339 | resourceName = @"MacTemplate"; 340 | } 341 | } 342 | NSBundle * bundle = [NSBundle bundleForClass:[self class]]; 343 | NSString * templatePath = [bundle pathForResource:resourceName ofType:@"xml"]; 344 | return templatePath; 345 | } 346 | 347 | 348 | @end 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | -------------------------------------------------------------------------------- /BetterXib/IOSStoryboardTemplate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /BetterXib/IOSTemplate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /BetterXib/MacTemplate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /BetterXib/Model/TProject.h: -------------------------------------------------------------------------------- 1 | // 2 | // TProject.h 3 | // BetterXib 4 | // 5 | // Created by 张小刚 on 14-6-17. 6 | // Copyright (c) 2014年 duohuo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum { 12 | ProjectTypeXib = 0, 13 | ProjectTypeStoryboard = 1, 14 | }ProjectType; 15 | 16 | @interface TProject : NSObject 17 | 18 | - (id)initWithName: (NSString *)projectName platform: (BOOL)iosOrMac xibType: (BOOL)xibOrStoryboard; 19 | 20 | @property (nonatomic, retain) NSString * name; 21 | @property (nonatomic, assign) ProjectType type; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /BetterXib/Model/TProject.m: -------------------------------------------------------------------------------- 1 | // 2 | // TProject.m 3 | // BetterXib 4 | // 5 | // Created by 张小刚 on 14-6-17. 6 | // Copyright (c) 2014年 duohuo. All rights reserved. 7 | // 8 | 9 | #import "TProject.h" 10 | 11 | @implementation TProject 12 | 13 | - (id)initWithName: (NSString *)projectName platform: (BOOL)iosOrMac xibType: (BOOL)xibOrStoryboard 14 | { 15 | self = [super init]; 16 | if(self){ 17 | self.name = projectName; 18 | ProjectType type; 19 | if(iosOrMac){ 20 | if(xibOrStoryboard){ 21 | type = ProjectTypeXib; 22 | }else{ 23 | type = ProjectTypeStoryboard; 24 | } 25 | }else{ 26 | type = ProjectTypeXib; 27 | } 28 | self.type = type; 29 | } 30 | return self; 31 | } 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /BetterXib/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /BetterXibTest/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // BetterXibTest 4 | // 5 | // Created by 张小刚 on 14-6-13. 6 | // Copyright (c) 2014年 duohuo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | @property (assign) IBOutlet NSWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /BetterXibTest/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // BetterXibTest 4 | // 5 | // Created by 张小刚 on 14-6-13. 6 | // Copyright (c) 2014年 duohuo. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "AddProjectWindowController.h" 11 | #import "TProject.h" 12 | 13 | static NSString * const PLUGIN_NAME = @"BetterXib"; 14 | static NSString * const WORKING_DIR = @".BetterXib"; 15 | static NSString * const PROJECT_DIR = @"Projects"; 16 | static NSString * const HELLO_FILE = @"hello.plist"; 17 | static NSString * const XIB_SUFFIX = @"xib"; 18 | static NSString * const STORYBOARD_SUFFIX = @"storyboard"; 19 | static NSString * const PLIST_LAST_PROJECT = @"lastProjectName"; 20 | 21 | @interface AppDelegate () 22 | { 23 | NSArray * _projects; 24 | TProject * _currentProject; 25 | AddProjectWindowController * _addProjectWindowController; 26 | } 27 | @end 28 | 29 | @implementation AppDelegate 30 | 31 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 32 | { 33 | // Insert code here to initialize your application 34 | [self go]; 35 | } 36 | 37 | - (void)go 38 | { 39 | [self initEnvironment]; 40 | [self loadData]; 41 | [self createMenu]; 42 | } 43 | 44 | - (void)initEnvironment 45 | { 46 | //创建工作环境 47 | NSFileManager * fileManager = [NSFileManager defaultManager]; 48 | BOOL isDirectory; 49 | BOOL isExists = [fileManager fileExistsAtPath:[self projectsDir] isDirectory:&isDirectory]; 50 | if(!isExists || !isDirectory){ 51 | __autoreleasing NSError * error = nil; 52 | if(![fileManager createDirectoryAtPath:[self projectsDir] withIntermediateDirectories:YES attributes:nil error:&error]){ 53 | NSLog(@"create project dir error : %@",error); 54 | abort(); 55 | } 56 | } 57 | } 58 | 59 | - (void)loadData 60 | { 61 | NSFileManager * fileManager = [NSFileManager defaultManager]; 62 | NSError * error = nil; 63 | NSArray * projectNames = [fileManager contentsOfDirectoryAtPath:[self projectsDir] error:&error]; 64 | NSMutableArray * projects = [NSMutableArray array]; 65 | 66 | NSString * xibSuffix = [NSString stringWithFormat:@".%@",XIB_SUFFIX]; 67 | NSString * storyboardSuffix = [NSString stringWithFormat:@".%@",STORYBOARD_SUFFIX]; 68 | for (NSString * projectName in projectNames) { 69 | if([projectName hasSuffix:xibSuffix] || [projectName hasSuffix:storyboardSuffix]){ 70 | if([projectName hasSuffix:xibSuffix]){ 71 | NSString * name = [projectName stringByReplacingOccurrencesOfString:xibSuffix withString:@""]; 72 | if(name.length > 0){ 73 | TProject * project = [[TProject alloc] init]; 74 | project.name = name; 75 | project.type = ProjectTypeXib; 76 | [projects addObject:project]; 77 | } 78 | }else if([projectName hasSuffix:storyboardSuffix]){ 79 | NSString * name = [projectName stringByReplacingOccurrencesOfString:storyboardSuffix withString:@""]; 80 | if(name.length > 0){ 81 | TProject * project = [[TProject alloc] init]; 82 | project.name = name; 83 | project.type = ProjectTypeStoryboard; 84 | [projects addObject:project]; 85 | } 86 | } 87 | } 88 | } 89 | _projects = projects; 90 | if(_projects.count > 0){ 91 | //current projectName; 92 | NSDictionary * helloData = [NSDictionary dictionaryWithContentsOfFile:[self helloPath]]; 93 | NSString * lastProjectName = helloData[PLIST_LAST_PROJECT]; 94 | TProject * lastProject = nil; 95 | if(lastProjectName.length > 0){ 96 | for (TProject * project in _projects) { 97 | if([project.name isEqualToString:lastProjectName]){ 98 | lastProject = project; 99 | break; 100 | } 101 | } 102 | } 103 | if(!lastProject){ 104 | lastProject = _projects[0]; 105 | } 106 | _currentProject = lastProject; 107 | } 108 | } 109 | 110 | - (void)createMenu 111 | { 112 | NSMenuItem *menuItem = [[NSApp mainMenu] itemWithTitle:@"Window"]; 113 | if (!menuItem){ 114 | NSLog(@"not found Window Menu"); 115 | } 116 | [[menuItem submenu] addItem:[NSMenuItem separatorItem]]; 117 | NSMenuItem *mainMenu = [[NSMenuItem alloc] initWithTitle:[NSString stringWithFormat:@"%@",PLUGIN_NAME] action:@selector(doMainMenu) keyEquivalent:@"g"]; 118 | [mainMenu setKeyEquivalentModifierMask:NSControlKeyMask]; 119 | [mainMenu setTarget:self]; 120 | [[menuItem submenu] addItem:mainMenu]; 121 | if(!mainMenu) return; 122 | NSMenu * subMenu = [[NSMenu alloc] init]; 123 | [mainMenu setSubmenu:subMenu]; 124 | //add project Menu 125 | for (int i=0; i<_projects.count; i++) { 126 | TProject * project = _projects[i]; 127 | NSString * projectName = project.name; 128 | NSMenuItem *projectMenu = [[NSMenuItem alloc] initWithTitle:projectName action:@selector(doProjectMenu:) keyEquivalent:@""]; 129 | if(project == _currentProject){ 130 | [projectMenu setState:NSOnState]; 131 | } 132 | [projectMenu setTarget:self]; 133 | [[mainMenu submenu] addItem:projectMenu]; 134 | } 135 | if(_projects.count > 0){ 136 | [[mainMenu submenu] addItem:[NSMenuItem separatorItem]]; 137 | } 138 | [[mainMenu submenu] addItem:[NSMenuItem separatorItem]]; 139 | //new project menu 140 | NSMenuItem *addMenu = [[NSMenuItem alloc] initWithTitle:@"新建" action:@selector(doAddProject) keyEquivalent:@""]; 141 | [addMenu setTarget:self]; 142 | [[mainMenu submenu] addItem:addMenu]; 143 | //working dir menu 144 | NSMenuItem *homeMenu = [[NSMenuItem alloc] initWithTitle:@"工作目录" action:@selector(doGoHome) keyEquivalent:@""]; 145 | [homeMenu setTarget:self]; 146 | [[mainMenu submenu] addItem:homeMenu]; 147 | } 148 | 149 | - (void)doAddProject 150 | { 151 | __block typeof(self) bself = self; 152 | if(!_addProjectWindowController){ 153 | _addProjectWindowController = [[AddProjectWindowController alloc] initWithWindowNibName:@"AddProjectWindowController"]; 154 | [_addProjectWindowController setCompleteBlock:^(NSString *projectName, BOOL isPlatformIOS, BOOL xibOrStoryboard) { 155 | //projectName exist ? 156 | BOOL projectNameExists = NO; 157 | for (TProject * project in bself->_projects) { 158 | NSString * name = project.name; 159 | if([name isEqualToString:projectName]){ 160 | projectNameExists = YES; 161 | break; 162 | } 163 | } 164 | if(projectNameExists){ 165 | NSAlert * alert = [NSAlert alertWithMessageText:@"提示" defaultButton:@"确定" alternateButton:nil otherButton:nil informativeTextWithFormat:@"%@",@"该项目名已存在"]; 166 | [alert runModal]; 167 | }else{ 168 | NSData * templateData = nil; 169 | NSString * templatePath = [bself templatePathForPlatform:isPlatformIOS xibOrStoryboard:xibOrStoryboard]; 170 | templateData = [NSData dataWithContentsOfFile:templatePath]; 171 | NSString * projectPath = [bself projectPathFor:projectName platform:isPlatformIOS xibOrStoryboard:xibOrStoryboard]; 172 | __autoreleasing NSError * error = nil; 173 | if(![templateData writeToFile:projectPath options:0 error:&error]){ 174 | NSLog(@"%@",error); 175 | }else{ 176 | //add new project menu 177 | TProject * project = [[TProject alloc] initWithName:projectName platform:isPlatformIOS xibType:xibOrStoryboard]; 178 | NSMutableArray * mutableProjects = [NSMutableArray arrayWithArray:bself->_projects ? bself->_projects : @[]]; 179 | [mutableProjects insertObject:project atIndex:0]; 180 | 181 | NSMenu * mainMenu = [bself mainMenu]; 182 | if(!mainMenu) return; 183 | NSMenuItem * newItem = [[NSMenuItem alloc] initWithTitle:projectName action:@selector(doProjectMenu:) keyEquivalent:@""]; 184 | [newItem setTarget:bself]; 185 | [mainMenu insertItem:newItem atIndex:0]; 186 | 187 | [bself setCurrentProject:project]; 188 | [bself doMainMenu]; //手动 189 | [bself->_addProjectWindowController close]; 190 | bself->_addProjectWindowController = nil; 191 | 192 | } 193 | } 194 | }]; 195 | } 196 | NSScreen * screen = [NSScreen mainScreen]; 197 | CGFloat screenWidth = screen.frame.size.width; 198 | CGFloat screenHeight = screen.frame.size.height; 199 | CGFloat windowWidth = _addProjectWindowController.window.frame.size.width; 200 | CGFloat windowHeight = _addProjectWindowController.window.frame.size.height; 201 | [_addProjectWindowController.window setFrameOrigin :NSMakePoint((screenWidth - windowWidth)/2, (screenHeight - windowHeight - 100))]; 202 | [_addProjectWindowController showWindow:nil]; 203 | } 204 | 205 | - (void)doGoHome 206 | { 207 | [[NSWorkspace sharedWorkspace] openFile:[self workingDir] withApplication:@"Finder"]; 208 | } 209 | 210 | - (void)doMainMenu{ 211 | if(!_currentProject){ 212 | [self doAddProject]; 213 | }else{ 214 | NSString * projectPath = [self projectPath:_currentProject]; 215 | if(![[NSWorkspace sharedWorkspace] openFile:projectPath withApplication:@"Xcode"]){ 216 | NSLog(@"open fail"); 217 | } 218 | } 219 | } 220 | 221 | - (void)doProjectMenu: (NSMenuItem *)projectMenu{ 222 | NSString * projectName = projectMenu.title; 223 | TProject * project = [self projectByName:projectName]; 224 | NSString * projectPath = [self projectPath:project]; 225 | if(projectPath.length > 0){ 226 | [[NSWorkspace sharedWorkspace] openFile:projectPath withApplication:@"Xcode"]; 227 | [self setCurrentProject:project]; 228 | } 229 | } 230 | 231 | - (void)setCurrentProject: (TProject *)project 232 | { 233 | if(project != _currentProject){ 234 | _currentProject = project; 235 | //save 236 | NSDictionary * data = @{ 237 | PLIST_LAST_PROJECT : project.name, 238 | }; 239 | [data writeToFile:[self helloPath] atomically:YES]; 240 | 241 | NSArray * subMenus = [[self mainMenu] itemArray]; 242 | for (NSMenuItem * menuItem in subMenus) { 243 | menuItem.state = NSOffState; 244 | } 245 | [[self projectMenuItem:project] setState:NSOnState]; 246 | } 247 | } 248 | 249 | - (NSMenu *)mainMenu 250 | { 251 | NSMenuItem *menuItem = [[NSApp mainMenu] itemWithTitle:@"Window"]; 252 | if (!menuItem){ 253 | NSLog(@"not found Window Menu"); 254 | } 255 | NSMenuItem * mainMenuItem = [[menuItem submenu] itemWithTitle:PLUGIN_NAME]; 256 | if(!mainMenuItem) return nil; 257 | NSMenu * mainMenu = [mainMenuItem submenu]; 258 | return mainMenu; 259 | } 260 | 261 | - (NSMenuItem *)projectMenuItem: (TProject *)project 262 | { 263 | NSMenu * mainMenu = [self mainMenu]; 264 | return [mainMenu itemWithTitle:project.name]; 265 | } 266 | 267 | - (TProject *)projectByName: (NSString *)projectName 268 | { 269 | TProject * targetProject = nil; 270 | for (TProject * project in _projects) { 271 | if([project.name isEqualToString:projectName]){ 272 | targetProject = project; 273 | break; 274 | } 275 | } 276 | return targetProject; 277 | } 278 | 279 | #pragma mark ----------------- util ---------------- 280 | 281 | - (NSString *)workingDir{ 282 | return [NSString stringWithFormat:@"%@/%@",NSHomeDirectory(),WORKING_DIR]; 283 | } 284 | 285 | - (NSString *)projectsDir{ 286 | return [NSString stringWithFormat:@"%@/%@",[self workingDir],PROJECT_DIR]; 287 | } 288 | 289 | - (NSString *)helloPath{ 290 | return [NSString stringWithFormat:@"%@/%@",[self workingDir],HELLO_FILE]; 291 | } 292 | 293 | - (NSString *)projectPath: (TProject *)project{ 294 | if(!project) return nil; 295 | NSString * suffix = project.type == ProjectTypeXib ? XIB_SUFFIX : STORYBOARD_SUFFIX; 296 | return [NSString stringWithFormat:@"%@/%@.%@",[self projectsDir],project.name,suffix]; 297 | } 298 | 299 | - (NSString *)projectPathFor: (NSString *)projectName platform: (BOOL)isPlatformIOS xibOrStoryboard: (BOOL)xibOrStoryboard 300 | { 301 | if(projectName.length == 0) return nil; 302 | NSString * suffix = nil; 303 | { 304 | if(isPlatformIOS){ 305 | //ios 306 | suffix = xibOrStoryboard ? XIB_SUFFIX : STORYBOARD_SUFFIX; 307 | }else{ 308 | //mac 309 | suffix = XIB_SUFFIX; 310 | } 311 | } 312 | return [NSString stringWithFormat:@"%@/%@.%@",[self projectsDir],projectName,suffix]; 313 | } 314 | 315 | - (NSString *)templatePathForPlatform: (BOOL)isPlatformIOS xibOrStoryboard: (BOOL)xibOrStoryboard{ 316 | NSString * resourceName = nil; 317 | { 318 | if(isPlatformIOS){ 319 | //ios 320 | resourceName = xibOrStoryboard ? @"IOSTemplate" : @"IOSStoryboardTemplate"; 321 | }else{ 322 | //mac 323 | resourceName = @"MacTemplate"; 324 | } 325 | } 326 | NSBundle * bundle = [NSBundle bundleForClass:[self class]]; 327 | NSString * templatePath = [bundle pathForResource:resourceName ofType:@"xml"]; 328 | return templatePath; 329 | } 330 | 331 | 332 | @end 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | -------------------------------------------------------------------------------- /BetterXibTest/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | Default 523 | 524 | 525 | 526 | 527 | 528 | 529 | Left to Right 530 | 531 | 532 | 533 | 534 | 535 | 536 | Right to Left 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | Default 548 | 549 | 550 | 551 | 552 | 553 | 554 | Left to Right 555 | 556 | 557 | 558 | 559 | 560 | 561 | Right to Left 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | -------------------------------------------------------------------------------- /BetterXibTest/BetterXibTest-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | net.duohuo.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2014年 duohuo. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /BetterXibTest/BetterXibTest-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /BetterXibTest/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /BetterXibTest/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /BetterXibTest/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /BetterXibTest/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // BetterXibTest 4 | // 5 | // Created by 张小刚 on 14-6-13. 6 | // Copyright (c) 2014年 duohuo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) 12 | { 13 | return NSApplicationMain(argc, argv); 14 | } 15 | -------------------------------------------------------------------------------- /BetterXibTestTests/BetterXibTestTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | net.duohuo.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /BetterXibTestTests/BetterXibTestTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BetterXibTestTests.m 3 | // BetterXibTestTests 4 | // 5 | // Created by 张小刚 on 14-6-13. 6 | // Copyright (c) 2014年 duohuo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BetterXibTestTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation BetterXibTestTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /BetterXibTestTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | BetterXib 2 | ========= 3 | 在使用`xib`的过程中你是否碰到过这样的情景:你选中一个`Label`,修改它的字体、颜色、大小,然后使用。过了一会儿,在另一个地方你又要使用刚才配置过的`Label`,于是。。过了两秒钟你想起了上次使用它的地方,接着你熟练的搜索,复制,粘贴。又过了一会儿,你又要使用它。。 4 | 5 | 如何解决? 6 | -------- 7 | 8 | 当第三次我又要使用那个Label的时候,我想:"嗯,是时候创建一个“类”来解决这个问题啦!" 9 | 10 | 我的做法是:建一个以项目命名的`xib`文件,在这个文件中存放这个项目中重复使用的`UI控件`。在需要的时候直接从这个项目文件中复制,粘贴。 11 | 生活美好了一些! 12 | 13 | 接着,在学会儿编写Xcode插件后,我写了`BetterXib` 14 | 它很小,但很有用! 15 | 现在你只需要按下`Ctrl+G`,那个`Label`就会出现在你的面前! 16 | 17 | 使用方法 18 | -------- 19 | - **插件安装** 20 | copy BetterXib.xcplugin to ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/ or build target , after build, Xcode will help you copy the plug-in product to that directory. 21 | Then you should restart Xcode ,let Xcode load the plug-in. 22 | 23 | - **使用** 24 | 按`Ctrl+G`会引导生成一个控件模板文件,然后你可以在模板文件中存放项目中经常使用到的`UI控件` 25 | 下次使用的时候,再按`Ctrl+G`,模板文件会被打开,你就可以从里面选择你需要的控件啦。 26 | --------------------------------------------------------------------------------