├── ENSwiftSideMenu.podspec ├── Example ├── SwiftSideMenu.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── vtrulyaev.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── vtrulyaev.xcuserdatad │ │ └── xcschemes │ │ ├── SwiftSideMenu.xcscheme │ │ └── xcschememanagement.plist ├── SwiftSideMenu │ ├── AppDelegate.swift │ ├── Base.lproj │ │ └── Main.storyboard │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ └── Contents.json │ ├── Info.plist │ ├── LaunchView.xib │ ├── MyMenuTableViewController.swift │ ├── MyNavigationController.swift │ ├── ViewController.swift │ ├── ViewController2.swift │ └── image.png └── SwiftSideMenuTests │ ├── Info.plist │ └── SwiftSideMenuTests.swift ├── LICENSE ├── Library ├── ENSideMenu.swift └── ENSideMenuNavigationController.swift ├── ObjCExample ├── ObjCExample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── evgeny.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── evgeny.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── ObjCExample.xcscheme │ │ └── xcschememanagement.plist ├── ObjCExample │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── MenuItemsTVC.h │ ├── MenuItemsTVC.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m └── ObjCExampleTests │ ├── Info.plist │ └── ObjCExampleTests.m ├── Package.swift ├── README.md └── demo.gif /ENSwiftSideMenu.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "ENSwiftSideMenu" 4 | s.version = "0.1.4" 5 | s.summary = "A simple side menu for iOS 9 and higher" 6 | s.homepage = "https://github.com/evnaz/ENSwiftSideMenu" 7 | s.license = { :type => "MIT", :file => "LICENSE" } 8 | s.author = { "Evgeny Nazarov" => "e.nazarov@yahoo.com" } 9 | s.requires_arc = true 10 | s.platform = :ios, "9.0" 11 | s.swift_version = '5.0' 12 | s.source = { :git => "https://github.com/evnaz/ENSwiftSideMenu.git", :tag => "0.1.4"} 13 | s.source_files = "Library/*.swift" 14 | 15 | end 16 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1429137D19D97A4F0025188A /* MyMenuTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1429137C19D97A4F0025188A /* MyMenuTableViewController.swift */; }; 11 | 1429139319DA9F4D0025188A /* MyNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1429139219DA9F4D0025188A /* MyNavigationController.swift */; }; 12 | 14EAB63D19DD4E95006A90FC /* ENSideMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14EAB63B19DD4E95006A90FC /* ENSideMenu.swift */; }; 13 | 14EAB63E19DD4E95006A90FC /* ENSideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14EAB63C19DD4E95006A90FC /* ENSideMenuNavigationController.swift */; }; 14 | 5C132589198E2A9A00CA49BE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C132588198E2A9A00CA49BE /* AppDelegate.swift */; }; 15 | 5C13258B198E2A9A00CA49BE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C13258A198E2A9A00CA49BE /* ViewController.swift */; }; 16 | 5C132590198E2A9A00CA49BE /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5C13258F198E2A9A00CA49BE /* Images.xcassets */; }; 17 | 5C13259C198E2A9A00CA49BE /* SwiftSideMenuTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C13259B198E2A9A00CA49BE /* SwiftSideMenuTests.swift */; }; 18 | 5C1325AA198E2AB300CA49BE /* image.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C1325A7198E2AB300CA49BE /* image.png */; }; 19 | 5C6D6A271A7E26380047FE0D /* ViewController2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C6D6A261A7E26380047FE0D /* ViewController2.swift */; }; 20 | 5C7D78C21BAEEEC2002BD24B /* LaunchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5C7D78C11BAEEEC2002BD24B /* LaunchView.xib */; }; 21 | 9E4766FC19DDBCE900FCEACC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5C13258C198E2A9A00CA49BE /* Main.storyboard */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | 5C132596198E2A9A00CA49BE /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = 5C13257B198E2A9A00CA49BE /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = 5C132582198E2A9A00CA49BE; 30 | remoteInfo = SwiftSideMenu; 31 | }; 32 | /* End PBXContainerItemProxy section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | 1429137C19D97A4F0025188A /* MyMenuTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyMenuTableViewController.swift; sourceTree = ""; }; 36 | 1429139219DA9F4D0025188A /* MyNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyNavigationController.swift; sourceTree = ""; }; 37 | 14EAB63B19DD4E95006A90FC /* ENSideMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ENSideMenu.swift; sourceTree = ""; }; 38 | 14EAB63C19DD4E95006A90FC /* ENSideMenuNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ENSideMenuNavigationController.swift; sourceTree = ""; }; 39 | 5C132583198E2A9A00CA49BE /* SwiftSideMenu.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftSideMenu.app; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 5C132587198E2A9A00CA49BE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 41 | 5C132588198E2A9A00CA49BE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 42 | 5C13258A198E2A9A00CA49BE /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 43 | 5C13258D198E2A9A00CA49BE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 44 | 5C13258F198E2A9A00CA49BE /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 45 | 5C132595198E2A9A00CA49BE /* SwiftSideMenuTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftSideMenuTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | 5C13259A198E2A9A00CA49BE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 47 | 5C13259B198E2A9A00CA49BE /* SwiftSideMenuTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftSideMenuTests.swift; sourceTree = ""; }; 48 | 5C1325A7198E2AB300CA49BE /* image.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = image.png; sourceTree = ""; }; 49 | 5C6D6A261A7E26380047FE0D /* ViewController2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController2.swift; sourceTree = ""; }; 50 | 5C7D78C11BAEEEC2002BD24B /* LaunchView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchView.xib; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | 5C132580198E2A9A00CA49BE /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | 5C132592198E2A9A00CA49BE /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | 1429137B19D979A50025188A /* Storyboard Example */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 5C132588198E2A9A00CA49BE /* AppDelegate.swift */, 75 | 1429139419DAA9C00025188A /* Controllers */, 76 | ); 77 | name = "Storyboard Example"; 78 | sourceTree = ""; 79 | }; 80 | 1429139419DAA9C00025188A /* Controllers */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 1429139219DA9F4D0025188A /* MyNavigationController.swift */, 84 | 1429137C19D97A4F0025188A /* MyMenuTableViewController.swift */, 85 | 5C13258A198E2A9A00CA49BE /* ViewController.swift */, 86 | 5C6D6A261A7E26380047FE0D /* ViewController2.swift */, 87 | ); 88 | name = Controllers; 89 | sourceTree = ""; 90 | }; 91 | 14EAB63A19DD4E95006A90FC /* Library */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 14EAB63B19DD4E95006A90FC /* ENSideMenu.swift */, 95 | 14EAB63C19DD4E95006A90FC /* ENSideMenuNavigationController.swift */, 96 | ); 97 | name = Library; 98 | path = ../../Library; 99 | sourceTree = ""; 100 | }; 101 | 5C13257A198E2A9A00CA49BE = { 102 | isa = PBXGroup; 103 | children = ( 104 | 5C132585198E2A9A00CA49BE /* SwiftSideMenu */, 105 | 5C132598198E2A9A00CA49BE /* SwiftSideMenuTests */, 106 | 5C132584198E2A9A00CA49BE /* Products */, 107 | ); 108 | sourceTree = ""; 109 | }; 110 | 5C132584198E2A9A00CA49BE /* Products */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 5C132583198E2A9A00CA49BE /* SwiftSideMenu.app */, 114 | 5C132595198E2A9A00CA49BE /* SwiftSideMenuTests.xctest */, 115 | ); 116 | name = Products; 117 | sourceTree = ""; 118 | }; 119 | 5C132585198E2A9A00CA49BE /* SwiftSideMenu */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 14EAB63A19DD4E95006A90FC /* Library */, 123 | 1429137B19D979A50025188A /* Storyboard Example */, 124 | 5C1325A7198E2AB300CA49BE /* image.png */, 125 | 5C13258C198E2A9A00CA49BE /* Main.storyboard */, 126 | 5C7D78C11BAEEEC2002BD24B /* LaunchView.xib */, 127 | 5C13258F198E2A9A00CA49BE /* Images.xcassets */, 128 | 5C132586198E2A9A00CA49BE /* Supporting Files */, 129 | ); 130 | path = SwiftSideMenu; 131 | sourceTree = ""; 132 | }; 133 | 5C132586198E2A9A00CA49BE /* Supporting Files */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 5C132587198E2A9A00CA49BE /* Info.plist */, 137 | ); 138 | name = "Supporting Files"; 139 | sourceTree = ""; 140 | }; 141 | 5C132598198E2A9A00CA49BE /* SwiftSideMenuTests */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 5C13259B198E2A9A00CA49BE /* SwiftSideMenuTests.swift */, 145 | 5C132599198E2A9A00CA49BE /* Supporting Files */, 146 | ); 147 | path = SwiftSideMenuTests; 148 | sourceTree = ""; 149 | }; 150 | 5C132599198E2A9A00CA49BE /* Supporting Files */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 5C13259A198E2A9A00CA49BE /* Info.plist */, 154 | ); 155 | name = "Supporting Files"; 156 | sourceTree = ""; 157 | }; 158 | /* End PBXGroup section */ 159 | 160 | /* Begin PBXNativeTarget section */ 161 | 5C132582198E2A9A00CA49BE /* SwiftSideMenu */ = { 162 | isa = PBXNativeTarget; 163 | buildConfigurationList = 5C13259F198E2A9A00CA49BE /* Build configuration list for PBXNativeTarget "SwiftSideMenu" */; 164 | buildPhases = ( 165 | 5C13257F198E2A9A00CA49BE /* Sources */, 166 | 5C132580198E2A9A00CA49BE /* Frameworks */, 167 | 5C132581198E2A9A00CA49BE /* Resources */, 168 | ); 169 | buildRules = ( 170 | ); 171 | dependencies = ( 172 | ); 173 | name = SwiftSideMenu; 174 | productName = SwiftSideMenu; 175 | productReference = 5C132583198E2A9A00CA49BE /* SwiftSideMenu.app */; 176 | productType = "com.apple.product-type.application"; 177 | }; 178 | 5C132594198E2A9A00CA49BE /* SwiftSideMenuTests */ = { 179 | isa = PBXNativeTarget; 180 | buildConfigurationList = 5C1325A2198E2A9A00CA49BE /* Build configuration list for PBXNativeTarget "SwiftSideMenuTests" */; 181 | buildPhases = ( 182 | 5C132591198E2A9A00CA49BE /* Sources */, 183 | 5C132592198E2A9A00CA49BE /* Frameworks */, 184 | 5C132593198E2A9A00CA49BE /* Resources */, 185 | ); 186 | buildRules = ( 187 | ); 188 | dependencies = ( 189 | 5C132597198E2A9A00CA49BE /* PBXTargetDependency */, 190 | ); 191 | name = SwiftSideMenuTests; 192 | productName = SwiftSideMenuTests; 193 | productReference = 5C132595198E2A9A00CA49BE /* SwiftSideMenuTests.xctest */; 194 | productType = "com.apple.product-type.bundle.unit-test"; 195 | }; 196 | /* End PBXNativeTarget section */ 197 | 198 | /* Begin PBXProject section */ 199 | 5C13257B198E2A9A00CA49BE /* Project object */ = { 200 | isa = PBXProject; 201 | attributes = { 202 | LastSwiftUpdateCheck = 0700; 203 | LastUpgradeCheck = 1020; 204 | ORGANIZATIONNAME = "Evgeny Nazarov"; 205 | TargetAttributes = { 206 | 5C132582198E2A9A00CA49BE = { 207 | CreatedOnToolsVersion = 6.0; 208 | LastSwiftMigration = 0900; 209 | }; 210 | 5C132594198E2A9A00CA49BE = { 211 | CreatedOnToolsVersion = 6.0; 212 | LastSwiftMigration = 1020; 213 | TestTargetID = 5C132582198E2A9A00CA49BE; 214 | }; 215 | }; 216 | }; 217 | buildConfigurationList = 5C13257E198E2A9A00CA49BE /* Build configuration list for PBXProject "SwiftSideMenu" */; 218 | compatibilityVersion = "Xcode 3.2"; 219 | developmentRegion = en; 220 | hasScannedForEncodings = 0; 221 | knownRegions = ( 222 | en, 223 | Base, 224 | ); 225 | mainGroup = 5C13257A198E2A9A00CA49BE; 226 | productRefGroup = 5C132584198E2A9A00CA49BE /* Products */; 227 | projectDirPath = ""; 228 | projectRoot = ""; 229 | targets = ( 230 | 5C132582198E2A9A00CA49BE /* SwiftSideMenu */, 231 | 5C132594198E2A9A00CA49BE /* SwiftSideMenuTests */, 232 | ); 233 | }; 234 | /* End PBXProject section */ 235 | 236 | /* Begin PBXResourcesBuildPhase section */ 237 | 5C132581198E2A9A00CA49BE /* Resources */ = { 238 | isa = PBXResourcesBuildPhase; 239 | buildActionMask = 2147483647; 240 | files = ( 241 | 9E4766FC19DDBCE900FCEACC /* Main.storyboard in Resources */, 242 | 5C7D78C21BAEEEC2002BD24B /* LaunchView.xib in Resources */, 243 | 5C132590198E2A9A00CA49BE /* Images.xcassets in Resources */, 244 | 5C1325AA198E2AB300CA49BE /* image.png in Resources */, 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | 5C132593198E2A9A00CA49BE /* Resources */ = { 249 | isa = PBXResourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | ); 253 | runOnlyForDeploymentPostprocessing = 0; 254 | }; 255 | /* End PBXResourcesBuildPhase section */ 256 | 257 | /* Begin PBXSourcesBuildPhase section */ 258 | 5C13257F198E2A9A00CA49BE /* Sources */ = { 259 | isa = PBXSourcesBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | 14EAB63E19DD4E95006A90FC /* ENSideMenuNavigationController.swift in Sources */, 263 | 5C13258B198E2A9A00CA49BE /* ViewController.swift in Sources */, 264 | 1429137D19D97A4F0025188A /* MyMenuTableViewController.swift in Sources */, 265 | 14EAB63D19DD4E95006A90FC /* ENSideMenu.swift in Sources */, 266 | 5C6D6A271A7E26380047FE0D /* ViewController2.swift in Sources */, 267 | 1429139319DA9F4D0025188A /* MyNavigationController.swift in Sources */, 268 | 5C132589198E2A9A00CA49BE /* AppDelegate.swift in Sources */, 269 | ); 270 | runOnlyForDeploymentPostprocessing = 0; 271 | }; 272 | 5C132591198E2A9A00CA49BE /* Sources */ = { 273 | isa = PBXSourcesBuildPhase; 274 | buildActionMask = 2147483647; 275 | files = ( 276 | 5C13259C198E2A9A00CA49BE /* SwiftSideMenuTests.swift in Sources */, 277 | ); 278 | runOnlyForDeploymentPostprocessing = 0; 279 | }; 280 | /* End PBXSourcesBuildPhase section */ 281 | 282 | /* Begin PBXTargetDependency section */ 283 | 5C132597198E2A9A00CA49BE /* PBXTargetDependency */ = { 284 | isa = PBXTargetDependency; 285 | target = 5C132582198E2A9A00CA49BE /* SwiftSideMenu */; 286 | targetProxy = 5C132596198E2A9A00CA49BE /* PBXContainerItemProxy */; 287 | }; 288 | /* End PBXTargetDependency section */ 289 | 290 | /* Begin PBXVariantGroup section */ 291 | 5C13258C198E2A9A00CA49BE /* Main.storyboard */ = { 292 | isa = PBXVariantGroup; 293 | children = ( 294 | 5C13258D198E2A9A00CA49BE /* Base */, 295 | ); 296 | name = Main.storyboard; 297 | sourceTree = ""; 298 | }; 299 | /* End PBXVariantGroup section */ 300 | 301 | /* Begin XCBuildConfiguration section */ 302 | 5C13259D198E2A9A00CA49BE /* Debug */ = { 303 | isa = XCBuildConfiguration; 304 | buildSettings = { 305 | ALWAYS_SEARCH_USER_PATHS = NO; 306 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 308 | CLANG_CXX_LIBRARY = "libc++"; 309 | CLANG_ENABLE_MODULES = YES; 310 | CLANG_ENABLE_OBJC_ARC = YES; 311 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 312 | CLANG_WARN_BOOL_CONVERSION = YES; 313 | CLANG_WARN_COMMA = YES; 314 | CLANG_WARN_CONSTANT_CONVERSION = YES; 315 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 316 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 317 | CLANG_WARN_EMPTY_BODY = YES; 318 | CLANG_WARN_ENUM_CONVERSION = YES; 319 | CLANG_WARN_INFINITE_RECURSION = YES; 320 | CLANG_WARN_INT_CONVERSION = YES; 321 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 322 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 323 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 324 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 325 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 326 | CLANG_WARN_STRICT_PROTOTYPES = YES; 327 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 328 | CLANG_WARN_UNREACHABLE_CODE = YES; 329 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 330 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 331 | COPY_PHASE_STRIP = NO; 332 | ENABLE_STRICT_OBJC_MSGSEND = YES; 333 | ENABLE_TESTABILITY = YES; 334 | GCC_C_LANGUAGE_STANDARD = gnu99; 335 | GCC_DYNAMIC_NO_PIC = NO; 336 | GCC_NO_COMMON_BLOCKS = YES; 337 | GCC_OPTIMIZATION_LEVEL = 0; 338 | GCC_PREPROCESSOR_DEFINITIONS = ( 339 | "DEBUG=1", 340 | "$(inherited)", 341 | ); 342 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 343 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 344 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 345 | GCC_WARN_UNDECLARED_SELECTOR = YES; 346 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 347 | GCC_WARN_UNUSED_FUNCTION = YES; 348 | GCC_WARN_UNUSED_VARIABLE = YES; 349 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 350 | MTL_ENABLE_DEBUG_INFO = YES; 351 | ONLY_ACTIVE_ARCH = YES; 352 | SDKROOT = iphoneos; 353 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 354 | TARGETED_DEVICE_FAMILY = "1,2"; 355 | }; 356 | name = Debug; 357 | }; 358 | 5C13259E198E2A9A00CA49BE /* Release */ = { 359 | isa = XCBuildConfiguration; 360 | buildSettings = { 361 | ALWAYS_SEARCH_USER_PATHS = NO; 362 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 363 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 364 | CLANG_CXX_LIBRARY = "libc++"; 365 | CLANG_ENABLE_MODULES = YES; 366 | CLANG_ENABLE_OBJC_ARC = YES; 367 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 368 | CLANG_WARN_BOOL_CONVERSION = YES; 369 | CLANG_WARN_COMMA = YES; 370 | CLANG_WARN_CONSTANT_CONVERSION = YES; 371 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 372 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 373 | CLANG_WARN_EMPTY_BODY = YES; 374 | CLANG_WARN_ENUM_CONVERSION = YES; 375 | CLANG_WARN_INFINITE_RECURSION = YES; 376 | CLANG_WARN_INT_CONVERSION = YES; 377 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 378 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 379 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 380 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 381 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 382 | CLANG_WARN_STRICT_PROTOTYPES = YES; 383 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 384 | CLANG_WARN_UNREACHABLE_CODE = YES; 385 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 386 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 387 | COPY_PHASE_STRIP = YES; 388 | ENABLE_NS_ASSERTIONS = NO; 389 | ENABLE_STRICT_OBJC_MSGSEND = YES; 390 | GCC_C_LANGUAGE_STANDARD = gnu99; 391 | GCC_NO_COMMON_BLOCKS = YES; 392 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 393 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 394 | GCC_WARN_UNDECLARED_SELECTOR = YES; 395 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 396 | GCC_WARN_UNUSED_FUNCTION = YES; 397 | GCC_WARN_UNUSED_VARIABLE = YES; 398 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 399 | MTL_ENABLE_DEBUG_INFO = NO; 400 | SDKROOT = iphoneos; 401 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 402 | TARGETED_DEVICE_FAMILY = "1,2"; 403 | VALIDATE_PRODUCT = YES; 404 | }; 405 | name = Release; 406 | }; 407 | 5C1325A0198E2A9A00CA49BE /* Debug */ = { 408 | isa = XCBuildConfiguration; 409 | buildSettings = { 410 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 411 | INFOPLIST_FILE = SwiftSideMenu/Info.plist; 412 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 413 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 414 | PRODUCT_BUNDLE_IDENTIFIER = "ru.test.${PRODUCT_NAME:rfc1034identifier}"; 415 | PRODUCT_NAME = "$(TARGET_NAME)"; 416 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 417 | SWIFT_VERSION = 5.0; 418 | }; 419 | name = Debug; 420 | }; 421 | 5C1325A1198E2A9A00CA49BE /* Release */ = { 422 | isa = XCBuildConfiguration; 423 | buildSettings = { 424 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 425 | INFOPLIST_FILE = SwiftSideMenu/Info.plist; 426 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 427 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 428 | PRODUCT_BUNDLE_IDENTIFIER = "ru.test.${PRODUCT_NAME:rfc1034identifier}"; 429 | PRODUCT_NAME = "$(TARGET_NAME)"; 430 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 431 | SWIFT_VERSION = 5.0; 432 | }; 433 | name = Release; 434 | }; 435 | 5C1325A3198E2A9A00CA49BE /* Debug */ = { 436 | isa = XCBuildConfiguration; 437 | buildSettings = { 438 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SwiftSideMenu.app/SwiftSideMenu"; 439 | FRAMEWORK_SEARCH_PATHS = ( 440 | "$(SDKROOT)/Developer/Library/Frameworks", 441 | "$(inherited)", 442 | ); 443 | GCC_PREPROCESSOR_DEFINITIONS = ( 444 | "DEBUG=1", 445 | "$(inherited)", 446 | ); 447 | INFOPLIST_FILE = SwiftSideMenuTests/Info.plist; 448 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 449 | PRODUCT_BUNDLE_IDENTIFIER = "ru.test.${PRODUCT_NAME:rfc1034identifier}"; 450 | PRODUCT_NAME = "$(TARGET_NAME)"; 451 | SWIFT_VERSION = 5.0; 452 | TEST_HOST = "$(BUNDLE_LOADER)"; 453 | }; 454 | name = Debug; 455 | }; 456 | 5C1325A4198E2A9A00CA49BE /* Release */ = { 457 | isa = XCBuildConfiguration; 458 | buildSettings = { 459 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SwiftSideMenu.app/SwiftSideMenu"; 460 | FRAMEWORK_SEARCH_PATHS = ( 461 | "$(SDKROOT)/Developer/Library/Frameworks", 462 | "$(inherited)", 463 | ); 464 | INFOPLIST_FILE = SwiftSideMenuTests/Info.plist; 465 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 466 | PRODUCT_BUNDLE_IDENTIFIER = "ru.test.${PRODUCT_NAME:rfc1034identifier}"; 467 | PRODUCT_NAME = "$(TARGET_NAME)"; 468 | SWIFT_VERSION = 5.0; 469 | TEST_HOST = "$(BUNDLE_LOADER)"; 470 | }; 471 | name = Release; 472 | }; 473 | /* End XCBuildConfiguration section */ 474 | 475 | /* Begin XCConfigurationList section */ 476 | 5C13257E198E2A9A00CA49BE /* Build configuration list for PBXProject "SwiftSideMenu" */ = { 477 | isa = XCConfigurationList; 478 | buildConfigurations = ( 479 | 5C13259D198E2A9A00CA49BE /* Debug */, 480 | 5C13259E198E2A9A00CA49BE /* Release */, 481 | ); 482 | defaultConfigurationIsVisible = 0; 483 | defaultConfigurationName = Release; 484 | }; 485 | 5C13259F198E2A9A00CA49BE /* Build configuration list for PBXNativeTarget "SwiftSideMenu" */ = { 486 | isa = XCConfigurationList; 487 | buildConfigurations = ( 488 | 5C1325A0198E2A9A00CA49BE /* Debug */, 489 | 5C1325A1198E2A9A00CA49BE /* Release */, 490 | ); 491 | defaultConfigurationIsVisible = 0; 492 | defaultConfigurationName = Release; 493 | }; 494 | 5C1325A2198E2A9A00CA49BE /* Build configuration list for PBXNativeTarget "SwiftSideMenuTests" */ = { 495 | isa = XCConfigurationList; 496 | buildConfigurations = ( 497 | 5C1325A3198E2A9A00CA49BE /* Debug */, 498 | 5C1325A4198E2A9A00CA49BE /* Release */, 499 | ); 500 | defaultConfigurationIsVisible = 0; 501 | defaultConfigurationName = Release; 502 | }; 503 | /* End XCConfigurationList section */ 504 | }; 505 | rootObject = 5C13257B198E2A9A00CA49BE /* Project object */; 506 | } 507 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu.xcodeproj/project.xcworkspace/xcuserdata/vtrulyaev.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/touchasky/ENSwiftSideMenu/4a585ea393e4a7254507b4b196f5a7e6784ff6de/Example/SwiftSideMenu.xcodeproj/project.xcworkspace/xcuserdata/vtrulyaev.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Example/SwiftSideMenu.xcodeproj/xcuserdata/vtrulyaev.xcuserdatad/xcschemes/SwiftSideMenu.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu.xcodeproj/xcuserdata/vtrulyaev.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftSideMenu.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 5C132582198E2A9A00CA49BE 16 | 17 | primary 18 | 19 | 20 | 5C132594198E2A9A00CA49BE 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SwiftSideMenu 4 | // 5 | // Created by Evgeny on 03.08.14. 6 | // Copyright (c) 2014 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(_ application: UIApplication) { 22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 23 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 24 | } 25 | 26 | func applicationDidEnterBackground(_ application: UIApplication) { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | func applicationWillEnterForeground(_ application: UIApplication) { 32 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | func applicationDidBecomeActive(_ application: UIApplication) { 36 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 37 | } 38 | 39 | func applicationWillTerminate(_ application: UIApplication) { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | 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 | 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 | 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 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /Example/SwiftSideMenu/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "orientation" : "portrait", 20 | "idiom" : "ipad", 21 | "extent" : "full-screen", 22 | "minimum-system-version" : "7.0", 23 | "scale" : "1x" 24 | }, 25 | { 26 | "orientation" : "landscape", 27 | "idiom" : "ipad", 28 | "extent" : "full-screen", 29 | "minimum-system-version" : "7.0", 30 | "scale" : "1x" 31 | }, 32 | { 33 | "orientation" : "portrait", 34 | "idiom" : "ipad", 35 | "extent" : "full-screen", 36 | "minimum-system-version" : "7.0", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "orientation" : "landscape", 41 | "idiom" : "ipad", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "2x" 45 | } 46 | ], 47 | "info" : { 48 | "version" : 1, 49 | "author" : "xcode" 50 | } 51 | } -------------------------------------------------------------------------------- /Example/SwiftSideMenu/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 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchView 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu/LaunchView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu/MyMenuTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MyMenuTableViewController.swift 3 | // SwiftSideMenu 4 | // 5 | // Created by Evgeny Nazarov on 29.09.14. 6 | // Copyright (c) 2014 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MyMenuTableViewController: UITableViewController { 12 | 13 | private let menuOptionCellId = "Cell" 14 | var selectedMenuItem : Int = 0 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | 19 | // Customize apperance of table view 20 | tableView.contentInset = UIEdgeInsets(top: 64.0, left: 0, bottom: 0, right: 0) 21 | tableView.separatorStyle = .none 22 | tableView.backgroundColor = UIColor.clear 23 | tableView.scrollsToTop = false 24 | 25 | // Preserve selection between presentations 26 | clearsSelectionOnViewWillAppear = false 27 | 28 | // Preselect a menu option 29 | tableView.selectRow(at: IndexPath(row: selectedMenuItem, section: 0), animated: false, scrollPosition: .middle) 30 | } 31 | 32 | 33 | // MARK: - Table view data source 34 | override func numberOfSections(in tableView: UITableView) -> Int { 35 | return 1 36 | } 37 | 38 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 39 | return 4 40 | } 41 | 42 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 43 | 44 | var cell = tableView.dequeueReusableCell(withIdentifier: menuOptionCellId) 45 | 46 | if (cell == nil) { 47 | cell = UITableViewCell(style:.default, reuseIdentifier: menuOptionCellId) 48 | cell!.backgroundColor = .clear 49 | cell!.textLabel?.textColor = .darkGray 50 | let selectedBackgroundView = UIView(frame: CGRect(x: 0, y: 0, width: cell!.frame.size.width, height: cell!.frame.size.height)) 51 | selectedBackgroundView.backgroundColor = UIColor.gray.withAlphaComponent(0.2) 52 | cell!.selectedBackgroundView = selectedBackgroundView 53 | } 54 | 55 | cell!.textLabel?.text = "ViewController #\(indexPath.row+1)" 56 | 57 | return cell! 58 | } 59 | 60 | override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 61 | return 50.0 62 | } 63 | 64 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 65 | 66 | print("did select row: \(indexPath.row)") 67 | 68 | if (indexPath.row == selectedMenuItem) { 69 | return 70 | } 71 | 72 | selectedMenuItem = indexPath.row 73 | 74 | //Present new view controller 75 | let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main",bundle: nil) 76 | var destViewController : UIViewController 77 | switch (indexPath.row) { 78 | case 0: 79 | destViewController = mainStoryboard.instantiateViewController(withIdentifier: "ViewController1") 80 | break 81 | case 1: 82 | destViewController = mainStoryboard.instantiateViewController(withIdentifier: "ViewController2") 83 | break 84 | case 2: 85 | destViewController = mainStoryboard.instantiateViewController(withIdentifier: "ViewController3") 86 | break 87 | default: 88 | destViewController = mainStoryboard.instantiateViewController(withIdentifier: "ViewController4") 89 | break 90 | } 91 | sideMenuController()?.setContentViewController(destViewController) 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu/MyNavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MyNavigationController.swift 3 | // SwiftSideMenu 4 | // 5 | // Created by Evgeny Nazarov on 30.09.14. 6 | // Copyright (c) 2014 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MyNavigationController: ENSideMenuNavigationController { 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | 15 | // Create a table view controller 16 | let tableViewController = MyMenuTableViewController() 17 | 18 | // Create side menu 19 | sideMenu = ENSideMenu(sourceView: view, menuViewController: tableViewController, menuPosition:.left) 20 | 21 | // Set a delegate 22 | sideMenu?.delegate = self 23 | 24 | // Configure side menu 25 | sideMenu?.menuWidth = 180.0 26 | 27 | // Show navigation bar above side menu 28 | view.bringSubviewToFront(navigationBar) 29 | } 30 | 31 | override func didReceiveMemoryWarning() { 32 | super.didReceiveMemoryWarning() 33 | // Dispose of any resources that can be recreated. 34 | } 35 | } 36 | 37 | extension MyNavigationController: ENSideMenuDelegate { 38 | func sideMenuWillOpen() { 39 | print("sideMenuWillOpen") 40 | } 41 | 42 | func sideMenuWillClose() { 43 | print("sideMenuWillClose") 44 | } 45 | 46 | func sideMenuDidClose() { 47 | print("sideMenuDidClose") 48 | } 49 | 50 | func sideMenuDidOpen() { 51 | print("sideMenuDidOpen") 52 | } 53 | 54 | func sideMenuShouldOpenSideMenu() -> Bool { 55 | return true 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SwiftSideMenu 4 | // 5 | // Created by Evgeny on 03.08.14. 6 | // Copyright (c) 2014 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController, ENSideMenuDelegate { 12 | 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | self.sideMenuController()?.sideMenu?.delegate = self 17 | } 18 | 19 | override func didReceiveMemoryWarning() { 20 | super.didReceiveMemoryWarning() 21 | // Dispose of any resources that can be recreated. 22 | } 23 | 24 | @IBAction func toggleSideMenuBtn(_ sender: UIBarButtonItem) { 25 | toggleSideMenuView() 26 | } 27 | 28 | // MARK: - ENSideMenu Delegate 29 | func sideMenuWillOpen() { 30 | print("sideMenuWillOpen") 31 | } 32 | 33 | func sideMenuWillClose() { 34 | print("sideMenuWillClose") 35 | } 36 | 37 | func sideMenuShouldOpenSideMenu() -> Bool { 38 | print("sideMenuShouldOpenSideMenu") 39 | return true 40 | } 41 | 42 | func sideMenuDidClose() { 43 | print("sideMenuDidClose") 44 | } 45 | 46 | func sideMenuDidOpen() { 47 | print("sideMenuDidOpen") 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu/ViewController2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController2.swift 3 | // SwiftSideMenu 4 | // 5 | // Created by Evgeny on 01.02.15. 6 | // Copyright (c) 2015 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController2: UIViewController, ENSideMenuDelegate { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | self.sideMenuController()?.sideMenu?.delegate = self 16 | } 17 | 18 | // MARK: - ENSideMenu Delegate 19 | func sideMenuWillOpen() { 20 | print("sideMenuWillOpen") 21 | } 22 | 23 | func sideMenuWillClose() { 24 | print("sideMenuWillClose") 25 | } 26 | 27 | func sideMenuDidClose() { 28 | print("sideMenuDidClose") 29 | } 30 | 31 | func sideMenuDidOpen() { 32 | print("sideMenuDidOpen") 33 | } 34 | 35 | func sideMenuShouldOpenSideMenu() -> Bool { 36 | print("sideMenuShouldOpenSideMenu") 37 | return true 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Example/SwiftSideMenu/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/touchasky/ENSwiftSideMenu/4a585ea393e4a7254507b4b196f5a7e6784ff6de/Example/SwiftSideMenu/image.png -------------------------------------------------------------------------------- /Example/SwiftSideMenuTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/SwiftSideMenuTests/SwiftSideMenuTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftSideMenuTests.swift 3 | // SwiftSideMenuTests 4 | // 5 | // Created by Evgeny on 03.08.14. 6 | // Copyright (c) 2014 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class SwiftSideMenuTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Evgeny Nazarov (https://github.com/evnaz) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Library/ENSideMenu.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SideMenu.swift 3 | // SwiftSideMenu 4 | // 5 | // Created by Evgeny on 24.07.14. 6 | // Copyright (c) 2014 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol ENSideMenuDelegate: class { 12 | func sideMenuWillOpen() 13 | func sideMenuWillClose() 14 | func sideMenuShouldOpenSideMenu () -> Bool 15 | func sideMenuDidOpen() 16 | func sideMenuDidClose() 17 | } 18 | 19 | public protocol ENSideMenuProtocol: class { 20 | var sideMenu : ENSideMenu? { get } 21 | func setContentViewController(_ contentViewController: UIViewController) 22 | } 23 | 24 | public enum ENSideMenuAnimation : Int { 25 | case none 26 | case `default` 27 | } 28 | /** 29 | The position of the side view on the screen. 30 | 31 | - Left: Left side of the screen 32 | - Right: Right side of the screen 33 | */ 34 | public enum ENSideMenuPosition : Int { 35 | case left 36 | case right 37 | } 38 | 39 | public extension UIViewController { 40 | /** 41 | Changes current state of side menu view. 42 | */ 43 | func toggleSideMenuView () { 44 | sideMenuController()?.sideMenu?.toggleMenu() 45 | } 46 | /** 47 | Hides the side menu view. 48 | */ 49 | func hideSideMenuView () { 50 | sideMenuController()?.sideMenu?.hideSideMenu() 51 | } 52 | /** 53 | Shows the side menu view. 54 | */ 55 | func showSideMenuView () { 56 | sideMenuController()?.sideMenu?.showSideMenu() 57 | } 58 | 59 | /** 60 | Returns a Boolean value indicating whether the side menu is showed. 61 | 62 | :returns: BOOL value 63 | */ 64 | func isSideMenuOpen () -> Bool { 65 | let sieMenuOpen = sideMenuController()?.sideMenu?.isMenuOpen 66 | return sieMenuOpen! 67 | } 68 | 69 | /** 70 | * You must call this method from viewDidLayoutSubviews in your content view controlers so it fixes size and position of the side menu when the screen 71 | * rotates. 72 | * A convenient way to do it might be creating a subclass of UIViewController that does precisely that and then subclassing your view controllers from it. 73 | */ 74 | func fixSideMenuSize() { 75 | if let navController = navigationController as? ENSideMenuNavigationController { 76 | navController.sideMenu?.updateFrame() 77 | } 78 | } 79 | /** 80 | Returns a view controller containing a side menu 81 | 82 | :returns: A `UIViewController`responding to `ENSideMenuProtocol` protocol 83 | */ 84 | func sideMenuController () -> ENSideMenuProtocol? { 85 | var iteration : UIViewController? = parent 86 | if (iteration == nil) { 87 | return topMostController() 88 | } 89 | repeat { 90 | if (iteration is ENSideMenuProtocol) { 91 | return iteration as? ENSideMenuProtocol 92 | } else if (iteration?.parent != nil && iteration?.parent != iteration) { 93 | iteration = iteration!.parent 94 | } else { 95 | iteration = nil 96 | } 97 | } while (iteration != nil) 98 | 99 | return iteration as? ENSideMenuProtocol 100 | } 101 | 102 | internal func topMostController () -> ENSideMenuProtocol? { 103 | var topController : UIViewController? = UIApplication.shared.keyWindow?.rootViewController 104 | if (topController is UITabBarController) { 105 | topController = (topController as! UITabBarController).selectedViewController 106 | } 107 | var lastMenuProtocol : ENSideMenuProtocol? 108 | while (topController?.presentedViewController != nil) { 109 | if(topController?.presentedViewController is ENSideMenuProtocol) { 110 | lastMenuProtocol = topController?.presentedViewController as? ENSideMenuProtocol 111 | } 112 | topController = topController?.presentedViewController 113 | } 114 | 115 | if (lastMenuProtocol != nil) { 116 | return lastMenuProtocol 117 | } 118 | else { 119 | return topController as? ENSideMenuProtocol 120 | } 121 | } 122 | } 123 | 124 | open class ENSideMenu : NSObject, UIGestureRecognizerDelegate { 125 | /// The width of the side menu view. The default value is 160. 126 | open var menuWidth : CGFloat = 160.0 { 127 | didSet { 128 | needUpdateApperance = true 129 | updateSideMenuApperanceIfNeeded() 130 | updateFrame() 131 | } 132 | } 133 | fileprivate var menuPosition:ENSideMenuPosition = .left 134 | fileprivate var blurStyle: UIBlurEffect.Style = .light 135 | /// A Boolean value indicating whether the bouncing effect is enabled. The default value is TRUE. 136 | open var bouncingEnabled :Bool = true 137 | /// The duration of the slide animation. Used only when `bouncingEnabled` is FALSE. 138 | open var animationDuration = 0.4 139 | fileprivate let sideMenuContainerView = UIView() 140 | fileprivate(set) var menuViewController : UIViewController! 141 | fileprivate var animator : UIDynamicAnimator! 142 | fileprivate var sourceView : UIView! 143 | fileprivate var needUpdateApperance : Bool = false 144 | /// The delegate of the side menu 145 | open weak var delegate : ENSideMenuDelegate? 146 | fileprivate(set) var isMenuOpen : Bool = false 147 | /// A Boolean value indicating whether the left swipe is enabled. 148 | open var allowLeftSwipe : Bool = true 149 | /// A Boolean value indicating whether the right swipe is enabled. 150 | open var allowRightSwipe : Bool = true 151 | open var allowPanGesture : Bool = true 152 | fileprivate var panRecognizer : UIPanGestureRecognizer? 153 | 154 | /** 155 | Initializes an instance of a `ENSideMenu` object. 156 | 157 | :param: sourceView The parent view of the side menu view. 158 | :param: menuPosition The position of the side menu view. 159 | 160 | :returns: An initialized `ENSideMenu` object, added to the specified view. 161 | */ 162 | public init(sourceView: UIView, menuPosition: ENSideMenuPosition, blurStyle: UIBlurEffect.Style = .light) { 163 | super.init() 164 | self.sourceView = sourceView 165 | self.menuPosition = menuPosition 166 | self.blurStyle = blurStyle 167 | self.setupMenuView() 168 | 169 | animator = UIDynamicAnimator(referenceView:sourceView) 170 | animator.delegate = self 171 | 172 | self.panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(ENSideMenu.handlePan(_:))) 173 | panRecognizer!.delegate = self 174 | sourceView.addGestureRecognizer(panRecognizer!) 175 | 176 | // Add right swipe gesture recognizer 177 | let rightSwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(ENSideMenu.handleGesture(_:))) 178 | rightSwipeGestureRecognizer.delegate = self 179 | rightSwipeGestureRecognizer.direction = .right 180 | 181 | // Add left swipe gesture recognizer 182 | let leftSwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(ENSideMenu.handleGesture(_:))) 183 | leftSwipeGestureRecognizer.delegate = self 184 | leftSwipeGestureRecognizer.direction = .left 185 | 186 | if (menuPosition == .left) { 187 | sourceView.addGestureRecognizer(rightSwipeGestureRecognizer) 188 | sideMenuContainerView.addGestureRecognizer(leftSwipeGestureRecognizer) 189 | } 190 | else { 191 | sideMenuContainerView.addGestureRecognizer(rightSwipeGestureRecognizer) 192 | sourceView.addGestureRecognizer(leftSwipeGestureRecognizer) 193 | } 194 | 195 | } 196 | /** 197 | Initializes an instance of a `ENSideMenu` object. 198 | 199 | :param: sourceView The parent view of the side menu view. 200 | :param: menuViewController A menu view controller object which will be placed in the side menu view. 201 | :param: menuPosition The position of the side menu view. 202 | 203 | :returns: An initialized `ENSideMenu` object, added to the specified view, containing the specified menu view controller. 204 | */ 205 | public convenience init(sourceView: UIView, menuViewController: UIViewController, menuPosition: ENSideMenuPosition, blurStyle: UIBlurEffect.Style = .light) { 206 | self.init(sourceView: sourceView, menuPosition: menuPosition, blurStyle: blurStyle) 207 | self.menuViewController = menuViewController 208 | menuViewController.view.frame = sideMenuContainerView.bounds 209 | menuViewController.view.autoresizingMask = [.flexibleHeight, .flexibleWidth] 210 | sideMenuContainerView.addSubview(menuViewController.view) 211 | } 212 | /** 213 | Updates the frame of the side menu view. 214 | */ 215 | func updateFrame() { 216 | var width:CGFloat 217 | var height:CGFloat 218 | (width, height) = adjustFrameDimensions( sourceView.frame.size.width, height: sourceView.frame.size.height) 219 | let menuFrame = CGRect( 220 | x: (menuPosition == .left) ? 221 | isMenuOpen ? 0 : -menuWidth-1.0 : 222 | isMenuOpen ? width - menuWidth : width+1.0, 223 | y: sourceView.frame.origin.y, 224 | width: menuWidth, 225 | height: height 226 | ) 227 | sideMenuContainerView.frame = menuFrame 228 | } 229 | 230 | fileprivate func adjustFrameDimensions( _ width: CGFloat, height: CGFloat ) -> (CGFloat,CGFloat) { 231 | if floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1 && 232 | (UIApplication.shared.statusBarOrientation == UIInterfaceOrientation.landscapeRight || 233 | UIApplication.shared.statusBarOrientation == UIInterfaceOrientation.landscapeLeft) { 234 | // iOS 7.1 or lower and landscape mode -> interchange width and height 235 | return (height, width) 236 | } 237 | else { 238 | return (width, height) 239 | } 240 | 241 | } 242 | 243 | fileprivate func setupMenuView() { 244 | 245 | // Configure side menu container 246 | updateFrame() 247 | 248 | sideMenuContainerView.backgroundColor = UIColor.clear 249 | sideMenuContainerView.clipsToBounds = false 250 | sideMenuContainerView.layer.masksToBounds = false 251 | sideMenuContainerView.layer.shadowOffset = (menuPosition == .left) ? CGSize(width: 1.0, height: 1.0) : CGSize(width: -1.0, height: -1.0) 252 | sideMenuContainerView.layer.shadowRadius = 1.0 253 | sideMenuContainerView.layer.shadowOpacity = 0.125 254 | sideMenuContainerView.layer.shadowPath = UIBezierPath(rect: sideMenuContainerView.bounds).cgPath 255 | 256 | sourceView.addSubview(sideMenuContainerView) 257 | 258 | if (NSClassFromString("UIVisualEffectView") != nil) { 259 | // Add blur view 260 | let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: blurStyle)) as UIVisualEffectView 261 | visualEffectView.frame = sideMenuContainerView.bounds 262 | visualEffectView.autoresizingMask = [.flexibleHeight, .flexibleWidth] 263 | sideMenuContainerView.addSubview(visualEffectView) 264 | } 265 | else { 266 | // TODO: add blur for ios 7 267 | } 268 | } 269 | 270 | fileprivate func toggleMenu (_ shouldOpen: Bool) { 271 | if shouldOpen, delegate?.sideMenuShouldOpenSideMenu() == false { 272 | return 273 | } 274 | updateSideMenuApperanceIfNeeded() 275 | isMenuOpen = shouldOpen 276 | var width:CGFloat 277 | var height:CGFloat 278 | (width, height) = adjustFrameDimensions( sourceView.frame.size.width, height: sourceView.frame.size.height) 279 | if (bouncingEnabled) { 280 | 281 | animator.removeAllBehaviors() 282 | 283 | var gravityDirectionX: CGFloat 284 | var pushMagnitude: CGFloat 285 | var boundaryPointX: CGFloat 286 | var boundaryPointY: CGFloat 287 | 288 | if (menuPosition == .left) { 289 | // Left side menu 290 | gravityDirectionX = (shouldOpen) ? 1 : -1 291 | pushMagnitude = (shouldOpen) ? 35 : -35 292 | boundaryPointX = (shouldOpen) ? menuWidth : -menuWidth-2 293 | boundaryPointY = 25 294 | } 295 | else { 296 | // Right side menu 297 | gravityDirectionX = (shouldOpen) ? -1 : 1 298 | pushMagnitude = (shouldOpen) ? -35 : 35 299 | boundaryPointX = (shouldOpen) ? width-menuWidth : width+menuWidth+2 300 | boundaryPointY = -25 301 | } 302 | 303 | let gravityBehavior = UIGravityBehavior(items: [sideMenuContainerView]) 304 | gravityBehavior.gravityDirection = CGVector(dx: gravityDirectionX, dy: 0) 305 | animator.addBehavior(gravityBehavior) 306 | 307 | let collisionBehavior = UICollisionBehavior(items: [sideMenuContainerView]) 308 | collisionBehavior.addBoundary(withIdentifier: "menuBoundary" as NSCopying, from: CGPoint(x: boundaryPointX, y: boundaryPointY), 309 | to: CGPoint(x: boundaryPointX, y: height)) 310 | animator.addBehavior(collisionBehavior) 311 | 312 | let pushBehavior = UIPushBehavior(items: [sideMenuContainerView], mode: .instantaneous) 313 | pushBehavior.magnitude = pushMagnitude 314 | animator.addBehavior(pushBehavior) 315 | 316 | let menuViewBehavior = UIDynamicItemBehavior(items: [sideMenuContainerView]) 317 | menuViewBehavior.elasticity = 0.25 318 | animator.addBehavior(menuViewBehavior) 319 | 320 | } 321 | else { 322 | var destFrame :CGRect 323 | if (menuPosition == .left) { 324 | destFrame = CGRect(x: (shouldOpen) ? -2.0 : -menuWidth, y: 0, width: menuWidth, height: height) 325 | } 326 | else { 327 | destFrame = CGRect(x: (shouldOpen) ? width-menuWidth : width+2.0, 328 | y: 0, 329 | width: menuWidth, 330 | height: height) 331 | } 332 | 333 | UIView.animate( 334 | withDuration: animationDuration, 335 | animations: { [weak self] () -> Void in 336 | self?.sideMenuContainerView.frame = destFrame 337 | }, 338 | completion: { [weak self] (Bool) -> Void in 339 | guard let strongSelf = self else { return } 340 | if (strongSelf.isMenuOpen) { 341 | strongSelf.delegate?.sideMenuDidOpen() 342 | } else { 343 | strongSelf.delegate?.sideMenuDidClose() 344 | } 345 | }) 346 | } 347 | 348 | if (shouldOpen) { 349 | delegate?.sideMenuWillOpen() 350 | } else { 351 | delegate?.sideMenuWillClose() 352 | } 353 | } 354 | 355 | open func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 356 | 357 | if delegate?.sideMenuShouldOpenSideMenu() == false { 358 | return false 359 | } 360 | 361 | if gestureRecognizer is UISwipeGestureRecognizer { 362 | let swipeGestureRecognizer = gestureRecognizer as! UISwipeGestureRecognizer 363 | if !allowLeftSwipe { 364 | if swipeGestureRecognizer.direction == .left { 365 | return false 366 | } 367 | } 368 | 369 | if !allowRightSwipe { 370 | if swipeGestureRecognizer.direction == .right { 371 | return false 372 | } 373 | } 374 | } 375 | else if gestureRecognizer.isEqual(panRecognizer) { 376 | if allowPanGesture == false { 377 | return false 378 | } 379 | animator.removeAllBehaviors() 380 | let touchPosition = gestureRecognizer.location(ofTouch: 0, in: sourceView) 381 | if menuPosition == .left { 382 | if isMenuOpen { 383 | if touchPosition.x < menuWidth { 384 | return true 385 | } 386 | } 387 | else { 388 | if touchPosition.x < 25 { 389 | return true 390 | } 391 | } 392 | } 393 | else { 394 | if isMenuOpen { 395 | if touchPosition.x > sourceView.frame.width - menuWidth { 396 | return true 397 | } 398 | } 399 | else { 400 | if touchPosition.x > sourceView.frame.width-25 { 401 | return true 402 | } 403 | } 404 | } 405 | 406 | return false 407 | } 408 | return true 409 | } 410 | 411 | @objc internal func handleGesture(_ gesture: UISwipeGestureRecognizer) { 412 | toggleMenu((menuPosition == .right && gesture.direction == .left) 413 | || (menuPosition == .left && gesture.direction == .right)) 414 | } 415 | 416 | @objc internal func handlePan(_ recognizer : UIPanGestureRecognizer){ 417 | 418 | let leftToRight = recognizer.velocity(in: recognizer.view).x > 0 419 | 420 | switch recognizer.state { 421 | case .began: 422 | 423 | break 424 | 425 | case .changed: 426 | 427 | let translation = recognizer.translation(in: sourceView).x 428 | let xPoint : CGFloat = sideMenuContainerView.center.x + translation + (menuPosition == .left ? 1 : -1) * menuWidth / 2 429 | 430 | if menuPosition == .left { 431 | if xPoint <= 0 || xPoint > sideMenuContainerView.frame.width { 432 | return 433 | } 434 | }else{ 435 | if xPoint <= sourceView.frame.size.width - menuWidth || xPoint >= sourceView.frame.size.width 436 | { 437 | return 438 | } 439 | } 440 | 441 | sideMenuContainerView.center.x = sideMenuContainerView.center.x + translation 442 | recognizer.setTranslation(CGPoint.zero, in: sourceView) 443 | 444 | default: 445 | 446 | let shouldClose = menuPosition == .left ? !leftToRight && sideMenuContainerView.frame.maxX < menuWidth : leftToRight && sideMenuContainerView.frame.minX > (sourceView.frame.size.width - menuWidth) 447 | 448 | toggleMenu(!shouldClose) 449 | 450 | } 451 | } 452 | 453 | fileprivate func updateSideMenuApperanceIfNeeded () { 454 | if (needUpdateApperance) { 455 | var frame = sideMenuContainerView.frame 456 | frame.size.width = menuWidth 457 | sideMenuContainerView.frame = frame 458 | sideMenuContainerView.layer.shadowPath = UIBezierPath(rect: sideMenuContainerView.bounds).cgPath 459 | 460 | needUpdateApperance = false 461 | } 462 | } 463 | 464 | /** 465 | Toggles the state of the side menu. 466 | */ 467 | open func toggleMenu () { 468 | if (isMenuOpen) { 469 | toggleMenu(false) 470 | } 471 | else { 472 | updateSideMenuApperanceIfNeeded() 473 | toggleMenu(true) 474 | } 475 | } 476 | /** 477 | Shows the side menu if the menu is hidden. 478 | */ 479 | open func showSideMenu () { 480 | if (!isMenuOpen) { 481 | toggleMenu(true) 482 | } 483 | } 484 | /** 485 | Hides the side menu if the menu is showed. 486 | */ 487 | open func hideSideMenu () { 488 | if (isMenuOpen) { 489 | toggleMenu(false) 490 | } 491 | } 492 | } 493 | 494 | extension ENSideMenu: UIDynamicAnimatorDelegate { 495 | public func dynamicAnimatorDidPause(_ animator: UIDynamicAnimator) { 496 | if (isMenuOpen) { 497 | delegate?.sideMenuDidOpen() 498 | } else { 499 | delegate?.sideMenuDidClose() 500 | } 501 | } 502 | } 503 | -------------------------------------------------------------------------------- /Library/ENSideMenuNavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RootNavigationViewController.swift 3 | // SwiftSideMenu 4 | // 5 | // Created by Evgeny Nazarov on 29.09.14. 6 | // Copyright (c) 2014 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class ENSideMenuNavigationController: UINavigationController, ENSideMenuProtocol { 12 | 13 | open var sideMenu : ENSideMenu? 14 | open var sideMenuAnimationType : ENSideMenuAnimation = .default 15 | 16 | 17 | // MARK: - Life cycle 18 | open override func viewDidLoad() { 19 | super.viewDidLoad() 20 | } 21 | 22 | public init( menuViewController: UIViewController, contentViewController: UIViewController?) { 23 | super.init(nibName: nil, bundle: nil) 24 | 25 | if (contentViewController != nil) { 26 | self.viewControllers = [contentViewController!] 27 | } 28 | 29 | sideMenu = ENSideMenu(sourceView: self.view, menuViewController: menuViewController, menuPosition:.left) 30 | view.bringSubviewToFront(navigationBar) 31 | } 32 | 33 | required public init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | } 36 | 37 | open override func didReceiveMemoryWarning() { 38 | super.didReceiveMemoryWarning() 39 | // Dispose of any resources that can be recreated. 40 | } 41 | 42 | // MARK: - Navigation 43 | open func setContentViewController(_ contentViewController: UIViewController) { 44 | self.sideMenu?.toggleMenu() 45 | switch sideMenuAnimationType { 46 | case .none: 47 | self.viewControllers = [contentViewController] 48 | break 49 | default: 50 | contentViewController.navigationItem.hidesBackButton = true 51 | self.setViewControllers([contentViewController], animated: true) 52 | break 53 | } 54 | 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5C23D7071A6038B40004FF06 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C23D7061A6038B40004FF06 /* main.m */; }; 11 | 5C23D70A1A6038B40004FF06 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C23D7091A6038B40004FF06 /* AppDelegate.m */; }; 12 | 5C23D70D1A6038B40004FF06 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C23D70C1A6038B40004FF06 /* ViewController.m */; }; 13 | 5C23D7101A6038B40004FF06 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5C23D70E1A6038B40004FF06 /* Main.storyboard */; }; 14 | 5C23D7121A6038B40004FF06 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5C23D7111A6038B40004FF06 /* Images.xcassets */; }; 15 | 5C23D7151A6038B40004FF06 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5C23D7131A6038B40004FF06 /* LaunchScreen.xib */; }; 16 | 5C23D7211A6038B40004FF06 /* ObjCExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C23D7201A6038B40004FF06 /* ObjCExampleTests.m */; }; 17 | 5C23D72D1A60394E0004FF06 /* ENSideMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C23D72B1A60394E0004FF06 /* ENSideMenu.swift */; }; 18 | 5C23D72E1A60394E0004FF06 /* ENSideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C23D72C1A60394E0004FF06 /* ENSideMenuNavigationController.swift */; }; 19 | 5C23D7311A603B830004FF06 /* MenuItemsTVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C23D7301A603B830004FF06 /* MenuItemsTVC.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 5C23D71B1A6038B40004FF06 /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 5C23D6F91A6038B40004FF06 /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = 5C23D7001A6038B40004FF06; 28 | remoteInfo = ObjCExample; 29 | }; 30 | /* End PBXContainerItemProxy section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 5C23D7011A6038B40004FF06 /* ObjCExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ObjCExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 5C23D7051A6038B40004FF06 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 35 | 5C23D7061A6038B40004FF06 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 36 | 5C23D7081A6038B40004FF06 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 37 | 5C23D7091A6038B40004FF06 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 38 | 5C23D70B1A6038B40004FF06 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 39 | 5C23D70C1A6038B40004FF06 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 40 | 5C23D70F1A6038B40004FF06 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 41 | 5C23D7111A6038B40004FF06 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 42 | 5C23D7141A6038B40004FF06 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 43 | 5C23D71A1A6038B40004FF06 /* ObjCExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ObjCExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 5C23D71F1A6038B40004FF06 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | 5C23D7201A6038B40004FF06 /* ObjCExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjCExampleTests.m; sourceTree = ""; }; 46 | 5C23D72B1A60394E0004FF06 /* ENSideMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ENSideMenu.swift; sourceTree = ""; }; 47 | 5C23D72C1A60394E0004FF06 /* ENSideMenuNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ENSideMenuNavigationController.swift; sourceTree = ""; }; 48 | 5C23D72F1A603B830004FF06 /* MenuItemsTVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MenuItemsTVC.h; sourceTree = ""; }; 49 | 5C23D7301A603B830004FF06 /* MenuItemsTVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MenuItemsTVC.m; sourceTree = ""; }; 50 | /* End PBXFileReference section */ 51 | 52 | /* Begin PBXFrameworksBuildPhase section */ 53 | 5C23D6FE1A6038B40004FF06 /* Frameworks */ = { 54 | isa = PBXFrameworksBuildPhase; 55 | buildActionMask = 2147483647; 56 | files = ( 57 | ); 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | 5C23D7171A6038B40004FF06 /* Frameworks */ = { 61 | isa = PBXFrameworksBuildPhase; 62 | buildActionMask = 2147483647; 63 | files = ( 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | /* End PBXFrameworksBuildPhase section */ 68 | 69 | /* Begin PBXGroup section */ 70 | 5C23D6F81A6038B40004FF06 = { 71 | isa = PBXGroup; 72 | children = ( 73 | 5C23D7031A6038B40004FF06 /* ObjCExample */, 74 | 5C23D71D1A6038B40004FF06 /* ObjCExampleTests */, 75 | 5C23D7021A6038B40004FF06 /* Products */, 76 | ); 77 | sourceTree = ""; 78 | }; 79 | 5C23D7021A6038B40004FF06 /* Products */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 5C23D7011A6038B40004FF06 /* ObjCExample.app */, 83 | 5C23D71A1A6038B40004FF06 /* ObjCExampleTests.xctest */, 84 | ); 85 | name = Products; 86 | sourceTree = ""; 87 | }; 88 | 5C23D7031A6038B40004FF06 /* ObjCExample */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 5C23D72A1A60394E0004FF06 /* Library */, 92 | 5C23D7081A6038B40004FF06 /* AppDelegate.h */, 93 | 5C23D7091A6038B40004FF06 /* AppDelegate.m */, 94 | 5C23D72F1A603B830004FF06 /* MenuItemsTVC.h */, 95 | 5C23D7301A603B830004FF06 /* MenuItemsTVC.m */, 96 | 5C23D70B1A6038B40004FF06 /* ViewController.h */, 97 | 5C23D70C1A6038B40004FF06 /* ViewController.m */, 98 | 5C23D70E1A6038B40004FF06 /* Main.storyboard */, 99 | 5C23D7111A6038B40004FF06 /* Images.xcassets */, 100 | 5C23D7131A6038B40004FF06 /* LaunchScreen.xib */, 101 | 5C23D7041A6038B40004FF06 /* Supporting Files */, 102 | ); 103 | path = ObjCExample; 104 | sourceTree = ""; 105 | }; 106 | 5C23D7041A6038B40004FF06 /* Supporting Files */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 5C23D7051A6038B40004FF06 /* Info.plist */, 110 | 5C23D7061A6038B40004FF06 /* main.m */, 111 | ); 112 | name = "Supporting Files"; 113 | sourceTree = ""; 114 | }; 115 | 5C23D71D1A6038B40004FF06 /* ObjCExampleTests */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 5C23D7201A6038B40004FF06 /* ObjCExampleTests.m */, 119 | 5C23D71E1A6038B40004FF06 /* Supporting Files */, 120 | ); 121 | path = ObjCExampleTests; 122 | sourceTree = ""; 123 | }; 124 | 5C23D71E1A6038B40004FF06 /* Supporting Files */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 5C23D71F1A6038B40004FF06 /* Info.plist */, 128 | ); 129 | name = "Supporting Files"; 130 | sourceTree = ""; 131 | }; 132 | 5C23D72A1A60394E0004FF06 /* Library */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 5C23D72B1A60394E0004FF06 /* ENSideMenu.swift */, 136 | 5C23D72C1A60394E0004FF06 /* ENSideMenuNavigationController.swift */, 137 | ); 138 | name = Library; 139 | path = ../../Library; 140 | sourceTree = ""; 141 | }; 142 | /* End PBXGroup section */ 143 | 144 | /* Begin PBXNativeTarget section */ 145 | 5C23D7001A6038B40004FF06 /* ObjCExample */ = { 146 | isa = PBXNativeTarget; 147 | buildConfigurationList = 5C23D7241A6038B40004FF06 /* Build configuration list for PBXNativeTarget "ObjCExample" */; 148 | buildPhases = ( 149 | 5C23D6FD1A6038B40004FF06 /* Sources */, 150 | 5C23D6FE1A6038B40004FF06 /* Frameworks */, 151 | 5C23D6FF1A6038B40004FF06 /* Resources */, 152 | ); 153 | buildRules = ( 154 | ); 155 | dependencies = ( 156 | ); 157 | name = ObjCExample; 158 | productName = ObjCExample; 159 | productReference = 5C23D7011A6038B40004FF06 /* ObjCExample.app */; 160 | productType = "com.apple.product-type.application"; 161 | }; 162 | 5C23D7191A6038B40004FF06 /* ObjCExampleTests */ = { 163 | isa = PBXNativeTarget; 164 | buildConfigurationList = 5C23D7271A6038B40004FF06 /* Build configuration list for PBXNativeTarget "ObjCExampleTests" */; 165 | buildPhases = ( 166 | 5C23D7161A6038B40004FF06 /* Sources */, 167 | 5C23D7171A6038B40004FF06 /* Frameworks */, 168 | 5C23D7181A6038B40004FF06 /* Resources */, 169 | ); 170 | buildRules = ( 171 | ); 172 | dependencies = ( 173 | 5C23D71C1A6038B40004FF06 /* PBXTargetDependency */, 174 | ); 175 | name = ObjCExampleTests; 176 | productName = ObjCExampleTests; 177 | productReference = 5C23D71A1A6038B40004FF06 /* ObjCExampleTests.xctest */; 178 | productType = "com.apple.product-type.bundle.unit-test"; 179 | }; 180 | /* End PBXNativeTarget section */ 181 | 182 | /* Begin PBXProject section */ 183 | 5C23D6F91A6038B40004FF06 /* Project object */ = { 184 | isa = PBXProject; 185 | attributes = { 186 | LastUpgradeCheck = 0610; 187 | ORGANIZATIONNAME = "Evgeny Nazarov"; 188 | TargetAttributes = { 189 | 5C23D7001A6038B40004FF06 = { 190 | CreatedOnToolsVersion = 6.1.1; 191 | }; 192 | 5C23D7191A6038B40004FF06 = { 193 | CreatedOnToolsVersion = 6.1.1; 194 | TestTargetID = 5C23D7001A6038B40004FF06; 195 | }; 196 | }; 197 | }; 198 | buildConfigurationList = 5C23D6FC1A6038B40004FF06 /* Build configuration list for PBXProject "ObjCExample" */; 199 | compatibilityVersion = "Xcode 3.2"; 200 | developmentRegion = English; 201 | hasScannedForEncodings = 0; 202 | knownRegions = ( 203 | en, 204 | Base, 205 | ); 206 | mainGroup = 5C23D6F81A6038B40004FF06; 207 | productRefGroup = 5C23D7021A6038B40004FF06 /* Products */; 208 | projectDirPath = ""; 209 | projectRoot = ""; 210 | targets = ( 211 | 5C23D7001A6038B40004FF06 /* ObjCExample */, 212 | 5C23D7191A6038B40004FF06 /* ObjCExampleTests */, 213 | ); 214 | }; 215 | /* End PBXProject section */ 216 | 217 | /* Begin PBXResourcesBuildPhase section */ 218 | 5C23D6FF1A6038B40004FF06 /* Resources */ = { 219 | isa = PBXResourcesBuildPhase; 220 | buildActionMask = 2147483647; 221 | files = ( 222 | 5C23D7101A6038B40004FF06 /* Main.storyboard in Resources */, 223 | 5C23D7151A6038B40004FF06 /* LaunchScreen.xib in Resources */, 224 | 5C23D7121A6038B40004FF06 /* Images.xcassets in Resources */, 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | 5C23D7181A6038B40004FF06 /* Resources */ = { 229 | isa = PBXResourcesBuildPhase; 230 | buildActionMask = 2147483647; 231 | files = ( 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | /* End PBXResourcesBuildPhase section */ 236 | 237 | /* Begin PBXSourcesBuildPhase section */ 238 | 5C23D6FD1A6038B40004FF06 /* Sources */ = { 239 | isa = PBXSourcesBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | 5C23D72D1A60394E0004FF06 /* ENSideMenu.swift in Sources */, 243 | 5C23D7311A603B830004FF06 /* MenuItemsTVC.m in Sources */, 244 | 5C23D70D1A6038B40004FF06 /* ViewController.m in Sources */, 245 | 5C23D70A1A6038B40004FF06 /* AppDelegate.m in Sources */, 246 | 5C23D72E1A60394E0004FF06 /* ENSideMenuNavigationController.swift in Sources */, 247 | 5C23D7071A6038B40004FF06 /* main.m in Sources */, 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | 5C23D7161A6038B40004FF06 /* Sources */ = { 252 | isa = PBXSourcesBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | 5C23D7211A6038B40004FF06 /* ObjCExampleTests.m in Sources */, 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | /* End PBXSourcesBuildPhase section */ 260 | 261 | /* Begin PBXTargetDependency section */ 262 | 5C23D71C1A6038B40004FF06 /* PBXTargetDependency */ = { 263 | isa = PBXTargetDependency; 264 | target = 5C23D7001A6038B40004FF06 /* ObjCExample */; 265 | targetProxy = 5C23D71B1A6038B40004FF06 /* PBXContainerItemProxy */; 266 | }; 267 | /* End PBXTargetDependency section */ 268 | 269 | /* Begin PBXVariantGroup section */ 270 | 5C23D70E1A6038B40004FF06 /* Main.storyboard */ = { 271 | isa = PBXVariantGroup; 272 | children = ( 273 | 5C23D70F1A6038B40004FF06 /* Base */, 274 | ); 275 | name = Main.storyboard; 276 | sourceTree = ""; 277 | }; 278 | 5C23D7131A6038B40004FF06 /* LaunchScreen.xib */ = { 279 | isa = PBXVariantGroup; 280 | children = ( 281 | 5C23D7141A6038B40004FF06 /* Base */, 282 | ); 283 | name = LaunchScreen.xib; 284 | sourceTree = ""; 285 | }; 286 | /* End PBXVariantGroup section */ 287 | 288 | /* Begin XCBuildConfiguration section */ 289 | 5C23D7221A6038B40004FF06 /* Debug */ = { 290 | isa = XCBuildConfiguration; 291 | buildSettings = { 292 | ALWAYS_SEARCH_USER_PATHS = NO; 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_EMPTY_BODY = YES; 301 | CLANG_WARN_ENUM_CONVERSION = YES; 302 | CLANG_WARN_INT_CONVERSION = YES; 303 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 304 | CLANG_WARN_UNREACHABLE_CODE = YES; 305 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 306 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 307 | COPY_PHASE_STRIP = NO; 308 | ENABLE_STRICT_OBJC_MSGSEND = YES; 309 | GCC_C_LANGUAGE_STANDARD = gnu99; 310 | GCC_DYNAMIC_NO_PIC = NO; 311 | GCC_OPTIMIZATION_LEVEL = 0; 312 | GCC_PREPROCESSOR_DEFINITIONS = ( 313 | "DEBUG=1", 314 | "$(inherited)", 315 | ); 316 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 317 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 318 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 319 | GCC_WARN_UNDECLARED_SELECTOR = YES; 320 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 321 | GCC_WARN_UNUSED_FUNCTION = YES; 322 | GCC_WARN_UNUSED_VARIABLE = YES; 323 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 324 | MTL_ENABLE_DEBUG_INFO = YES; 325 | ONLY_ACTIVE_ARCH = YES; 326 | SDKROOT = iphoneos; 327 | }; 328 | name = Debug; 329 | }; 330 | 5C23D7231A6038B40004FF06 /* Release */ = { 331 | isa = XCBuildConfiguration; 332 | buildSettings = { 333 | ALWAYS_SEARCH_USER_PATHS = NO; 334 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 335 | CLANG_CXX_LIBRARY = "libc++"; 336 | CLANG_ENABLE_MODULES = YES; 337 | CLANG_ENABLE_OBJC_ARC = YES; 338 | CLANG_WARN_BOOL_CONVERSION = YES; 339 | CLANG_WARN_CONSTANT_CONVERSION = YES; 340 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 341 | CLANG_WARN_EMPTY_BODY = YES; 342 | CLANG_WARN_ENUM_CONVERSION = YES; 343 | CLANG_WARN_INT_CONVERSION = YES; 344 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 345 | CLANG_WARN_UNREACHABLE_CODE = YES; 346 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 347 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 348 | COPY_PHASE_STRIP = YES; 349 | ENABLE_NS_ASSERTIONS = NO; 350 | ENABLE_STRICT_OBJC_MSGSEND = YES; 351 | GCC_C_LANGUAGE_STANDARD = gnu99; 352 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 353 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 354 | GCC_WARN_UNDECLARED_SELECTOR = YES; 355 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 356 | GCC_WARN_UNUSED_FUNCTION = YES; 357 | GCC_WARN_UNUSED_VARIABLE = YES; 358 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 359 | MTL_ENABLE_DEBUG_INFO = NO; 360 | SDKROOT = iphoneos; 361 | VALIDATE_PRODUCT = YES; 362 | }; 363 | name = Release; 364 | }; 365 | 5C23D7251A6038B40004FF06 /* Debug */ = { 366 | isa = XCBuildConfiguration; 367 | buildSettings = { 368 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 369 | INFOPLIST_FILE = ObjCExample/Info.plist; 370 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 371 | PRODUCT_NAME = "$(TARGET_NAME)"; 372 | }; 373 | name = Debug; 374 | }; 375 | 5C23D7261A6038B40004FF06 /* Release */ = { 376 | isa = XCBuildConfiguration; 377 | buildSettings = { 378 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 379 | INFOPLIST_FILE = ObjCExample/Info.plist; 380 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 381 | PRODUCT_NAME = "$(TARGET_NAME)"; 382 | }; 383 | name = Release; 384 | }; 385 | 5C23D7281A6038B40004FF06 /* Debug */ = { 386 | isa = XCBuildConfiguration; 387 | buildSettings = { 388 | BUNDLE_LOADER = "$(TEST_HOST)"; 389 | FRAMEWORK_SEARCH_PATHS = ( 390 | "$(SDKROOT)/Developer/Library/Frameworks", 391 | "$(inherited)", 392 | ); 393 | GCC_PREPROCESSOR_DEFINITIONS = ( 394 | "DEBUG=1", 395 | "$(inherited)", 396 | ); 397 | INFOPLIST_FILE = ObjCExampleTests/Info.plist; 398 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 399 | PRODUCT_NAME = "$(TARGET_NAME)"; 400 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ObjCExample.app/ObjCExample"; 401 | }; 402 | name = Debug; 403 | }; 404 | 5C23D7291A6038B40004FF06 /* Release */ = { 405 | isa = XCBuildConfiguration; 406 | buildSettings = { 407 | BUNDLE_LOADER = "$(TEST_HOST)"; 408 | FRAMEWORK_SEARCH_PATHS = ( 409 | "$(SDKROOT)/Developer/Library/Frameworks", 410 | "$(inherited)", 411 | ); 412 | INFOPLIST_FILE = ObjCExampleTests/Info.plist; 413 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 414 | PRODUCT_NAME = "$(TARGET_NAME)"; 415 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ObjCExample.app/ObjCExample"; 416 | }; 417 | name = Release; 418 | }; 419 | /* End XCBuildConfiguration section */ 420 | 421 | /* Begin XCConfigurationList section */ 422 | 5C23D6FC1A6038B40004FF06 /* Build configuration list for PBXProject "ObjCExample" */ = { 423 | isa = XCConfigurationList; 424 | buildConfigurations = ( 425 | 5C23D7221A6038B40004FF06 /* Debug */, 426 | 5C23D7231A6038B40004FF06 /* Release */, 427 | ); 428 | defaultConfigurationIsVisible = 0; 429 | defaultConfigurationName = Release; 430 | }; 431 | 5C23D7241A6038B40004FF06 /* Build configuration list for PBXNativeTarget "ObjCExample" */ = { 432 | isa = XCConfigurationList; 433 | buildConfigurations = ( 434 | 5C23D7251A6038B40004FF06 /* Debug */, 435 | 5C23D7261A6038B40004FF06 /* Release */, 436 | ); 437 | defaultConfigurationIsVisible = 0; 438 | defaultConfigurationName = Release; 439 | }; 440 | 5C23D7271A6038B40004FF06 /* Build configuration list for PBXNativeTarget "ObjCExampleTests" */ = { 441 | isa = XCConfigurationList; 442 | buildConfigurations = ( 443 | 5C23D7281A6038B40004FF06 /* Debug */, 444 | 5C23D7291A6038B40004FF06 /* Release */, 445 | ); 446 | defaultConfigurationIsVisible = 0; 447 | defaultConfigurationName = Release; 448 | }; 449 | /* End XCConfigurationList section */ 450 | }; 451 | rootObject = 5C23D6F91A6038B40004FF06 /* Project object */; 452 | } 453 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample.xcodeproj/project.xcworkspace/xcuserdata/evgeny.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/touchasky/ENSwiftSideMenu/4a585ea393e4a7254507b4b196f5a7e6784ff6de/ObjCExample/ObjCExample.xcodeproj/project.xcworkspace/xcuserdata/evgeny.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ObjCExample/ObjCExample.xcodeproj/xcuserdata/evgeny.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample.xcodeproj/xcuserdata/evgeny.xcuserdatad/xcschemes/ObjCExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample.xcodeproj/xcuserdata/evgeny.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ObjCExample.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 5C23D7001A6038B40004FF06 16 | 17 | primary 18 | 19 | 20 | 5C23D7191A6038B40004FF06 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ObjCExample 4 | // 5 | // Created by Evgeny on 09.01.15. 6 | // Copyright (c) 2015 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ObjCExample 4 | // 5 | // Created by Evgeny on 09.01.15. 6 | // Copyright (c) 2015 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | // Name of your project + '-Swift.h' 12 | // There is no autocomplete while you typing 13 | // Go inside this class to understand how works swift code in the objc project 14 | #import "objcexample-Swift.h" 15 | 16 | #import "MenuItemsTVC.h" 17 | 18 | @interface AppDelegate () 19 | 20 | @end 21 | 22 | @implementation AppDelegate 23 | 24 | 25 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 26 | // Override point for customization after application launch. 27 | MenuItemsTVC *sideMenuTVC = [MenuItemsTVC new]; 28 | UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 29 | UIViewController *contentVC = [storyboard instantiateViewControllerWithIdentifier:@"ViewController1"]; 30 | 31 | ENSideMenuNavigationController *navVC = [[ENSideMenuNavigationController alloc] initWithMenuTableViewController:sideMenuTVC 32 | contentViewController:contentVC]; 33 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 34 | [self.window setRootViewController:navVC]; 35 | [self.window makeKeyAndVisible]; 36 | return YES; 37 | } 38 | 39 | - (void)applicationWillResignActive:(UIApplication *)application { 40 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 41 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 42 | } 43 | 44 | - (void)applicationDidEnterBackground:(UIApplication *)application { 45 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 46 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 47 | } 48 | 49 | - (void)applicationWillEnterForeground:(UIApplication *)application { 50 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 51 | } 52 | 53 | - (void)applicationDidBecomeActive:(UIApplication *)application { 54 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 55 | } 56 | 57 | - (void)applicationWillTerminate:(UIApplication *)application { 58 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | ru.enazarov.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/MenuItemsTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // MenuItemsTVC.h 3 | // ObjCExample 4 | // 5 | // Created by Evgeny on 09.01.15. 6 | // Copyright (c) 2015 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MenuItemsTVC : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/MenuItemsTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // MenuItemsTVC.m 3 | // ObjCExample 4 | // 5 | // Created by Evgeny on 09.01.15. 6 | // Copyright (c) 2015 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | #import "MenuItemsTVC.h" 10 | #import "objcexample-Swift.h" 11 | 12 | @implementation MenuItemsTVC 13 | 14 | - (void)viewDidLoad { 15 | [super viewDidLoad]; 16 | [self.tableView setContentInset:UIEdgeInsetsMake(64.f, 0, 0, 0)]; 17 | [self.tableView setBackgroundColor:[UIColor clearColor]]; 18 | } 19 | 20 | #pragma mark - Table view data source 21 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 22 | // Return the number of sections. 23 | return 1; 24 | } 25 | 26 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 27 | // Return the number of rows in the section. 28 | return 2; 29 | } 30 | 31 | 32 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 33 | static NSString *cellID = @"Cell"; 34 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; 35 | if (cell == nil) { 36 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; 37 | cell.backgroundColor = [UIColor clearColor]; 38 | UIView *selectionView = [[UIView alloc] initWithFrame:cell.bounds]; 39 | selectionView.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.3f]; 40 | [cell setSelectedBackgroundView:selectionView]; 41 | } 42 | cell.textLabel.text = [NSString stringWithFormat:@"Row %ld", (long)indexPath.row]; 43 | 44 | return cell; 45 | } 46 | 47 | #pragma mark - UITableView Delegate 48 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 49 | { 50 | UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 51 | UIViewController *destTVC = nil; 52 | switch (indexPath.row) { 53 | case 0: 54 | destTVC = [storyboard instantiateViewControllerWithIdentifier:@"ViewController1"]; 55 | break; 56 | default: 57 | destTVC = [storyboard instantiateViewControllerWithIdentifier:@"ViewController2"]; 58 | break; 59 | } 60 | 61 | [self.sideMenuController setContentViewController:destTVC]; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // ObjCExample 4 | // 5 | // Created by Evgeny on 09.01.15. 6 | // Copyright (c) 2015 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // ObjCExample 4 | // 5 | // Created by Evgeny on 09.01.15. 6 | // Copyright (c) 2015 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "objcexample-Swift.h" 11 | 12 | @interface ViewController () 13 | 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | // Do any additional setup after loading the view, typically from a nib. 21 | UIBarButtonItem *toggleButton = [[UIBarButtonItem alloc] initWithTitle:@"Toggle" style:UIBarButtonItemStylePlain target:self action:@selector(toggleSideMenuView)]; 22 | [self.navigationItem setLeftBarButtonItem:toggleButton]; 23 | } 24 | 25 | - (void)didReceiveMemoryWarning { 26 | [super didReceiveMemoryWarning]; 27 | // Dispose of any resources that can be recreated. 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ObjCExample 4 | // 5 | // Created by Evgeny on 09.01.15. 6 | // Copyright (c) 2015 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | ru.enazarov.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExampleTests/ObjCExampleTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ObjCExampleTests.m 3 | // ObjCExampleTests 4 | // 5 | // Created by Evgeny on 09.01.15. 6 | // Copyright (c) 2015 Evgeny Nazarov. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ObjCExampleTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation ObjCExampleTests 17 | 18 | - (void)setUp { 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 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "ENSwiftSideMenu", 7 | platforms: [ 8 | .iOS(.v10) 9 | ], 10 | products: [ 11 | .library(name: "ENSwiftSideMenu", targets: ["ENSwiftSideMenu"]), 12 | ], 13 | targets: [ 14 | .target(name: "ENSwiftSideMenu", path: "Library"), 15 | ] 16 | ) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ENSwiftSideMenu 2 | 3 | A lightweight flyover side menu component for iOS with the ```UIDynamic```'s bouncing animation, ```UIGestures``` and ```UIBlurEffect```. Allows you to use native ```UINavigationController```'s logic to manage view controllers. The component is written in **Swift**. 4 | 5 | ![](https://github.com/evnaz/ENSwiftSideMenu/blob/master/demo.gif) 6 | 7 | ## Requirements 8 | * iOS 9 or higher 9 | 10 | ## Installation 11 | ### CocoaPods 12 | The recommended way for installating `ENSwiftSideMenu` is via the [CocoaPods](http://cocoapods.org/) package manager 13 | ``` bash 14 | platform :ios, '9.0' 15 | pod 'ENSwiftSideMenu', '~> 0.1.4' 16 | ``` 17 | ### Manual Install 18 | All you need is import `ENSideMenu.swift` and `ENSideMenuNavigationController.swift` to your project folder. 19 | 20 | ## Usage Example 21 | 1. Create a root UINavigationController subclassing from ENSideMenuNavigationController 22 | 2. Create a UIViewController for your side menu 23 | 3. Initilize the menu view with a source view and menu view controller: 24 | 25 | ```swift 26 | override func viewDidLoad() { 27 | super.viewDidLoad() 28 | sideMenu = ENSideMenu(sourceView: self.view, menuViewController: MyMenuViewController(), menuPosition:.Left) 29 | // show the navigation bar over the side menu view 30 | view.bringSubviewToFront(navigationBar) 31 | } 32 | ``` 33 | 34 | 4. To change content view controller use next line in your menu view controller: 35 | 36 | ```swift 37 | sideMenuController()?.setContentViewController(destViewController) 38 | ``` 39 | 40 | 5. Check example project for more explanation 41 | 42 | ## License 43 | 44 | The MIT License (MIT) 45 | 46 | Copyright (c) 2014 Evgeny Nazarov 47 | 48 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 49 | 50 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 51 | 52 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 53 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/touchasky/ENSwiftSideMenu/4a585ea393e4a7254507b4b196f5a7e6784ff6de/demo.gif --------------------------------------------------------------------------------