├── .DS_Store ├── .gitignore ├── IntroductionExample.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ ├── Ryan.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ ├── matthewyork.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings │ │ └── shams.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── Ryan.xcuserdatad │ └── xcschemes │ │ ├── IntroductionExample.xcscheme │ │ └── xcschememanagement.plist │ ├── matthewyork.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints.xcbkptlist │ └── xcschemes │ │ ├── IntroductionExample.xcscheme │ │ └── xcschememanagement.plist │ └── shams.xcuserdatad │ └── xcschemes │ ├── IntroductionExample.xcscheme │ └── xcschememanagement.plist ├── IntroductionExample ├── Default-568h@2x.png ├── Default.png ├── Default@2x.png ├── IntroductionExample-Info.plist ├── IntroductionExample-Prefix.pch ├── MYAppDelegate.h ├── MYAppDelegate.m ├── MYIntroductionPanel.h ├── MYIntroductionPanel.m ├── MYIntroductionView.h ├── MYIntroductionView.m ├── MYViewController.h ├── MYViewController.m ├── SampleBackground.png ├── SampleHeaderImage.png ├── SampleImage1.png ├── SampleImage2.png ├── en.lproj │ ├── InfoPlist.strings │ └── MYViewController.xib └── main.m ├── LICENSE ├── MYIntroduction.podspec ├── README.md └── Resources └── Images └── IntercedeScreenshot.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatthewYork/iPhone-IntroductionTutorial/4e44cf359bf654edf756047ee9da0f77d086ec2d/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | *.xcuserstate 20 | XXX.xcodeproj/project.xcworkspace/xcuserdata/xxx.xcuserdatad/UserInterfaceState.xcuserstate 21 | *.xcuserstate 22 | -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6C0E2DB817CE369400D18105 /* MYViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0E2DB717CE369300D18105 /* MYViewController.m */; }; 11 | F02BB21516E847B400E3D502 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F02BB21416E847B400E3D502 /* UIKit.framework */; }; 12 | F02BB21716E847B400E3D502 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F02BB21616E847B400E3D502 /* Foundation.framework */; }; 13 | F02BB21916E847B400E3D502 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F02BB21816E847B400E3D502 /* CoreGraphics.framework */; }; 14 | F02BB21F16E847B400E3D502 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F02BB21D16E847B400E3D502 /* InfoPlist.strings */; }; 15 | F02BB22116E847B400E3D502 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F02BB22016E847B400E3D502 /* main.m */; }; 16 | F02BB22516E847B400E3D502 /* MYAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F02BB22416E847B400E3D502 /* MYAppDelegate.m */; }; 17 | F02BB22716E847B400E3D502 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = F02BB22616E847B400E3D502 /* Default.png */; }; 18 | F02BB22916E847B400E3D502 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F02BB22816E847B400E3D502 /* Default@2x.png */; }; 19 | F02BB22B16E847B400E3D502 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F02BB22A16E847B400E3D502 /* Default-568h@2x.png */; }; 20 | F02BB23116E847B400E3D502 /* MYViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F02BB22F16E847B400E3D502 /* MYViewController.xib */; }; 21 | F02BB23916E847D600E3D502 /* MYIntroductionView.m in Sources */ = {isa = PBXBuildFile; fileRef = F02BB23816E847D600E3D502 /* MYIntroductionView.m */; }; 22 | F02BB24116E8576100E3D502 /* MYIntroductionPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = F02BB24016E8576100E3D502 /* MYIntroductionPanel.m */; }; 23 | F02BB24816E961B300E3D502 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F02BB24716E961B300E3D502 /* QuartzCore.framework */; }; 24 | F02BB25A16E9991F00E3D502 /* SampleHeaderImage.png in Resources */ = {isa = PBXBuildFile; fileRef = F02BB25916E9991F00E3D502 /* SampleHeaderImage.png */; }; 25 | F02BB26816E9A67C00E3D502 /* SampleBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = F02BB26716E9A67C00E3D502 /* SampleBackground.png */; }; 26 | F0558C4716EEBEF100B8BFA3 /* SampleImage1.png in Resources */ = {isa = PBXBuildFile; fileRef = F0558C4616EEBEF100B8BFA3 /* SampleImage1.png */; }; 27 | F0558C4916EEC0D400B8BFA3 /* SampleImage2.png in Resources */ = {isa = PBXBuildFile; fileRef = F0558C4816EEC0D400B8BFA3 /* SampleImage2.png */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | 6C0E2DB717CE369300D18105 /* MYViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYViewController.m; sourceTree = ""; }; 32 | F02BB21116E847B400E3D502 /* IntroductionExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IntroductionExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | F02BB21416E847B400E3D502 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 34 | F02BB21616E847B400E3D502 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 35 | F02BB21816E847B400E3D502 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 36 | F02BB21C16E847B400E3D502 /* IntroductionExample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "IntroductionExample-Info.plist"; sourceTree = ""; }; 37 | F02BB21E16E847B400E3D502 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 38 | F02BB22016E847B400E3D502 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 39 | F02BB22216E847B400E3D502 /* IntroductionExample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "IntroductionExample-Prefix.pch"; sourceTree = ""; }; 40 | F02BB22316E847B400E3D502 /* MYAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MYAppDelegate.h; sourceTree = ""; }; 41 | F02BB22416E847B400E3D502 /* MYAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MYAppDelegate.m; sourceTree = ""; }; 42 | F02BB22616E847B400E3D502 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 43 | F02BB22816E847B400E3D502 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 44 | F02BB22A16E847B400E3D502 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 45 | F02BB22C16E847B400E3D502 /* MYViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MYViewController.h; sourceTree = ""; }; 46 | F02BB23016E847B400E3D502 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MYViewController.xib; sourceTree = ""; }; 47 | F02BB23716E847D600E3D502 /* MYIntroductionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYIntroductionView.h; sourceTree = ""; }; 48 | F02BB23816E847D600E3D502 /* MYIntroductionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYIntroductionView.m; sourceTree = ""; }; 49 | F02BB23F16E8576100E3D502 /* MYIntroductionPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYIntroductionPanel.h; sourceTree = ""; }; 50 | F02BB24016E8576100E3D502 /* MYIntroductionPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYIntroductionPanel.m; sourceTree = ""; }; 51 | F02BB24716E961B300E3D502 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 52 | F02BB25916E9991F00E3D502 /* SampleHeaderImage.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SampleHeaderImage.png; sourceTree = ""; }; 53 | F02BB26716E9A67C00E3D502 /* SampleBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SampleBackground.png; sourceTree = ""; }; 54 | F0558C4616EEBEF100B8BFA3 /* SampleImage1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SampleImage1.png; sourceTree = ""; }; 55 | F0558C4816EEC0D400B8BFA3 /* SampleImage2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SampleImage2.png; sourceTree = ""; }; 56 | /* End PBXFileReference section */ 57 | 58 | /* Begin PBXFrameworksBuildPhase section */ 59 | F02BB20E16E847B400E3D502 /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | F02BB24816E961B300E3D502 /* QuartzCore.framework in Frameworks */, 64 | F02BB21516E847B400E3D502 /* UIKit.framework in Frameworks */, 65 | F02BB21716E847B400E3D502 /* Foundation.framework in Frameworks */, 66 | F02BB21916E847B400E3D502 /* CoreGraphics.framework in Frameworks */, 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | /* End PBXFrameworksBuildPhase section */ 71 | 72 | /* Begin PBXGroup section */ 73 | F02BB20816E847B400E3D502 = { 74 | isa = PBXGroup; 75 | children = ( 76 | F02BB21A16E847B400E3D502 /* IntroductionExample */, 77 | F02BB21316E847B400E3D502 /* Frameworks */, 78 | F02BB21216E847B400E3D502 /* Products */, 79 | ); 80 | sourceTree = ""; 81 | }; 82 | F02BB21216E847B400E3D502 /* Products */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | F02BB21116E847B400E3D502 /* IntroductionExample.app */, 86 | ); 87 | name = Products; 88 | sourceTree = ""; 89 | }; 90 | F02BB21316E847B400E3D502 /* Frameworks */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | F02BB24716E961B300E3D502 /* QuartzCore.framework */, 94 | F02BB21416E847B400E3D502 /* UIKit.framework */, 95 | F02BB21616E847B400E3D502 /* Foundation.framework */, 96 | F02BB21816E847B400E3D502 /* CoreGraphics.framework */, 97 | ); 98 | name = Frameworks; 99 | sourceTree = ""; 100 | }; 101 | F02BB21A16E847B400E3D502 /* IntroductionExample */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | F02BB22316E847B400E3D502 /* MYAppDelegate.h */, 105 | F02BB22416E847B400E3D502 /* MYAppDelegate.m */, 106 | F02BB22C16E847B400E3D502 /* MYViewController.h */, 107 | 6C0E2DB717CE369300D18105 /* MYViewController.m */, 108 | F02BB22F16E847B400E3D502 /* MYViewController.xib */, 109 | F02BB24216E90F6A00E3D502 /* MYIntroductionView */, 110 | F02BB21B16E847B400E3D502 /* Supporting Files */, 111 | ); 112 | path = IntroductionExample; 113 | sourceTree = ""; 114 | }; 115 | F02BB21B16E847B400E3D502 /* Supporting Files */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | F0558C4616EEBEF100B8BFA3 /* SampleImage1.png */, 119 | F0558C4816EEC0D400B8BFA3 /* SampleImage2.png */, 120 | F02BB25916E9991F00E3D502 /* SampleHeaderImage.png */, 121 | F02BB26716E9A67C00E3D502 /* SampleBackground.png */, 122 | F02BB21C16E847B400E3D502 /* IntroductionExample-Info.plist */, 123 | F02BB21D16E847B400E3D502 /* InfoPlist.strings */, 124 | F02BB22016E847B400E3D502 /* main.m */, 125 | F02BB22216E847B400E3D502 /* IntroductionExample-Prefix.pch */, 126 | F02BB22616E847B400E3D502 /* Default.png */, 127 | F02BB22816E847B400E3D502 /* Default@2x.png */, 128 | F02BB22A16E847B400E3D502 /* Default-568h@2x.png */, 129 | ); 130 | name = "Supporting Files"; 131 | sourceTree = ""; 132 | }; 133 | F02BB24216E90F6A00E3D502 /* MYIntroductionView */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | F02BB23716E847D600E3D502 /* MYIntroductionView.h */, 137 | F02BB23816E847D600E3D502 /* MYIntroductionView.m */, 138 | F02BB23F16E8576100E3D502 /* MYIntroductionPanel.h */, 139 | F02BB24016E8576100E3D502 /* MYIntroductionPanel.m */, 140 | ); 141 | name = MYIntroductionView; 142 | sourceTree = ""; 143 | }; 144 | /* End PBXGroup section */ 145 | 146 | /* Begin PBXNativeTarget section */ 147 | F02BB21016E847B400E3D502 /* IntroductionExample */ = { 148 | isa = PBXNativeTarget; 149 | buildConfigurationList = F02BB23416E847B400E3D502 /* Build configuration list for PBXNativeTarget "IntroductionExample" */; 150 | buildPhases = ( 151 | F02BB20D16E847B400E3D502 /* Sources */, 152 | F02BB20E16E847B400E3D502 /* Frameworks */, 153 | F02BB20F16E847B400E3D502 /* Resources */, 154 | ); 155 | buildRules = ( 156 | ); 157 | dependencies = ( 158 | ); 159 | name = IntroductionExample; 160 | productName = IntroductionExample; 161 | productReference = F02BB21116E847B400E3D502 /* IntroductionExample.app */; 162 | productType = "com.apple.product-type.application"; 163 | }; 164 | /* End PBXNativeTarget section */ 165 | 166 | /* Begin PBXProject section */ 167 | F02BB20916E847B400E3D502 /* Project object */ = { 168 | isa = PBXProject; 169 | attributes = { 170 | CLASSPREFIX = MY; 171 | LastUpgradeCheck = 0460; 172 | ORGANIZATIONNAME = "Matthew York"; 173 | }; 174 | buildConfigurationList = F02BB20C16E847B400E3D502 /* Build configuration list for PBXProject "IntroductionExample" */; 175 | compatibilityVersion = "Xcode 3.2"; 176 | developmentRegion = English; 177 | hasScannedForEncodings = 0; 178 | knownRegions = ( 179 | en, 180 | ); 181 | mainGroup = F02BB20816E847B400E3D502; 182 | productRefGroup = F02BB21216E847B400E3D502 /* Products */; 183 | projectDirPath = ""; 184 | projectRoot = ""; 185 | targets = ( 186 | F02BB21016E847B400E3D502 /* IntroductionExample */, 187 | ); 188 | }; 189 | /* End PBXProject section */ 190 | 191 | /* Begin PBXResourcesBuildPhase section */ 192 | F02BB20F16E847B400E3D502 /* Resources */ = { 193 | isa = PBXResourcesBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | F02BB21F16E847B400E3D502 /* InfoPlist.strings in Resources */, 197 | F02BB22716E847B400E3D502 /* Default.png in Resources */, 198 | F02BB22916E847B400E3D502 /* Default@2x.png in Resources */, 199 | F02BB22B16E847B400E3D502 /* Default-568h@2x.png in Resources */, 200 | F02BB23116E847B400E3D502 /* MYViewController.xib in Resources */, 201 | F02BB25A16E9991F00E3D502 /* SampleHeaderImage.png in Resources */, 202 | F02BB26816E9A67C00E3D502 /* SampleBackground.png in Resources */, 203 | F0558C4716EEBEF100B8BFA3 /* SampleImage1.png in Resources */, 204 | F0558C4916EEC0D400B8BFA3 /* SampleImage2.png in Resources */, 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | /* End PBXResourcesBuildPhase section */ 209 | 210 | /* Begin PBXSourcesBuildPhase section */ 211 | F02BB20D16E847B400E3D502 /* Sources */ = { 212 | isa = PBXSourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | F02BB22116E847B400E3D502 /* main.m in Sources */, 216 | F02BB22516E847B400E3D502 /* MYAppDelegate.m in Sources */, 217 | F02BB23916E847D600E3D502 /* MYIntroductionView.m in Sources */, 218 | F02BB24116E8576100E3D502 /* MYIntroductionPanel.m in Sources */, 219 | 6C0E2DB817CE369400D18105 /* MYViewController.m in Sources */, 220 | ); 221 | runOnlyForDeploymentPostprocessing = 0; 222 | }; 223 | /* End PBXSourcesBuildPhase section */ 224 | 225 | /* Begin PBXVariantGroup section */ 226 | F02BB21D16E847B400E3D502 /* InfoPlist.strings */ = { 227 | isa = PBXVariantGroup; 228 | children = ( 229 | F02BB21E16E847B400E3D502 /* en */, 230 | ); 231 | name = InfoPlist.strings; 232 | sourceTree = ""; 233 | }; 234 | F02BB22F16E847B400E3D502 /* MYViewController.xib */ = { 235 | isa = PBXVariantGroup; 236 | children = ( 237 | F02BB23016E847B400E3D502 /* en */, 238 | ); 239 | name = MYViewController.xib; 240 | sourceTree = ""; 241 | }; 242 | /* End PBXVariantGroup section */ 243 | 244 | /* Begin XCBuildConfiguration section */ 245 | F02BB23216E847B400E3D502 /* Debug */ = { 246 | isa = XCBuildConfiguration; 247 | buildSettings = { 248 | ALWAYS_SEARCH_USER_PATHS = NO; 249 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 250 | CLANG_CXX_LIBRARY = "libc++"; 251 | CLANG_ENABLE_OBJC_ARC = YES; 252 | CLANG_WARN_CONSTANT_CONVERSION = YES; 253 | CLANG_WARN_EMPTY_BODY = YES; 254 | CLANG_WARN_ENUM_CONVERSION = YES; 255 | CLANG_WARN_INT_CONVERSION = YES; 256 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 257 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 258 | COPY_PHASE_STRIP = NO; 259 | GCC_C_LANGUAGE_STANDARD = gnu99; 260 | GCC_DYNAMIC_NO_PIC = NO; 261 | GCC_OPTIMIZATION_LEVEL = 0; 262 | GCC_PREPROCESSOR_DEFINITIONS = ( 263 | "DEBUG=1", 264 | "$(inherited)", 265 | ); 266 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 267 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 268 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 269 | GCC_WARN_UNUSED_VARIABLE = YES; 270 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 271 | ONLY_ACTIVE_ARCH = YES; 272 | SDKROOT = iphoneos; 273 | }; 274 | name = Debug; 275 | }; 276 | F02BB23316E847B400E3D502 /* Release */ = { 277 | isa = XCBuildConfiguration; 278 | buildSettings = { 279 | ALWAYS_SEARCH_USER_PATHS = NO; 280 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 281 | CLANG_CXX_LIBRARY = "libc++"; 282 | CLANG_ENABLE_OBJC_ARC = YES; 283 | CLANG_WARN_CONSTANT_CONVERSION = YES; 284 | CLANG_WARN_EMPTY_BODY = YES; 285 | CLANG_WARN_ENUM_CONVERSION = YES; 286 | CLANG_WARN_INT_CONVERSION = YES; 287 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 288 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 289 | COPY_PHASE_STRIP = YES; 290 | GCC_C_LANGUAGE_STANDARD = gnu99; 291 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 292 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 293 | GCC_WARN_UNUSED_VARIABLE = YES; 294 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 295 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 296 | SDKROOT = iphoneos; 297 | VALIDATE_PRODUCT = YES; 298 | }; 299 | name = Release; 300 | }; 301 | F02BB23516E847B400E3D502 /* Debug */ = { 302 | isa = XCBuildConfiguration; 303 | buildSettings = { 304 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 305 | GCC_PREFIX_HEADER = "IntroductionExample/IntroductionExample-Prefix.pch"; 306 | INFOPLIST_FILE = "IntroductionExample/IntroductionExample-Info.plist"; 307 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 308 | PRODUCT_NAME = "$(TARGET_NAME)"; 309 | TARGETED_DEVICE_FAMILY = "1,2"; 310 | WRAPPER_EXTENSION = app; 311 | }; 312 | name = Debug; 313 | }; 314 | F02BB23616E847B400E3D502 /* Release */ = { 315 | isa = XCBuildConfiguration; 316 | buildSettings = { 317 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 318 | GCC_PREFIX_HEADER = "IntroductionExample/IntroductionExample-Prefix.pch"; 319 | INFOPLIST_FILE = "IntroductionExample/IntroductionExample-Info.plist"; 320 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 321 | PRODUCT_NAME = "$(TARGET_NAME)"; 322 | TARGETED_DEVICE_FAMILY = "1,2"; 323 | WRAPPER_EXTENSION = app; 324 | }; 325 | name = Release; 326 | }; 327 | /* End XCBuildConfiguration section */ 328 | 329 | /* Begin XCConfigurationList section */ 330 | F02BB20C16E847B400E3D502 /* Build configuration list for PBXProject "IntroductionExample" */ = { 331 | isa = XCConfigurationList; 332 | buildConfigurations = ( 333 | F02BB23216E847B400E3D502 /* Debug */, 334 | F02BB23316E847B400E3D502 /* Release */, 335 | ); 336 | defaultConfigurationIsVisible = 0; 337 | defaultConfigurationName = Release; 338 | }; 339 | F02BB23416E847B400E3D502 /* Build configuration list for PBXNativeTarget "IntroductionExample" */ = { 340 | isa = XCConfigurationList; 341 | buildConfigurations = ( 342 | F02BB23516E847B400E3D502 /* Debug */, 343 | F02BB23616E847B400E3D502 /* Release */, 344 | ); 345 | defaultConfigurationIsVisible = 0; 346 | defaultConfigurationName = Release; 347 | }; 348 | /* End XCConfigurationList section */ 349 | }; 350 | rootObject = F02BB20916E847B400E3D502 /* Project object */; 351 | } 352 | -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/project.xcworkspace/xcuserdata/Ryan.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatthewYork/iPhone-IntroductionTutorial/4e44cf359bf654edf756047ee9da0f77d086ec2d/IntroductionExample.xcodeproj/project.xcworkspace/xcuserdata/Ryan.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/project.xcworkspace/xcuserdata/matthewyork.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatthewYork/iPhone-IntroductionTutorial/4e44cf359bf654edf756047ee9da0f77d086ec2d/IntroductionExample.xcodeproj/project.xcworkspace/xcuserdata/matthewyork.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/project.xcworkspace/xcuserdata/matthewyork.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/project.xcworkspace/xcuserdata/shams.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatthewYork/iPhone-IntroductionTutorial/4e44cf359bf654edf756047ee9da0f77d086ec2d/IntroductionExample.xcodeproj/project.xcworkspace/xcuserdata/shams.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/xcuserdata/Ryan.xcuserdatad/xcschemes/IntroductionExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/xcuserdata/Ryan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | IntroductionExample.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | F02BB21016E847B400E3D502 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/xcuserdata/matthewyork.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 18 | 19 | 31 | 32 | 44 | 45 | 57 | 58 | 70 | 71 | 83 | 84 | 96 | 97 | 109 | 110 | 122 | 123 | 135 | 136 | 148 | 149 | 161 | 162 | 174 | 175 | 187 | 188 | 200 | 201 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/xcuserdata/matthewyork.xcuserdatad/xcschemes/IntroductionExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/xcuserdata/matthewyork.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | IntroductionExample.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | F02BB21016E847B400E3D502 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/xcuserdata/shams.xcuserdatad/xcschemes/IntroductionExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /IntroductionExample.xcodeproj/xcuserdata/shams.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | IntroductionExample.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | F02BB21016E847B400E3D502 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /IntroductionExample/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatthewYork/iPhone-IntroductionTutorial/4e44cf359bf654edf756047ee9da0f77d086ec2d/IntroductionExample/Default-568h@2x.png -------------------------------------------------------------------------------- /IntroductionExample/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatthewYork/iPhone-IntroductionTutorial/4e44cf359bf654edf756047ee9da0f77d086ec2d/IntroductionExample/Default.png -------------------------------------------------------------------------------- /IntroductionExample/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatthewYork/iPhone-IntroductionTutorial/4e44cf359bf654edf756047ee9da0f77d086ec2d/IntroductionExample/Default@2x.png -------------------------------------------------------------------------------- /IntroductionExample/IntroductionExample-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Introduction 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIcons 12 | 13 | CFBundlePrimaryIcon 14 | 15 | CFBundleIconFiles 16 | 17 | 18 | 19 | CFBundleIdentifier 20 | com.mattyork.${PRODUCT_NAME:rfc1034identifier} 21 | CFBundleInfoDictionaryVersion 22 | 6.0 23 | CFBundleName 24 | Introduction 25 | CFBundlePackageType 26 | APPL 27 | CFBundleShortVersionString 28 | 1.0 29 | CFBundleSignature 30 | ???? 31 | CFBundleVersion 32 | 1.0 33 | LSRequiresIPhoneOS 34 | 35 | UIRequiredDeviceCapabilities 36 | 37 | armv7 38 | 39 | UISupportedInterfaceOrientations 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | UISupportedInterfaceOrientations~ipad 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationPortraitUpsideDown 51 | UIInterfaceOrientationLandscapeRight 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /IntroductionExample/IntroductionExample-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'IntroductionExample' target in the 'IntroductionExample' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /IntroductionExample/MYAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MYAppDelegate.h 3 | // IntroductionExample 4 | // 5 | // Copyright (C) 2013, Matt York 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | // this software and associated documentation files (the "Software"), to deal in 9 | // the Software without restriction, including without limitation the rights to 10 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | // of the Software, and to permit persons to whom the Software is furnished to do 12 | // so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @class MYViewController; 29 | 30 | @interface MYAppDelegate : UIResponder 31 | 32 | @property (strong, nonatomic) UIWindow *window; 33 | 34 | @property (strong, nonatomic) MYViewController *viewController; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /IntroductionExample/MYAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // MYAppDelegate.m 3 | // IntroductionExample 4 | // 5 | // Copyright (C) 2013, Matt York 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | // this software and associated documentation files (the "Software"), to deal in 9 | // the Software without restriction, including without limitation the rights to 10 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | // of the Software, and to permit persons to whom the Software is furnished to do 12 | // so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | // 25 | 26 | #import "MYAppDelegate.h" 27 | 28 | #import "MYViewController.h" 29 | 30 | @implementation MYAppDelegate 31 | 32 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 33 | { 34 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 35 | // Override point for customization after application launch. 36 | self.viewController = [[MYViewController alloc] initWithNibName:@"MYViewController" bundle:nil]; 37 | self.window.rootViewController = self.viewController; 38 | [self.window makeKeyAndVisible]; 39 | return YES; 40 | } 41 | 42 | - (void)applicationWillResignActive:(UIApplication *)application 43 | { 44 | // 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. 45 | // 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. 46 | } 47 | 48 | - (void)applicationDidEnterBackground:(UIApplication *)application 49 | { 50 | // 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. 51 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 52 | } 53 | 54 | - (void)applicationWillEnterForeground:(UIApplication *)application 55 | { 56 | // 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. 57 | } 58 | 59 | - (void)applicationDidBecomeActive:(UIApplication *)application 60 | { 61 | // 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. 62 | } 63 | 64 | - (void)applicationWillTerminate:(UIApplication *)application 65 | { 66 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /IntroductionExample/MYIntroductionPanel.h: -------------------------------------------------------------------------------- 1 | // 2 | // MYIntroductionPanel.h 3 | // IntroductionExample 4 | // 5 | // Copyright (C) 2013, Matt York 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | // this software and associated documentation files (the "Software"), to deal in 9 | // the Software without restriction, including without limitation the rights to 10 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | // of the Software, and to permit persons to whom the Software is furnished to do 12 | // so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @interface MYIntroductionPanel : NSObject 29 | 30 | @property (nonatomic, retain) UIView *PanelContentView; 31 | 32 | //Title 33 | @property (nonatomic, retain) NSString *Title; 34 | 35 | //Description 36 | @property (nonatomic, retain) NSString *Description; 37 | 38 | //Custom init method 39 | -(id)initWithimage:(UIImage *)image title:(NSString *)title description:(NSString *)description; 40 | -(id)initWithimage:(UIImage *)image description:(NSString *)description; 41 | -(id)initWithContentView:(UIView*)view; 42 | 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /IntroductionExample/MYIntroductionPanel.m: -------------------------------------------------------------------------------- 1 | // 2 | // MYIntroductionPanel.m 3 | // IntroductionExample 4 | // 5 | // Copyright (C) 2013, Matt York 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | // this software and associated documentation files (the "Software"), to deal in 9 | // the Software without restriction, including without limitation the rights to 10 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | // of the Software, and to permit persons to whom the Software is furnished to do 12 | // so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | // 25 | 26 | #import "MYIntroductionPanel.h" 27 | #import 28 | 29 | @implementation MYIntroductionPanel 30 | 31 | -(id)initWithimage:(UIImage *)image title:(NSString *)title description:(NSString *)description{ 32 | if (self = [super init]) { 33 | //Set panel Image 34 | [self setupPanelContentViewWithImage:image]; 35 | 36 | self.Title = title; 37 | 38 | //Set panel Description 39 | self.Description = [[NSString alloc] initWithString:description]; 40 | } 41 | return self; 42 | } 43 | 44 | -(id)initWithimage:(UIImage *)image description:(NSString *)description{ 45 | if (self = [super init]) { 46 | //Set panel Image 47 | [self setupPanelContentViewWithImage:image]; 48 | 49 | self.Title = @""; 50 | 51 | //Set panel Description 52 | self.Description = [[NSString alloc] initWithString:description]; 53 | } 54 | return self; 55 | } 56 | 57 | -(id)initWithContentView:(UIView*)view { 58 | if(self = [super init]) { 59 | self.PanelContentView = view; 60 | self.Title = @""; 61 | self.PanelContentView.clipsToBounds = YES; 62 | } 63 | return self; 64 | } 65 | 66 | -(void)setupPanelContentViewWithImage:(UIImage*)image { 67 | self.PanelContentView = [[UIImageView alloc] initWithImage:image]; 68 | self.PanelContentView.contentMode = UIViewContentModeScaleAspectFit; 69 | self.PanelContentView.backgroundColor = [UIColor clearColor]; 70 | self.PanelContentView.layer.cornerRadius = 3; 71 | self.PanelContentView.clipsToBounds = YES; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /IntroductionExample/MYIntroductionView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MYIntroductionView.h 3 | // IntroductionExample 4 | // 5 | // Copyright (C) 2013, Matt York 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | // this software and associated documentation files (the "Software"), to deal in 9 | // the Software without restriction, including without limitation the rights to 10 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | // of the Software, and to permit persons to whom the Software is furnished to do 12 | // so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | // 25 | 26 | #import 27 | #import "MYIntroductionPanel.h" 28 | #import 29 | 30 | typedef enum { 31 | MYFinishTypeSwipeOut = 0, 32 | MYFinishTypeSkipButton 33 | }MYFinishType; 34 | 35 | typedef enum { 36 | MYLanguageDirectionLeftToRight = 0, 37 | MYLanguageDirectionRightToLeft 38 | }MYLanguageDirection; 39 | 40 | /******************************/ 41 | //Delegate Method Declarations 42 | /******************************/ 43 | @protocol MYIntroductionDelegate 44 | @optional 45 | -(void)introductionDidFinishWithType:(MYFinishType)finishType; 46 | -(void)introductionDidChangeToPanel:(MYIntroductionPanel *)panel withIndex:(NSInteger)panelIndex; 47 | @end 48 | 49 | 50 | /******************************/ 51 | //MYIntroductionView 52 | /******************************/ 53 | @interface MYIntroductionView : UIView { 54 | 55 | //Array of panel objects passed in at initialization 56 | NSArray *Panels; 57 | 58 | //Array of views created by MYIntroductionController from MYIntroductionPanel objects. For internal use only. 59 | NSMutableArray *panelViews; 60 | 61 | //Keeps track of the index of the last panel navigated to. For internal use only. 62 | NSInteger LastPanelIndex; 63 | 64 | //Variable keeping track of language direction 65 | MYLanguageDirection LanguageDirection; 66 | } 67 | 68 | 69 | /******************************/ 70 | //Properties 71 | /******************************/ 72 | 73 | //Delegate 74 | @property (weak) id delegate; 75 | 76 | //Panel management 77 | @property (nonatomic, assign) NSInteger CurrentPanelIndex; 78 | 79 | //Intoduction Properties 80 | @property (nonatomic, retain) UIImageView *BackgroundImageView; 81 | 82 | //Header properties 83 | @property (nonatomic, retain) UILabel *HeaderLabel; 84 | @property (nonatomic, retain) UIImageView *HeaderImageView; 85 | @property (nonatomic, retain) UIView *HeaderView; 86 | 87 | //Content properties 88 | @property (nonatomic, retain) UIScrollView *ContentScrollView; 89 | 90 | //PageControl/Skip Button 91 | @property (nonatomic, retain) UIPageControl *PageControl; 92 | @property (nonatomic, retain) UIButton *SkipButton; 93 | 94 | //Nuts & Bolts 95 | @property BOOL device; 96 | @property BOOL device_orientation; 97 | 98 | 99 | /******************************/ 100 | //Methods 101 | /******************************/ 102 | 103 | //Custom Init Methods 104 | - (id)initWithFrame:(CGRect)frame headerText:(NSString *)headerText panels:(NSArray *)panels; 105 | - (id)initWithFrame:(CGRect)frame headerImage:(UIImage *)headerImage panels:(NSArray *)panels; 106 | - (id)initWithFrame:(CGRect)frame headerText:(NSString *)headerText panels:(NSArray *)panels languageDirection:(MYLanguageDirection)languageDirection; 107 | - (id)initWithFrame:(CGRect)frame headerImage:(UIImage *)headerImage panels:(NSArray *)panels languageDirection:(MYLanguageDirection)languageDirection; 108 | - (id)initWithFrame:(CGRect)frame panels:(NSArray *)panels; 109 | - (id)initWithFrame:(CGRect)frame panels:(NSArray *)panels languageDirection:(MYLanguageDirection)languageDirection; 110 | 111 | //Header Content 112 | -(void)setHeaderText:(NSString *)headerText; 113 | -(void)setHeaderImage:(UIImage *)headerImage; 114 | 115 | //Introduction Content 116 | -(void)setBackgroundImage:(UIImage *)backgroundImage; 117 | -(void)setBackgroundColor:(UIColor *)backgroundColor; 118 | 119 | //Show/Hide 120 | -(void)showInView:(UIView *)view animateDuration:(CGFloat)duration; 121 | -(void)hideWithFadeOutDuration:(CGFloat)duration; 122 | 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /IntroductionExample/MYIntroductionView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MYIntroductionView.m 3 | // IntroductionExample 4 | // 5 | // Copyright (C) 2013, Matt York 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | // this software and associated documentation files (the "Software"), to deal in 9 | // the Software without restriction, including without limitation the rights to 10 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | // of the Software, and to permit persons to whom the Software is furnished to do 12 | // so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | // 25 | 26 | #import "MYIntroductionView.h" 27 | 28 | #define DEFAULT_BACKGROUND_COLOR [UIColor colorWithWhite:0 alpha:0.9] 29 | #define HEADER_VIEW_HEIGHT 45 30 | #define PAGE_CONTROL_PADDING 1 31 | #define TITLE_FONT [UIFont fontWithName:@"HelveticaNeue-Bold" size:16.0] 32 | #define TITLE_TEXT_COLOR [UIColor whiteColor] 33 | #define DESCRIPTION_FONT [UIFont fontWithName:@"HelveticaNeue-Light" size:13.0] 34 | #define DESCRIPTION_TEXT_COLOR [UIColor whiteColor] 35 | 36 | @implementation MYIntroductionView 37 | @synthesize delegate, device, device_orientation; 38 | 39 | - (id)initWithFrame:(CGRect)frame 40 | { 41 | self = [super initWithFrame:frame]; 42 | if (self) { 43 | // Initialization code 44 | [self initializeClassVariables]; 45 | [self buildUIWithFrame:frame headerViewVisible:YES]; 46 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 47 | } 48 | return self; 49 | } 50 | 51 | - (id)initWithFrame:(CGRect)frame headerText:(NSString *)headerText panels:(NSArray *)panels 52 | { 53 | self = [super initWithFrame:frame]; 54 | if (self) { 55 | // Initialization code 56 | [self initializeClassVariables]; 57 | Panels = [panels copy]; 58 | LanguageDirection = MYLanguageDirectionLeftToRight; 59 | [self buildUIWithFrame:frame headerViewVisible:YES]; 60 | [self setHeaderText:headerText]; 61 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 62 | } 63 | return self; 64 | } 65 | 66 | - (id)initWithFrame:(CGRect)frame headerImage:(UIImage *)headerImage panels:(NSArray *)panels 67 | { 68 | self = [super initWithFrame:frame]; 69 | if (self) { 70 | // Initialization code 71 | [self initializeClassVariables]; 72 | Panels = [panels copy]; 73 | LanguageDirection = MYLanguageDirectionLeftToRight; 74 | [self buildUIWithFrame:frame headerViewVisible:YES]; 75 | [self setHeaderImage:headerImage]; 76 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 77 | } 78 | return self; 79 | } 80 | 81 | - (id)initWithFrame:(CGRect)frame headerText:(NSString *)headerText panels:(NSArray *)panels languageDirection:(MYLanguageDirection)languageDirection 82 | { 83 | self = [super initWithFrame:frame]; 84 | if (self) { 85 | // Initialization code 86 | [self initializeClassVariables]; 87 | Panels = [panels copy]; 88 | LanguageDirection = languageDirection; 89 | [self buildUIWithFrame:frame headerViewVisible:YES]; 90 | [self setHeaderText:headerText]; 91 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 92 | } 93 | return self; 94 | } 95 | 96 | - (id)initWithFrame:(CGRect)frame headerImage:(UIImage *)headerImage panels:(NSArray *)panels languageDirection:(MYLanguageDirection)languageDirection 97 | { 98 | self = [super initWithFrame:frame]; 99 | if (self) { 100 | // Initialization code 101 | [self initializeClassVariables]; 102 | Panels = [panels copy]; 103 | LanguageDirection = languageDirection; 104 | [self buildUIWithFrame:frame headerViewVisible:YES]; 105 | [self setHeaderImage:headerImage]; 106 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 107 | } 108 | return self; 109 | } 110 | 111 | - (id)initWithFrame:(CGRect)frame panels:(NSArray *)panels 112 | { 113 | self = [super initWithFrame:frame]; 114 | if (self) { 115 | // Initialization code 116 | [self initializeClassVariables]; 117 | Panels = [panels copy]; 118 | LanguageDirection = MYLanguageDirectionLeftToRight; 119 | [self buildUIWithFrame:frame headerViewVisible:NO]; 120 | [self setHeaderText:nil]; 121 | } 122 | return self; 123 | } 124 | 125 | - (id)initWithFrame:(CGRect)frame panels:(NSArray *)panels languageDirection:(MYLanguageDirection)languageDirection 126 | { 127 | self = [super initWithFrame:frame]; 128 | if (self) { 129 | // Initialization code 130 | [self initializeClassVariables]; 131 | Panels = [panels copy]; 132 | LanguageDirection = languageDirection; 133 | [self buildUIWithFrame:frame headerViewVisible:NO]; 134 | [self setHeaderText:nil]; 135 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 136 | } 137 | return self; 138 | } 139 | 140 | 141 | -(void)initializeClassVariables{ 142 | panelViews = [[NSMutableArray alloc] init]; 143 | self.device = [self getCurrentDevice]; 144 | self.device_orientation = [self getCurrentOrientation]; 145 | } 146 | 147 | #pragma mark - UI Builder Methods 148 | 149 | -(BOOL)getCurrentDevice { 150 | return [[UIDevice currentDevice] userInterfaceIdiom]; //iPhone 1; iPad 0; 151 | } 152 | 153 | -(BOOL)getCurrentOrientation { 154 | switch ([[UIApplication sharedApplication] statusBarOrientation]) { 155 | case UIInterfaceOrientationPortrait: 156 | return 0; 157 | break; 158 | case UIInterfaceOrientationPortraitUpsideDown: 159 | return 0; 160 | break; 161 | case UIInterfaceOrientationLandscapeLeft: 162 | return 1; 163 | break; 164 | case UIInterfaceOrientationLandscapeRight: 165 | return 1; 166 | break; 167 | default: 168 | return 0; 169 | break; 170 | } 171 | } 172 | 173 | -(void)buildUIWithFrame:(CGRect)frame headerViewVisible:(BOOL)headerViewVisible{ 174 | self.backgroundColor = DEFAULT_BACKGROUND_COLOR; 175 | 176 | [self buildBackgroundImage]; 177 | [self buildHeaderViewWithFrame:frame visible:headerViewVisible]; 178 | [self buildContentScrollViewWithFrame:frame]; 179 | [self buildFooterView]; 180 | 181 | [self.BackgroundImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 182 | [self.HeaderImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 183 | [self.HeaderLabel setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 184 | [self.HeaderView setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 185 | [self.PageControl setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 186 | [self.SkipButton setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 187 | } 188 | 189 | -(void)buildBackgroundImage{ 190 | self.BackgroundImageView = [[UIImageView alloc] initWithFrame:self.frame]; 191 | self.BackgroundImageView.backgroundColor = [UIColor clearColor]; 192 | self.BackgroundImageView.contentMode = UIViewContentModeScaleToFill; 193 | self.BackgroundImageView.autoresizesSubviews = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 194 | [self addSubview:self.BackgroundImageView]; 195 | } 196 | 197 | -(void)buildHeaderViewWithFrame:(CGRect)frame visible:(BOOL)visible{ 198 | if (!visible) { 199 | self.HeaderView = [[UIView alloc] initWithFrame:CGRectZero]; 200 | return; 201 | } 202 | 203 | float headerYOffset = 5; 204 | if ([MYIntroductionView runningiOS7]) { 205 | headerYOffset = headerYOffset + 20; 206 | } 207 | 208 | self.HeaderView = [[UIView alloc] initWithFrame:CGRectMake(5, headerYOffset, frame.size.width - 10, HEADER_VIEW_HEIGHT)]; //Leave 5px padding on all sides 209 | self.HeaderView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth; 210 | self.HeaderView.backgroundColor = [UIColor clearColor]; 211 | 212 | //Setup HeaderImageView 213 | self.HeaderImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.HeaderView.frame.size.width, self.HeaderView.frame.size.height)]; 214 | self.HeaderImageView.backgroundColor = [UIColor clearColor]; 215 | self.HeaderImageView.contentMode = UIViewContentModeScaleAspectFit; 216 | self.HeaderImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth; 217 | [self.HeaderView addSubview:self.HeaderImageView]; 218 | self.HeaderImageView.hidden = YES; 219 | 220 | //Setup HeaderLabel 221 | self.HeaderLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.HeaderView.frame.size.width, self.HeaderView.frame.size.height)]; 222 | self.HeaderLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:25.0]; 223 | self.HeaderLabel.textColor = [UIColor whiteColor]; 224 | self.HeaderLabel.backgroundColor = [UIColor clearColor]; 225 | self.HeaderLabel.textAlignment = NSTextAlignmentCenter; 226 | self.HeaderLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; 227 | [self.HeaderView addSubview:self.HeaderLabel]; 228 | self.HeaderLabel.hidden = YES; 229 | [self addSubview:self.HeaderView]; 230 | 231 | // Add a drop shadow to the header text 232 | /* 233 | self.HeaderLabel.layer.shadowColor = [[UIColor blackColor]CGColor]; 234 | self.HeaderLabel.layer.shadowOffset = CGSizeMake(1.0f, 1.0f); 235 | self.HeaderLabel.layer.shadowOpacity = 1.0f; 236 | self.HeaderLabel.layer.shadowRadius = 1.0f; 237 | */ 238 | } 239 | 240 | -(void)buildContentScrollViewWithFrame:(CGRect)frame{ 241 | float centerPadding = frame.size.width; 242 | float outerPadding = 0; 243 | if (self.device == 0) { // iPhone 244 | if (self.device_orientation == 1) { // 1 for landscape 245 | self.ContentScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, self.HeaderView.frame.origin.y + self.HeaderView.frame.size.height - HEADER_VIEW_HEIGHT, frame.size.width, 0)]; 246 | } else { 247 | self.ContentScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, self.HeaderView.frame.origin.y + self.HeaderView.frame.size.height, frame.size.width, 0)]; 248 | } 249 | } else { // iPad 250 | if (self.device_orientation == 1) { // 1 for landscape 251 | centerPadding = self.frame.size.height; 252 | outerPadding = (self.frame.size.width - self.frame.size.height)/2; 253 | NSLog(@"C:%f, O:%f", centerPadding, outerPadding); 254 | } 255 | self.ContentScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(outerPadding, self.HeaderView.frame.origin.y + self.HeaderView.frame.size.height + 10, centerPadding, 0)]; 256 | } 257 | 258 | self.ContentScrollView.pagingEnabled = YES; 259 | self.ContentScrollView.showsHorizontalScrollIndicator = NO; 260 | self.ContentScrollView.showsVerticalScrollIndicator = NO; 261 | self.ContentScrollView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; 262 | self.ContentScrollView.delegate = self; 263 | 264 | //If panels exist, build views for them and add them to the ContentScrollView 265 | if (Panels) { 266 | if (Panels.count > 0) { 267 | if (LanguageDirection == MYLanguageDirectionLeftToRight) { 268 | [self buildContentScrollViewLeftToRight]; 269 | } 270 | else if (LanguageDirection == MYLanguageDirectionRightToLeft) { 271 | [self buildContentScrollViewRightToLeft]; 272 | } 273 | } 274 | } 275 | } 276 | 277 | 278 | -(void)buildContentScrollViewLeftToRight{ 279 | //A running x-coordinate. This grows for every page 280 | CGFloat contentXIndex = 0; 281 | for (int ii = 0; ii < Panels.count; ii++) { 282 | 283 | //Create a new view for the panel and add it to the array 284 | [panelViews addObject:[self PanelViewForPanel:Panels[ii] atXIndex:&contentXIndex]]; 285 | 286 | //Add the newly created panel view to ContentScrollView 287 | [self.ContentScrollView addSubview:panelViews[ii]]; 288 | } 289 | 290 | 291 | [self makePanelVisibleAtIndex:0]; 292 | 293 | //Dynamically sizes the content to fit the text content 294 | [self setContentScrollViewHeightForPanelIndex:0 animated:NO]; 295 | 296 | //Add a view at the end. This is simply "something to scroll toward" on the final panel. 297 | [self appendCloseViewAtXIndex:&contentXIndex]; 298 | 299 | //Finally, resize the content size of the scrollview to account for all the new views added to it 300 | self.ContentScrollView.contentSize = CGSizeMake(contentXIndex, self.ContentScrollView.frame.size.height); 301 | 302 | //Add the ContentScrollView to the introduction view 303 | [self addSubview:self.ContentScrollView]; 304 | } 305 | 306 | -(void)buildContentScrollViewRightToLeft{ 307 | //A running x-coordinate. This grows for every page 308 | CGFloat contentXIndex = 0; 309 | 310 | //Add a view at the end. This is simply "something to scroll toward" on the final panel. 311 | [self appendCloseViewAtXIndex:&contentXIndex]; 312 | 313 | NSInteger panelViewIndex = 0; 314 | for (int ii = Panels.count-1; ii > -1; ii--) { 315 | 316 | //Create a new view for the panel and add it to the array 317 | [panelViews addObject:[self PanelViewForPanel:Panels[ii] atXIndex:&contentXIndex]]; 318 | 319 | //Add the newly created panel view to ContentScrollView 320 | [self.ContentScrollView addSubview:panelViews[panelViewIndex]]; 321 | panelViewIndex++; 322 | } 323 | 324 | [self makePanelVisibleAtIndex:panelViews.count-1]; 325 | self.CurrentPanelIndex = panelViews.count-1; 326 | self.PageControl.currentPage = panelViews.count -1; 327 | 328 | //Dynamically sizes the content to fit the text content 329 | [self setContentScrollViewHeightForPanelIndex:Panels.count-1 animated:NO]; 330 | 331 | //Finally, resize the content size of the scrollview to account for all the new views added to it 332 | self.ContentScrollView.contentSize = CGSizeMake(contentXIndex, self.ContentScrollView.frame.size.height); 333 | self.ContentScrollView.contentOffset = CGPointMake(contentXIndex-self.ContentScrollView.frame.size.width, 0); 334 | 335 | //Add the ContentScrollView to the introduction view 336 | [self addSubview:self.ContentScrollView]; 337 | } 338 | 339 | -(UIView *)PanelViewForPanel:(MYIntroductionPanel *)panel atXIndex:(CGFloat*)xIndex{ 340 | 341 | //Build panel now that we have all the desired dimensions 342 | UIView *panelView = [[UIView alloc] initWithFrame:CGRectMake(*xIndex, 0, self.ContentScrollView.frame.size.width, 0)]; 343 | 344 | CGFloat panelContentHeight = MIN(panel.PanelContentView.frame.size.height, self.frame.size.width - 10); 345 | CGFloat panelContentWidth = MIN(panel.PanelContentView.frame.size.width, self.ContentScrollView.frame.size.width); 346 | //Build title container (if applicable) 347 | CGRect panelTitleLabelFrame; 348 | UILabel *panelTitleLabel; 349 | if (![panel.Title isEqualToString:@""]) { 350 | float panelTitleHeight = 0; 351 | if ([MYIntroductionView runningiOS7]) { 352 | NSDictionary *stringAttributes = [NSDictionary dictionaryWithObject:TITLE_FONT forKey: NSFontAttributeName]; 353 | 354 | panelTitleHeight = [panel.Title boundingRectWithSize:CGSizeMake(self.ContentScrollView.frame.size.width - 20, 100) options:NSStringDrawingUsesLineFragmentOrigin attributes:stringAttributes context:nil].size.height; 355 | panelTitleHeight = ceilf(panelTitleHeight); 356 | } 357 | else { 358 | panelTitleHeight = [panel.Title sizeWithFont:TITLE_FONT constrainedToSize:CGSizeMake(self.ContentScrollView.frame.size.width - 20, 100) lineBreakMode:NSLineBreakByWordWrapping].height; 359 | } 360 | 361 | panelTitleLabelFrame = CGRectMake(10, panelContentHeight+5, self.ContentScrollView.frame.size.width - 20, panelTitleHeight); 362 | panelTitleLabel = [[UILabel alloc] initWithFrame:panelTitleLabelFrame]; 363 | panelTitleLabel.text = panel.Title; 364 | panelTitleLabel.numberOfLines = 0; 365 | panelTitleLabel.font = TITLE_FONT; 366 | panelTitleLabel.textColor = TITLE_TEXT_COLOR; 367 | panelTitleLabel.backgroundColor = [UIColor clearColor]; 368 | panelTitleLabel.textAlignment = NSTextAlignmentCenter; 369 | panelTitleLabel.lineBreakMode = NSLineBreakByWordWrapping; 370 | // Add a drop shadow to the title text 371 | /* 372 | panelTitleLabel.layer.shadowColor = [[UIColor blackColor]CGColor]; 373 | panelTitleLabel.layer.shadowOffset = CGSizeMake(1.0f, 1.0f); 374 | panelTitleLabel.layer.shadowOpacity = 1.0f; 375 | panelTitleLabel.layer.shadowRadius = 1.0f; 376 | */ 377 | } 378 | else { 379 | panelTitleLabelFrame = CGRectMake(10, panelContentHeight+5, self.ContentScrollView.frame.size.width - 20, 0); 380 | panelTitleLabel = [[UILabel alloc] initWithFrame:panelTitleLabelFrame]; 381 | } 382 | [panelView addSubview:panelTitleLabel]; 383 | 384 | //Build description container; 385 | UILabel *panelDescriptionLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.ContentScrollView.frame.size.width, 0)]; 386 | panelDescriptionLabel.backgroundColor = [UIColor clearColor]; 387 | panelDescriptionLabel.textAlignment = NSTextAlignmentCenter; 388 | panelDescriptionLabel.textColor = DESCRIPTION_TEXT_COLOR; 389 | panelDescriptionLabel.font = DESCRIPTION_FONT; 390 | panelDescriptionLabel.numberOfLines = 0; 391 | panelDescriptionLabel.text = panel.Description; 392 | [panelDescriptionLabel setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin]; 393 | [panelView addSubview:panelDescriptionLabel]; 394 | 395 | // Add a drop shadow to the description text 396 | /* 397 | panelDescriptionTextView.userInteractionEnabled = false; 398 | panelDescriptionTextView.layer.shadowColor = [[UIColor blackColor]CGColor]; 399 | panelDescriptionTextView.layer.shadowOffset = CGSizeMake(1.0f, 1.0f); 400 | panelDescriptionTextView.layer.shadowOpacity = 1.0f; 401 | panelDescriptionTextView.layer.shadowRadius = 1.0f; 402 | */ 403 | 404 | //Gather a few layout parameters 405 | //Get the maximum size the description text could be (screenHeight-panelParentContainerOrigin - footersize) 406 | 407 | CGFloat maxScrollViewHeight = self.frame.size.height - self.ContentScrollView.frame.origin.y - (36+PAGE_CONTROL_PADDING); 408 | 409 | float panelDescriptionHeight = 0; 410 | if ([MYIntroductionView runningiOS7]) { 411 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 412 | [paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping]; 413 | 414 | NSDictionary *stringAttributes = @{NSFontAttributeName:DESCRIPTION_FONT, NSParagraphStyleAttributeName:paragraphStyle}; 415 | 416 | panelDescriptionHeight = [panel.Description boundingRectWithSize:CGSizeMake(self.ContentScrollView.frame.size.width - 20, 100) options:NSStringDrawingUsesLineFragmentOrigin attributes:stringAttributes context:nil].size.height; 417 | panelDescriptionHeight = ceilf(panelDescriptionHeight); 418 | } 419 | else { 420 | panelDescriptionHeight = [panel.Description sizeWithFont:DESCRIPTION_FONT constrainedToSize:CGSizeMake(self.ContentScrollView.frame.size.width - 20, 100) lineBreakMode:NSLineBreakByWordWrapping].height; 421 | } 422 | panelDescriptionHeight = panelDescriptionHeight + 10; 423 | 424 | int contentWrappedScrollViewHeight = 0; 425 | if ((panelContentHeight + panelDescriptionHeight + panelTitleLabelFrame.size.height) > maxScrollViewHeight) { 426 | contentWrappedScrollViewHeight = maxScrollViewHeight; 427 | panelContentHeight = contentWrappedScrollViewHeight-panelDescriptionHeight - panelTitleLabelFrame.size.height - 10; 428 | } 429 | else if ((panelContentHeight+panelDescriptionHeight + panelTitleLabelFrame.size.height) <= maxScrollViewHeight){ 430 | contentWrappedScrollViewHeight = panelContentHeight + panelTitleLabelFrame.size.height + panelDescriptionHeight; 431 | } 432 | 433 | panelView.frame = CGRectMake(*xIndex, 0, self.ContentScrollView.frame.size.width, contentWrappedScrollViewHeight); 434 | 435 | //Build panel container 436 | panel.PanelContentView.frame = (CGRect) { 437 | .origin = CGPointMake(5 + self.ContentScrollView.frame.size.width/2 - panelContentWidth/2, 0), 438 | .size = CGSizeMake(panelContentWidth, panelContentHeight), 439 | }; 440 | [panelView addSubview:panel.PanelContentView]; 441 | 442 | 443 | //Update frames based on the new/scaled image size we just gathered 444 | panelTitleLabel.frame = CGRectMake(10, panelContentHeight + 5, panelTitleLabel.frame.size.width, panelTitleLabel.frame.size.height); 445 | panelDescriptionLabel.frame = CGRectMake(0, panelContentHeight + panelTitleLabel.frame.size.height + 5, self.ContentScrollView.frame.size.width, panelDescriptionHeight); 446 | 447 | //Update xIndex 448 | *xIndex += self.ContentScrollView.frame.size.width; 449 | 450 | return panelView; 451 | } 452 | 453 | -(void)appendCloseViewAtXIndex:(CGFloat*)xIndex{ 454 | UIView *closeView = [[UIView alloc] initWithFrame:CGRectMake(*xIndex, 0, self.frame.size.width, 400)]; 455 | 456 | [self.ContentScrollView addSubview:closeView]; 457 | 458 | *xIndex += self.ContentScrollView.frame.size.width; 459 | } 460 | 461 | -(void)showPanelAtPageControl { 462 | 463 | LastPanelIndex = self.PageControl.currentPage; 464 | self.CurrentPanelIndex = self.PageControl.currentPage; 465 | 466 | //Format and show new content 467 | [self setContentScrollViewHeightForPanelIndex:self.CurrentPanelIndex animated:YES]; 468 | [self makePanelVisibleAtIndex:(NSInteger)self.CurrentPanelIndex]; 469 | 470 | [self.ContentScrollView setContentOffset:CGPointMake(self.CurrentPanelIndex * 320, 0) animated:YES]; 471 | //Call Back, if applicable 472 | if (LastPanelIndex != self.CurrentPanelIndex) { //Keeps from making the callback when just bouncing and not actually changing pages 473 | if ([(id)delegate respondsToSelector:@selector(introductionDidChangeToPanel:withIndex:)]) { 474 | [delegate introductionDidChangeToPanel:Panels[self.CurrentPanelIndex] withIndex:self.CurrentPanelIndex]; 475 | } 476 | } 477 | } 478 | 479 | -(void)buildFooterView{ 480 | //Build Page Control 481 | if (self.device == 1) { 482 | self.PageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, (self.ContentScrollView.frame.origin.y + self.ContentScrollView.frame.size.height + PAGE_CONTROL_PADDING), self.frame.size.width, 36)]; 483 | } else { 484 | self.PageControl = [[UIPageControl alloc] initWithFrame:CGRectMake((self.frame.size.width - 185)/2, (self.ContentScrollView.frame.origin.y + self.ContentScrollView.frame.size.height + PAGE_CONTROL_PADDING), 185, 36)]; 485 | } 486 | [self.PageControl setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 487 | [self.PageControl addTarget:self action:@selector(showPanelAtPageControl) forControlEvents:UIControlEventValueChanged]; 488 | 489 | self.PageControl.numberOfPages = Panels.count; 490 | [self addSubview:self.PageControl]; 491 | 492 | 493 | //Build Skip Button 494 | if (LanguageDirection == MYLanguageDirectionRightToLeft) { 495 | self.SkipButton = [[UIButton alloc] initWithFrame:CGRectMake(0, self.PageControl.frame.origin.y, 80, self.PageControl.frame.size.height)]; 496 | self.PageControl.currentPage = panelViews.count - 1; 497 | } 498 | else { 499 | // self.SkipButton = [[UIButton alloc] initWithFrame:CGRectMake(self.ContentScrollView.frame.size.width - 80, self.PageControl.frame.origin.y, 80, self.PageControl.frame.size.height)]; 500 | self.SkipButton = [[UIButton alloc] initWithFrame:CGRectMake(self.ContentScrollView.frame.size.width - 80, self.PageControl.frame.origin.y, 80, self.PageControl.frame.size.height)]; 501 | } 502 | 503 | [self.SkipButton setAutoresizingMask: UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin]; 504 | [self.SkipButton setTitle:NSLocalizedString(@"Skip", nil) forState:UIControlStateNormal]; 505 | [self.SkipButton addTarget:self action:@selector(skipIntroduction) forControlEvents:UIControlEventTouchUpInside]; 506 | [self addSubview:self.SkipButton]; 507 | } 508 | 509 | -(void)setContentScrollViewHeightForPanelIndex:(NSInteger)panelIndex animated:(BOOL)animated{ 510 | CGFloat newPanelHeight = [panelViews[panelIndex] frame].size.height; 511 | 512 | if (animated){ 513 | [UIView animateWithDuration:0.3 animations:^{ 514 | self.ContentScrollView.frame = CGRectMake(self.ContentScrollView.frame.origin.x, self.ContentScrollView.frame.origin.y, self.ContentScrollView.frame.size.width, newPanelHeight); 515 | self.PageControl.frame = CGRectMake(self.PageControl.frame.origin.x, (self.ContentScrollView.frame.origin.y + self.ContentScrollView.frame.size.height + PAGE_CONTROL_PADDING), self.PageControl.frame.size.width, self.PageControl.frame.size.height); 516 | 517 | self.SkipButton.frame = CGRectMake(self.SkipButton.frame.origin.x, (self.ContentScrollView.frame.origin.y + self.ContentScrollView.frame.size.height + PAGE_CONTROL_PADDING), self.SkipButton.frame.size.width, self.SkipButton.frame.size.height); 518 | }]; 519 | } 520 | else { 521 | self.ContentScrollView.frame = CGRectMake(self.ContentScrollView.frame.origin.x, self.ContentScrollView.frame.origin.y, self.ContentScrollView.frame.size.width, newPanelHeight); 522 | 523 | self.PageControl.frame = CGRectMake(self.PageControl.frame.origin.x, (self.ContentScrollView.frame.origin.y + self.ContentScrollView.frame.size.height + PAGE_CONTROL_PADDING), self.PageControl.frame.size.width, self.PageControl.frame.size.height); 524 | self.SkipButton.frame = CGRectMake(self.SkipButton.frame.origin.x, (self.ContentScrollView.frame.origin.y + self.ContentScrollView.frame.size.height + PAGE_CONTROL_PADDING), self.SkipButton.frame.size.width, self.SkipButton.frame.size.height); 525 | 526 | } 527 | 528 | self.ContentScrollView.contentSize = CGSizeMake(self.ContentScrollView.contentSize.width, newPanelHeight); 529 | } 530 | 531 | #pragma mark - Header Content 532 | 533 | -(void)setHeaderText:(NSString *)headerText{ 534 | self.HeaderLabel.hidden = NO; 535 | self.HeaderImageView.hidden = YES; 536 | self.HeaderLabel.text = headerText; 537 | } 538 | 539 | -(void)setHeaderImage:(UIImage *)headerImage { 540 | self.HeaderLabel.hidden = YES; 541 | self.HeaderImageView.hidden = NO; 542 | self.HeaderImageView.image = headerImage; 543 | } 544 | 545 | #pragma mark - Introduction Content 546 | 547 | -(void)setBackgroundImage:(UIImage *)backgroundImage{ 548 | self.BackgroundImageView.image = backgroundImage; 549 | [self.BackgroundImageView setAutoresizingMask: UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth]; 550 | } 551 | 552 | -(void)setBackgroundColor:(UIColor *)backgroundColor { 553 | self.BackgroundImageView.backgroundColor = backgroundColor; 554 | [self.BackgroundImageView setAutoresizingMask: UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth]; 555 | } 556 | 557 | #pragma mark - Show/Hide 558 | 559 | -(void)showInView:(UIView *)view animateDuration:(CGFloat)duration{ 560 | //Add introduction view 561 | self.alpha = 0; 562 | [view addSubview:self]; 563 | 564 | //Fade in 565 | [UIView animateWithDuration:duration animations:^{ 566 | self.alpha = 1; 567 | }]; 568 | } 569 | 570 | -(void)hideWithFadeOutDuration:(CGFloat)duration{ 571 | //Fade out 572 | [UIView animateWithDuration:duration animations:^{ 573 | self.alpha = 0; 574 | } completion:nil]; 575 | } 576 | 577 | -(void)makePanelVisibleAtIndex:(NSInteger)panelIndex{ 578 | if (LanguageDirection == MYLanguageDirectionLeftToRight) { 579 | [UIView animateWithDuration:0.3 animations:^{ 580 | for (int ii = 0; ii < panelViews.count; ii++) { 581 | if (ii == panelIndex) { 582 | [panelViews[ii] setAlpha:1]; 583 | } 584 | else { 585 | [panelViews[ii] setAlpha:0]; 586 | } 587 | } 588 | }]; 589 | } 590 | else { 591 | [UIView animateWithDuration:0.3 animations:^{ 592 | for (int ii = panelViews.count-1; ii > 0; ii--) { 593 | if (ii == panelIndex) { 594 | [panelViews[ii] setAlpha:1]; 595 | } 596 | else { 597 | [panelViews[ii] setAlpha:0]; 598 | } 599 | } 600 | }]; 601 | } 602 | } 603 | 604 | -(void)skipIntroduction{ 605 | if ([(id)delegate respondsToSelector:@selector(introductionDidFinishWithType:)]) { 606 | [delegate introductionDidFinishWithType:MYFinishTypeSkipButton]; 607 | } 608 | 609 | [self hideWithFadeOutDuration:0.3]; 610 | } 611 | 612 | #pragma mark - UIScrollView Delegate 613 | 614 | -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ 615 | if (LanguageDirection == MYLanguageDirectionLeftToRight) { 616 | self.CurrentPanelIndex = scrollView.contentOffset.x/self.ContentScrollView.frame.size.width; 617 | 618 | //remove self if you are at the end of the introduction 619 | if (self.CurrentPanelIndex == (panelViews.count)) { 620 | if ([(id)delegate respondsToSelector:@selector(introductionDidFinishWithType:)]) { 621 | [delegate introductionDidFinishWithType:MYFinishTypeSwipeOut]; 622 | } 623 | } 624 | else { 625 | //Update Page Control 626 | LastPanelIndex = self.PageControl.currentPage; 627 | self.PageControl.currentPage = self.CurrentPanelIndex; 628 | 629 | //Format and show new content 630 | [self setContentScrollViewHeightForPanelIndex:self.CurrentPanelIndex animated:YES]; 631 | [self makePanelVisibleAtIndex:(NSInteger)self.CurrentPanelIndex]; 632 | 633 | //Call Back, if applicable 634 | if (LastPanelIndex != self.CurrentPanelIndex) { //Keeps from making the callback when just bouncing and not actually changing pages 635 | if ([(id)delegate respondsToSelector:@selector(introductionDidChangeToPanel:withIndex:)]) { 636 | [delegate introductionDidChangeToPanel:Panels[self.CurrentPanelIndex] withIndex:self.CurrentPanelIndex]; 637 | } 638 | } 639 | } 640 | } 641 | else if(LanguageDirection == MYLanguageDirectionRightToLeft){ 642 | self.CurrentPanelIndex = (scrollView.contentOffset.x-320)/self.ContentScrollView.frame.size.width; 643 | 644 | //remove self if you are at the end of the introduction 645 | if (self.CurrentPanelIndex == -1) { 646 | if ([(id)delegate respondsToSelector:@selector(introductionDidFinishWithType:)]) { 647 | [delegate introductionDidFinishWithType:MYFinishTypeSwipeOut]; 648 | } 649 | } 650 | else { 651 | //Update Page Control 652 | LastPanelIndex = self.PageControl.currentPage; 653 | self.PageControl.currentPage = self.CurrentPanelIndex; 654 | 655 | //Format and show new content 656 | [self setContentScrollViewHeightForPanelIndex:self.CurrentPanelIndex animated:YES]; 657 | [self makePanelVisibleAtIndex:(NSInteger)self.CurrentPanelIndex]; 658 | 659 | //Call Back, if applicable 660 | if (LastPanelIndex != self.CurrentPanelIndex) { //Keeps from making the callback when just bouncing and not actually changing pages 661 | if ([(id)delegate respondsToSelector:@selector(introductionDidChangeToPanel:withIndex:)]) { 662 | [delegate introductionDidChangeToPanel:Panels[self.CurrentPanelIndex] withIndex:self.CurrentPanelIndex]; 663 | } 664 | } 665 | } 666 | } 667 | } 668 | 669 | -(void)scrollViewDidScroll:(UIScrollView *)scrollView{ 670 | if (LanguageDirection == MYLanguageDirectionLeftToRight) { 671 | if (self.CurrentPanelIndex == (panelViews.count - 1)) { 672 | self.alpha = ((self.ContentScrollView.frame.size.width*panelViews.count)-self.ContentScrollView.contentOffset.x)/self.ContentScrollView.frame.size.width; 673 | } 674 | } 675 | else if (LanguageDirection == MYLanguageDirectionRightToLeft){ 676 | if (self.CurrentPanelIndex == 0) { 677 | self.alpha = self.ContentScrollView.contentOffset.x/self.ContentScrollView.frame.size.width; 678 | } 679 | } 680 | } 681 | 682 | #pragma mark - Support Methods 683 | 684 | +(BOOL)runningiOS7{ 685 | NSString *currSysVer = [[UIDevice currentDevice] systemVersion]; 686 | if (currSysVer.floatValue >= 7.0) { 687 | return YES; 688 | } 689 | 690 | return NO; 691 | } 692 | 693 | @end 694 | -------------------------------------------------------------------------------- /IntroductionExample/MYViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MYViewController.h 3 | // IntroductionExample 4 | // 5 | // Copyright (C) 2013, Matt York 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | // this software and associated documentation files (the "Software"), to deal in 9 | // the Software without restriction, including without limitation the rights to 10 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | // of the Software, and to permit persons to whom the Software is furnished to do 12 | // so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | // 25 | 26 | #import 27 | #import "MYIntroductionView.h" 28 | 29 | @interface MYViewController : UIViewController 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /IntroductionExample/MYViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MYViewController.m 3 | // IntroductionExample 4 | // 5 | // Copyright (C) 2013, Matt York 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | // this software and associated documentation files (the "Software"), to deal in 9 | // the Software without restriction, including without limitation the rights to 10 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | // of the Software, and to permit persons to whom the Software is furnished to do 12 | // so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | // 25 | 26 | #import "MYViewController.h" 27 | 28 | 29 | @interface MYViewController () 30 | 31 | @end 32 | 33 | @implementation MYViewController 34 | 35 | - (void)viewDidLoad 36 | { 37 | [super viewDidLoad]; 38 | // Do any additional setup after loading the view, typically from a nib. 39 | } 40 | 41 | -(void)viewDidAppear:(BOOL)animated{ 42 | 43 | //STEP 1 Construct Panels 44 | MYIntroductionPanel *panel = [[MYIntroductionPanel alloc] initWithimage:[UIImage imageNamed:@"SampleImage1"] title:@"Sample Title" description:@"Welcome to MYIntroductionView, your 100 percent customizable interface for introductions and tutorials! Simply add a few classes to your project, and you are ready to go!" ]; 45 | 46 | //You may also add in a title for each panel 47 | MYIntroductionPanel *panel2 = [[MYIntroductionPanel alloc] initWithimage:[UIImage imageNamed:@"SampleImage2"] title:@"Your Ticket!" description:@"MYIntroductionView is your ticket to a great tutorial or introduction!"]; 48 | 49 | //STEP 2 Create IntroductionView 50 | /*A standard version*/ 51 | //MYIntroductionView *introductionView = [[MYIntroductionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) headerImage:[UIImage imageNamed:@"SampleHeaderImage.png"] panels:@[panel, panel2]]; 52 | 53 | /*A version with no header (ala "Path")*/ 54 | // MYIntroductionView *introductionView = [[MYIntroductionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) panels:@[panel, panel2]]; 55 | 56 | /*A more customized version*/ 57 | MYIntroductionView *introductionView = [[MYIntroductionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) headerText:@"MYIntroductionView" panels:@[panel, panel2] languageDirection:MYLanguageDirectionLeftToRight]; 58 | [introductionView setBackgroundImage:[UIImage imageNamed:@"SampleBackground"]]; 59 | 60 | /* 61 | MYIntroductionView *introductionView = [[MYIntroductionView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height) headerText:@"MYIntroductionView" panels:@[panel, panel2] languageDirection:MYLanguageDirectionLeftToRight]; 62 | 63 | [introductionView setBackgroundColor:[UIColor colorWithRed:37.0/255 green:104.0/255 blue:154.0/255 alpha:1.0]]; */ 64 | 65 | [introductionView.BackgroundImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 66 | [introductionView.HeaderImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 67 | [introductionView.HeaderLabel setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 68 | [introductionView.HeaderView setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 69 | [introductionView.PageControl setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 70 | [introductionView.SkipButton setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 71 | 72 | 73 | 74 | 75 | //Set delegate to self for callbacks (optional) 76 | introductionView.delegate = self; 77 | 78 | //STEP 3: Show introduction view 79 | [introductionView showInView:self.view animateDuration:0.0]; 80 | } 81 | 82 | - (void)didReceiveMemoryWarning 83 | { 84 | [super didReceiveMemoryWarning]; 85 | // Dispose of any resources that can be recreated. 86 | } 87 | 88 | #pragma mark - Sample Delegate Methods 89 | 90 | -(void)introductionDidFinishWithType:(MYFinishType)finishType{ 91 | if (finishType == MYFinishTypeSkipButton) { 92 | NSLog(@"Did Finish Introduction By Skipping It"); 93 | } 94 | else if (finishType == MYFinishTypeSwipeOut){ 95 | NSLog(@"Did Finish Introduction By Swiping Out"); 96 | } 97 | 98 | //One might consider making the introductionview a class variable and releasing it here. 99 | // I didn't do this to keep things simple for the sake of example. 100 | } 101 | 102 | -(void)introductionDidChangeToPanel:(MYIntroductionPanel *)panel withIndex:(NSInteger)panelIndex{ 103 | NSLog(@"%@ \nPanelIndex: %d", panel.Description, panelIndex); 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /IntroductionExample/SampleBackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatthewYork/iPhone-IntroductionTutorial/4e44cf359bf654edf756047ee9da0f77d086ec2d/IntroductionExample/SampleBackground.png -------------------------------------------------------------------------------- /IntroductionExample/SampleHeaderImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatthewYork/iPhone-IntroductionTutorial/4e44cf359bf654edf756047ee9da0f77d086ec2d/IntroductionExample/SampleHeaderImage.png -------------------------------------------------------------------------------- /IntroductionExample/SampleImage1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatthewYork/iPhone-IntroductionTutorial/4e44cf359bf654edf756047ee9da0f77d086ec2d/IntroductionExample/SampleImage1.png -------------------------------------------------------------------------------- /IntroductionExample/SampleImage2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatthewYork/iPhone-IntroductionTutorial/4e44cf359bf654edf756047ee9da0f77d086ec2d/IntroductionExample/SampleImage2.png -------------------------------------------------------------------------------- /IntroductionExample/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /IntroductionExample/en.lproj/MYViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1552 5 | 12C3012 6 | 3084 7 | 1187.34 8 | 625.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 2083 12 | 13 | 14 | IBNSLayoutConstraint 15 | IBProxyObject 16 | IBUILabel 17 | IBUIView 18 | 19 | 20 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 21 | 22 | 23 | PluginDependencyRecalculationVersion 24 | 25 | 26 | 27 | 28 | IBFilesOwner 29 | IBCocoaTouchFramework 30 | 31 | 32 | IBFirstResponder 33 | IBCocoaTouchFramework 34 | 35 | 36 | 37 | 274 38 | 39 | 40 | 41 | 292 42 | {{20, 57}, {280, 21}} 43 | 44 | 45 | 46 | _NS:9 47 | NO 48 | YES 49 | 7 50 | NO 51 | IBCocoaTouchFramework 52 | Example Home Screen 53 | 54 | 1 55 | MCAwIDAAA 56 | darkTextColor 57 | 58 | 59 | 0 60 | 1 61 | 62 | 1 63 | 17 64 | 65 | 66 | Helvetica 67 | 17 68 | 16 69 | 70 | NO 71 | 72 | 73 | {{0, 20}, {320, 548}} 74 | 75 | 76 | 77 | 78 | 3 79 | MQA 80 | 81 | NO 82 | 83 | 84 | IBUIScreenMetrics 85 | 86 | YES 87 | 88 | 89 | 90 | 91 | 92 | {320, 568} 93 | {568, 320} 94 | 95 | 96 | IBCocoaTouchFramework 97 | Retina 4 Full Screen 98 | 2 99 | 100 | IBCocoaTouchFramework 101 | 102 | 103 | 104 | 105 | 106 | 107 | view 108 | 109 | 110 | 111 | 7 112 | 113 | 114 | 115 | 116 | 117 | 0 118 | 119 | 120 | 121 | 122 | 123 | -1 124 | 125 | 126 | File's Owner 127 | 128 | 129 | -2 130 | 131 | 132 | 133 | 134 | 6 135 | 136 | 137 | 138 | 139 | 140 | 5 141 | 0 142 | 143 | 5 144 | 1 145 | 146 | 20 147 | 148 | 1000 149 | 150 | 8 151 | 29 152 | 3 153 | 154 | 155 | 156 | 6 157 | 0 158 | 159 | 6 160 | 1 161 | 162 | 20 163 | 164 | 1000 165 | 166 | 8 167 | 29 168 | 3 169 | 170 | 171 | 172 | 3 173 | 0 174 | 175 | 3 176 | 1 177 | 178 | 57 179 | 180 | 1000 181 | 182 | 3 183 | 9 184 | 3 185 | 186 | 187 | 188 | 189 | 190 | 8 191 | 192 | 193 | 194 | 195 | 196 | 10 197 | 198 | 199 | 200 | 201 | 11 202 | 203 | 204 | 205 | 206 | 13 207 | 208 | 209 | 210 | 211 | 212 | 213 | MYViewController 214 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 215 | UIResponder 216 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 217 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 218 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 219 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 220 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 221 | 222 | 223 | 224 | 225 | 226 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 227 | 228 | 229 | 230 | 231 | 232 | 233 | 13 234 | 235 | 236 | 237 | 238 | MYViewController 239 | UIViewController 240 | 241 | IBProjectSource 242 | ./Classes/MYViewController.h 243 | 244 | 245 | 246 | NSLayoutConstraint 247 | NSObject 248 | 249 | IBProjectSource 250 | ./Classes/NSLayoutConstraint.h 251 | 252 | 253 | 254 | 255 | 0 256 | IBCocoaTouchFramework 257 | YES 258 | 3 259 | YES 260 | 2083 261 | 262 | 263 | -------------------------------------------------------------------------------- /IntroductionExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // IntroductionExample 4 | // 5 | // Created by Matthew York on 3/6/13. 6 | // Copyright (c) 2013 Matthew York. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "MYAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([MYAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 by Matthew York 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /MYIntroduction.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'MYIntroduction' 3 | s.version = '0.1.1' 4 | s.summary = 'Solution for building stylish app introductions and tutorials.' 5 | s.homepage = 'https://github.com/MatthewYork/iPhone-IntroductionTutorial' 6 | 7 | s.description = 'A "drop-in" solution for building stylish app introductions and tutorials. ' \ 8 | 'Now supports left-to-right and right-to-left languages.' 9 | 10 | s.license = { :type => 'MIT', :file => 'LICENSE' } 11 | s.author = { "Matthew York" => "my3681@gmail.com" } 12 | 13 | s.source = { :git => "https://github.com/MatthewYork/iPhone-IntroductionTutorial.git", 14 | :commit => "8eb9f93c4d0651d4c6d40feb0bc76dedda4af547" } 15 | 16 | s.platform = :ios, '5.0' 17 | s.requires_arc = true 18 | 19 | s.source_files = 'IntroductionExample/MYIntroduction{Panel,View}.{h,m}' 20 | s.frameworks = 'QuartzCore' 21 | end 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | iPhone Introduction / Tutorial (MYIntroductionView) 2 | ================================ 3 | 4 | ### IMPORTANT! 5 | ### MYIntroductionView has been replaced by [MYBlurIntroductionView](https://github.com/MatthewYork/MYBlurIntroductionView) 6 | 7 | 8 | ![BackgroundImage](http://imageshack.us/a/img856/8606/iossimulatorscreenshotm.png) 9 | ![BackgroundImage](https://raw.github.com/MatthewYork/iPhone-IntroductionTutorial/master/Resources/Images/IntercedeScreenshot.png) 10 | 11 | Everyone needs them and everyone hates writing them... Yes, it's the tutorial screen! I got sick of writing one for every app I made, so I went ahead and standardized it here. 12 | 13 | Features Include: 14 | - Left-to-Right and Right-to-Left language support 15 | - Delegate methods for handling current page and completion events 16 | - Easy UIView implementation that works with or without storyboards 17 | - **NEW** Ability to use custom views in a panel instead of just images 18 | 19 | CocoaPods 20 | ======================== 21 | If you use CocoaPods, you can install MYIntroduction by inserting config below. 22 | ``` 23 | pod 'MYIntroduction', :git => 'https://github.com/MatthewYork/iPhone-IntroductionTutorial.git' 24 | ``` 25 | 26 | Manual installation 27 | ======================== 28 | 29 | - Add the QuartzCore framework by clicking on your Project File -> Build Phases -> Lnk Binary With Libraries 30 | - Add `MYIntroductionView.h` and `MYIntroductionView.m` to your project. 31 | - Add `MYIntroductionPanel.h` and `MYIntroductionPanel.m` to your project. 32 | - `#import "MYIntroductionView.h"` to use it in a class 33 | - Subscribe to the 'MYIntroductionDelegate' to enable delegate/callback interaction. 34 | 35 | How To Use It 36 | ======================== 37 | 38 | Step 1 - Build Panels 39 | ------------------------ 40 | The introduction view needs something to display, and these are done via panels. Each panel holds an image and some description text. To create a panel, simply call the `initWithImage:description:` method. Two examples may be seen below; 41 | 42 | You may initialize a panel without a title 43 | ```objc 44 | MYIntroductionPanel *panel = [[MYIntroductionPanel alloc] initWithimage:[UIImage imageNamed:@"SampleImage1"] description:@"Welcome to MYIntroductionView, your 100 percent customizable interface for introductions and tutorials! Simply add a few classes to your project, and you are ready to go!"]; 45 | ``` 46 | 47 | Or with a title for extra information 48 | ```objc 49 | MYIntroductionPanel *panel2 = [[MYIntroductionPanel alloc] initWithimage:[UIImage imageNamed:@"SampleImage2"] title:@"Your Ticket!" description:@"MYIntroductionView is your ticket to a great tutorial or introduction!"]; 50 | ``` 51 | 52 | Step 2 - Create Introduction View 53 | ----------------------- 54 | Once you panels have been created, you are ready to create the introduction view. You will pass the panels you just created into this method where they will be rendered (in order) in the introduction view. An example can be found below. 55 | 56 | ```objc 57 | MYIntroductionView *introductionView = [[MYIntroductionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) headerImage:[UIImage imageNamed:@"SampleHeaderImage.png"] panels:@[panel, panel2]]; 58 | ``` 59 | Don't forget to set the delegate to the calling class if you are using delegation for any callbacks 60 | 61 | ```objc 62 | introductionView.delegate = self; 63 | ``` 64 | 65 | *A note to those using right-to-left languages: There is another init method that includes a language direction variable. It is an enum of type `MYLanguageDirection`. If you wish to use the right-to-left mode, this is where you would instruct the view to do so. 66 | 67 | Step 3 - Show Introduction View 68 | ----------------------- 69 | 70 | ```objc 71 | [introductionView showInView:self.view]; 72 | ``` 73 | -------------------------------------------------------------------------------- /Resources/Images/IntercedeScreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatthewYork/iPhone-IntroductionTutorial/4e44cf359bf654edf756047ee9da0f77d086ec2d/Resources/Images/IntercedeScreenshot.png --------------------------------------------------------------------------------