├── .gitignore ├── Demo ├── 11.华丽的TableView刷新动效 │ ├── TableViewRefreshAnimation.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── TableViewRefreshAnimation │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── TableViewAnimator.swift │ │ ├── UITableView+Extension.swift │ │ └── ViewController.swift ├── 35.使用系统自带气泡弹框 │ ├── PopoverView.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── PopoverView │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── ViewController.swift ├── 40.给UICollectionView的Cell添加左滑删除 │ ├── EditingCollectionView.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── EditingCollectionView │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ └── trash.imageset │ │ │ ├── Contents.json │ │ │ ├── trash-1.png │ │ │ ├── trash-2.png │ │ │ └── trash.png │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── EditingCollectionViewCell.swift │ │ ├── Info.plist │ │ ├── ItemCollectionViewCell.swift │ │ ├── UIView+Extensions.swift │ │ └── ViewController.swift ├── 44.自定义带动画效果的模态框 │ ├── CustomPresentation.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── CustomPresentation │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── CustomActionsheetController.swift │ │ ├── Info.plist │ │ ├── PresentationController.swift │ │ ├── ToastViewController.swift │ │ └── ViewController.swift ├── 47.给App的某个功能添加快捷方式 │ ├── AddHomeShortcuts.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── AddHomeShortcuts.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── AddHomeShortcuts │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ └── feature_icon.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── feature_icon.png │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── FeatureViewController.swift │ │ ├── HomeViewController.swift │ │ ├── Info.plist │ │ └── shortcuts.html │ ├── Podfile │ ├── Podfile.lock │ └── Pods │ │ ├── Manifest.lock │ │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ │ ├── Swifter │ │ ├── LICENSE │ │ ├── README.md │ │ └── Sources │ │ │ ├── DemoServer.swift │ │ │ ├── Errno.swift │ │ │ ├── Files.swift │ │ │ ├── HttpParser.swift │ │ │ ├── HttpRequest.swift │ │ │ ├── HttpResponse.swift │ │ │ ├── HttpRouter.swift │ │ │ ├── HttpServer.swift │ │ │ ├── HttpServerIO.swift │ │ │ ├── MimeTypes.swift │ │ │ ├── Process.swift │ │ │ ├── Scopes.swift │ │ │ ├── Socket+File.swift │ │ │ ├── Socket+Server.swift │ │ │ ├── Socket.swift │ │ │ ├── String+BASE64.swift │ │ │ ├── String+File.swift │ │ │ ├── String+Misc.swift │ │ │ ├── String+SHA1.swift │ │ │ └── WebSockets.swift │ │ └── Target Support Files │ │ ├── Pods-AddHomeShortcuts │ │ ├── Info.plist │ │ ├── Pods-AddHomeShortcuts-acknowledgements.markdown │ │ ├── Pods-AddHomeShortcuts-acknowledgements.plist │ │ ├── Pods-AddHomeShortcuts-dummy.m │ │ ├── Pods-AddHomeShortcuts-frameworks.sh │ │ ├── Pods-AddHomeShortcuts-resources.sh │ │ ├── Pods-AddHomeShortcuts-umbrella.h │ │ ├── Pods-AddHomeShortcuts.debug.xcconfig │ │ ├── Pods-AddHomeShortcuts.modulemap │ │ └── Pods-AddHomeShortcuts.release.xcconfig │ │ └── Swifter │ │ ├── Info.plist │ │ ├── Swifter-dummy.m │ │ ├── Swifter-prefix.pch │ │ ├── Swifter-umbrella.h │ │ ├── Swifter.modulemap │ │ └── Swifter.xcconfig ├── 49.线程保活的封装 │ ├── keepThreadAlive.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── keepThreadAlive │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── PermenantThread.swift │ │ ├── TestViewController.swift │ │ └── ViewController.swift ├── 50.GCD定时器 │ ├── GCDTimer.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── GCDTimer │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── GCD │ │ ├── GCDGroup.swift │ │ ├── GCDQueue.swift │ │ ├── GCDQueuePriority.swift │ │ ├── GCDSemaphore.swift │ │ └── GCDTimer.swift │ │ ├── Info.plist │ │ └── ViewController.swift ├── 55.使用协调器模式管理控制器 │ ├── CoordinateDemo.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── CoordinateDemo │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Auth │ │ ├── Auth.storyboard │ │ └── AuthViewController.swift │ │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ │ ├── Coordinate │ │ ├── AppCoordinator.swift │ │ ├── AuthCoordinator.swift │ │ ├── MessageCoordinator.swift │ │ └── UIStoryboard+Extensions.swift │ │ ├── Info.plist │ │ ├── Main │ │ ├── Main.storyboard │ │ └── MainViewController.swift │ │ └── Message │ │ ├── MessageDetailController.swift │ │ └── MessageViewController.swift ├── 58.恢复非正常终止的应用状态 │ ├── RestoreApp.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── RestoreApp │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── FirstViewController.swift │ │ ├── Info.plist │ │ ├── LastViewController.swift │ │ ├── NavController.swift │ │ └── SecondViewController.swift ├── 62.插件化TableView │ ├── PluginTableView.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── PluginTableView │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── chili.imageset │ │ │ ├── Contents.json │ │ │ └── chili.png │ │ ├── lemon.imageset │ │ │ ├── Contents.json │ │ │ └── lemon.png │ │ ├── mushroom.imageset │ │ │ ├── Contents.json │ │ │ └── mushroom.png │ │ ├── orange.imageset │ │ │ ├── Contents.json │ │ │ └── orange.png │ │ ├── radish.imageset │ │ │ ├── Contents.json │ │ │ └── radish.png │ │ └── watermelon.imageset │ │ │ ├── Contents.json │ │ │ └── watermelon.png │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── BaseController.swift │ │ ├── Cell │ │ ├── CodeableViewCell.swift │ │ ├── NibTableViewCell.swift │ │ └── NibTableViewCell.xib │ │ ├── FirstViewController.swift │ │ ├── Info.plist │ │ ├── Model │ │ └── CellModel.swift │ │ ├── PluginTableView │ │ ├── Configurator.swift │ │ ├── DataSource.swift │ │ ├── PluginTableView.swift │ │ └── Section.swift │ │ ├── SecondViewController.swift │ │ └── ThirdViewController.swift ├── 63.自定义底部弹层控制器 │ ├── PresentPartController.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── PresentPartController │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── PresentPartController.swift │ │ ├── SceneDelegate.swift │ │ └── ViewController.swift └── 9.使用面向协议实现app的主题功能 │ ├── DCTheme.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── DCTheme │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── one.imageset │ │ ├── Contents.json │ │ ├── one@2x.png │ │ └── one@3x.png │ └── two.imageset │ │ ├── Contents.json │ │ ├── two@2x.png │ │ └── two@3x.png │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Extensions │ ├── UIColor+Extension.swift │ ├── UITableViewCell+Extension.swift │ ├── UIView+Extension.swift │ └── UIWindow+Extension.swift │ ├── Info.plist │ ├── MainViewController.swift │ ├── Theme │ ├── BlueTheme.swift │ ├── DarkTheme.swift │ ├── LightTheme.swift │ └── Theme.swift │ └── View │ └── BackgroundView.swift ├── LICENSE ├── MyPlayground.playground ├── Pages │ ├── 1.常用的几个高阶函数.xcplaygroundpage │ │ └── Contents.swift │ ├── 13.实现多重代理.xcplaygroundpage │ │ └── Contents.swift │ ├── 2.高阶函数扩展.xcplaygroundpage │ │ └── Contents.swift │ ├── 3.优雅的判断多个值中是否包含某一个值.xcplaygroundpage │ │ └── Contents.swift │ ├── 4. Hashable、Equatable和Comparable协议.xcplaygroundpage │ │ └── Contents.swift │ ├── 5.可变参数函数.xcplaygroundpage │ │ └── Contents.swift │ └── 6.where关键字.xcplaygroundpage │ │ └── Contents.swift └── contents.xcplayground ├── README.md ├── Source ├── IBDesignableView.png ├── TableViewRefreshAnimation2.gif ├── addContainerView.png ├── addshortcuts.png ├── addshortcutsgif.gif ├── anchor_autoLayout.png ├── attributed_url.png ├── blink_scale_corner.gif ├── changeStatusBarStyle2.gif ├── color_wheel.png ├── custom_actionsheet.gif ├── embedTableViewController.png ├── namespace_module.png ├── padding.png ├── popOverView.gif ├── present_part_controller.gif ├── restoration_id.png ├── shadow_move.gif ├── showStyle.png ├── tabbarAnimating.gif ├── themeDemo.gif ├── toast_view.gif └── yellow_pixel.png ├── SwiftTipsDemo ├── DCTool │ ├── DCTool │ │ ├── DCTool.swift │ │ ├── EdgeInsetLabel.swift │ │ ├── LayoutProxy.swift │ │ ├── MutexLock.swift │ │ ├── Observable.swift │ │ ├── Regex.swift │ │ ├── Registerable.swift │ │ ├── StackViewControllerProtocol.swift │ │ └── ViewControllerInjector.swift │ └── Extension │ │ ├── Collection+Extension.swift │ │ ├── Date+Extension.swift │ │ ├── Dictionary+Extension.swift │ │ ├── NSObject+Extension.swift │ │ ├── Optional+Extension.swift │ │ ├── UIButton+Extension.swift │ │ ├── UIColor+Extension.swift │ │ ├── UITableView+Extension.swift │ │ ├── UIView+Extension.swift │ │ ├── UIViewController+Extension.swift │ │ └── UIWindow+Extension.swift ├── Podfile ├── Podfile.lock ├── Pods │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ ├── SwiftLint │ │ ├── LICENSE │ │ └── swiftlint │ └── Target Support Files │ │ └── Pods-SwiftTipsDemo │ │ ├── Info.plist │ │ ├── Pods-SwiftTipsDemo-acknowledgements.markdown │ │ ├── Pods-SwiftTipsDemo-acknowledgements.plist │ │ ├── Pods-SwiftTipsDemo-dummy.m │ │ ├── Pods-SwiftTipsDemo-frameworks.sh │ │ ├── Pods-SwiftTipsDemo-resources.sh │ │ ├── Pods-SwiftTipsDemo-umbrella.h │ │ ├── Pods-SwiftTipsDemo.debug.xcconfig │ │ ├── Pods-SwiftTipsDemo.modulemap │ │ └── Pods-SwiftTipsDemo.release.xcconfig ├── SwiftTipsDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── SwiftTipsDemo.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── SwiftTipsDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── DetailViewController.swift │ ├── Info.plist │ └── ViewController.swift └── XcodeTips ├── XcodeTips.md └── source ├── after_refactor_storyboard.png ├── breakpoint_view.png ├── control_distance.png ├── lock_control.png ├── more_layer.png ├── refactor_storyboard.png ├── rename.png ├── set_storyboard_reference.png └── storyboard_reference.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | .DS_Store 9 | 10 | ## Various settings 11 | *.pbxuser 12 | !default.pbxuser 13 | *.mode1v3 14 | !default.mode1v3 15 | *.mode2v3 16 | !default.mode2v3 17 | *.perspectivev3 18 | !default.perspectivev3 19 | xcuserdata/ 20 | 21 | ## Other 22 | *.moved-aside 23 | *.xccheckout 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | *.dSYM.zip 30 | *.dSYM 31 | 32 | ## Playgrounds 33 | timeline.xctimeline 34 | playground.xcworkspace 35 | 36 | # Swift Package Manager 37 | # 38 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 39 | # Packages/ 40 | # Package.pins 41 | # Package.resolved 42 | .build/ 43 | 44 | # CocoaPods 45 | # 46 | # We recommend against adding the Pods directory to your .gitignore. However 47 | # you should judge for yourself, the pros and cons are mentioned at: 48 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 49 | # 50 | # Pods/ 51 | 52 | # Carthage 53 | # 54 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 55 | # Carthage/Checkouts 56 | 57 | Carthage/Build 58 | 59 | # fastlane 60 | # 61 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 62 | # screenshots whenever they are needed. 63 | # For more information about the recommended setup visit: 64 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 65 | 66 | fastlane/report.xml 67 | fastlane/Preview.html 68 | fastlane/screenshots/**/*.png 69 | fastlane/test_output 70 | -------------------------------------------------------------------------------- /Demo/11.华丽的TableView刷新动效/TableViewRefreshAnimation.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/11.华丽的TableView刷新动效/TableViewRefreshAnimation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/11.华丽的TableView刷新动效/TableViewRefreshAnimation/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Demo/11.华丽的TableView刷新动效/TableViewRefreshAnimation/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/11.华丽的TableView刷新动效/TableViewRefreshAnimation/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demo/11.华丽的TableView刷新动效/TableViewRefreshAnimation/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Demo/11.华丽的TableView刷新动效/TableViewRefreshAnimation/UITableView+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UITableView+Extension.swift 3 | // TableViewRefreshAnimation 4 | // 5 | // Created by Dariel on 2018/10/12. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UITableView { 12 | func isLastVisibleCell(at indexPath: IndexPath) -> Bool { 13 | guard let lastIndexPath = indexPathsForVisibleRows?.last else { 14 | return false 15 | } 16 | return lastIndexPath == indexPath 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Demo/35.使用系统自带气泡弹框/PopoverView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/35.使用系统自带气泡弹框/PopoverView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/35.使用系统自带气泡弹框/PopoverView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Demo/35.使用系统自带气泡弹框/PopoverView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/35.使用系统自带气泡弹框/PopoverView/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demo/35.使用系统自带气泡弹框/PopoverView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Demo/35.使用系统自带气泡弹框/PopoverView/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // PopoverView 4 | // 5 | // Created by Dariel on 2018/12/10. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | } 16 | } 17 | 18 | extension ViewController: UIPopoverPresentationControllerDelegate { 19 | 20 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 21 | if segue.identifier == "popoverSegue" { 22 | let popoverViewController = segue.destination 23 | popoverViewController.popoverPresentationController!.delegate = self 24 | } 25 | } 26 | func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle { 27 | return .none 28 | } 29 | 30 | func popoverPresentationControllerDidDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) { 31 | setAlphaOfBackgroundViews(alpha: 1) 32 | } 33 | 34 | func prepareForPopoverPresentation(_ popoverPresentationController: UIPopoverPresentationController) { 35 | setAlphaOfBackgroundViews(alpha: 0.8) 36 | } 37 | 38 | func setAlphaOfBackgroundViews(alpha: CGFloat) { 39 | let statusBarWindow = UIApplication.shared.value(forKey: "statusBarWindow") as? UIWindow 40 | UIView.animate(withDuration: 0.2) { 41 | statusBarWindow?.alpha = alpha 42 | self.view.alpha = alpha 43 | self.navigationController?.navigationBar.alpha = alpha 44 | } 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // EditingCollectionView 4 | // 5 | // Created by Dariel on 2019/1/8. 6 | // Copyright © 2019年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | 19 | 20 | 21 | return true 22 | } 23 | 24 | func applicationWillResignActive(_ application: UIApplication) { 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | } 29 | 30 | func applicationWillEnterForeground(_ application: UIApplication) { 31 | } 32 | 33 | func applicationDidBecomeActive(_ application: UIApplication) { 34 | } 35 | 36 | func applicationWillTerminate(_ application: UIApplication) { 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/Assets.xcassets/trash.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "trash-2.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "trash-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "trash.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/Assets.xcassets/trash.imageset/trash-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/Assets.xcassets/trash.imageset/trash-1.png -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/Assets.xcassets/trash.imageset/trash-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/Assets.xcassets/trash.imageset/trash-2.png -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/Assets.xcassets/trash.imageset/trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/Assets.xcassets/trash.imageset/trash.png -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/ItemCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ItemCollectionViewCell.swift 3 | // EditingCollectionView 4 | // 5 | // Created by Dariel on 2019/1/8. 6 | // Copyright © 2019年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ItemCollectionViewCell: EditingCollectionViewCell { 12 | 13 | let itemNameLabel: UILabel = { 14 | let label = UILabel() 15 | label.font = UIFont.systemFont(ofSize: 20) 16 | label.textColor = UIColor(white: 0.2, alpha: 1) 17 | label.textAlignment = .center 18 | return label 19 | }() 20 | 21 | let deleteImageView: UIImageView = { 22 | let image = UIImage(named: "trash")?.withRenderingMode(.alwaysTemplate) 23 | let imageView = UIImageView(image: image) 24 | imageView.tintColor = .white 25 | return imageView 26 | }() 27 | 28 | override init(frame: CGRect) { 29 | super.init(frame: frame) 30 | setupSubviews() 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | fatalError("init(coder:) has not been implemented") 35 | } 36 | 37 | private func setupSubviews() { 38 | visibleContainerView.backgroundColor = .white 39 | visibleContainerView.addSubview(itemNameLabel) 40 | itemNameLabel.pinEdgesToSuperView() 41 | 42 | hiddenContainerView.backgroundColor = UIColor(red: 231.0 / 255.0, green: 76.0 / 255.0, blue: 60.0 / 255.0, alpha: 1) 43 | hiddenContainerView.addSubview(deleteImageView) 44 | deleteImageView.translatesAutoresizingMaskIntoConstraints = false 45 | deleteImageView.centerXAnchor.constraint(equalTo: hiddenContainerView.centerXAnchor).isActive = true 46 | deleteImageView.centerYAnchor.constraint(equalTo: hiddenContainerView.centerYAnchor).isActive = true 47 | deleteImageView.widthAnchor.constraint(equalToConstant: 25).isActive = true 48 | deleteImageView.heightAnchor.constraint(equalToConstant: 30).isActive = true 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Demo/40.给UICollectionView的Cell添加左滑删除/EditingCollectionView/UIView+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extensions.swift 3 | // EditingCollectionView 4 | // 5 | // Created by Dariel on 2019/1/8. 6 | // Copyright © 2019年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView { 12 | 13 | func pinEdgesToSuperView() { 14 | guard let superView = superview else { return } 15 | translatesAutoresizingMaskIntoConstraints = false 16 | topAnchor.constraint(equalTo: superView.topAnchor).isActive = true 17 | leftAnchor.constraint(equalTo: superView.leftAnchor).isActive = true 18 | bottomAnchor.constraint(equalTo: superView.bottomAnchor).isActive = true 19 | rightAnchor.constraint(equalTo: superView.rightAnchor).isActive = true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Demo/44.自定义带动画效果的模态框/CustomPresentation.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/44.自定义带动画效果的模态框/CustomPresentation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/44.自定义带动画效果的模态框/CustomPresentation/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Demo/44.自定义带动画效果的模态框/CustomPresentation/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/44.自定义带动画效果的模态框/CustomPresentation/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demo/44.自定义带动画效果的模态框/CustomPresentation/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Demo/44.自定义带动画效果的模态框/CustomPresentation/PresentationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PresentationController.swift 3 | // CustomPresentation 4 | // 5 | // Created by Dariel on 2019/2/19. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PresentationController: UIPresentationController { 12 | 13 | private var calculatedFrameOfPresentedViewInContainerView = CGRect.zero 14 | private var shouldSetFrameWhenAccessingPresentedView = false 15 | 16 | override var presentedView: UIView? { 17 | if shouldSetFrameWhenAccessingPresentedView { 18 | super.presentedView?.frame = calculatedFrameOfPresentedViewInContainerView 19 | } 20 | return super.presentedView 21 | } 22 | 23 | override func presentationTransitionDidEnd(_ completed: Bool) { 24 | super.presentationTransitionDidEnd(completed) 25 | shouldSetFrameWhenAccessingPresentedView = completed 26 | } 27 | 28 | override func dismissalTransitionWillBegin() { 29 | super.dismissalTransitionWillBegin() 30 | shouldSetFrameWhenAccessingPresentedView = false 31 | } 32 | 33 | override func containerViewDidLayoutSubviews() { 34 | super.containerViewDidLayoutSubviews() 35 | calculatedFrameOfPresentedViewInContainerView = frameOfPresentedViewInContainerView 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Demo/44.自定义带动画效果的模态框/CustomPresentation/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // CustomPresentation 4 | // 5 | // Created by Dariel on 2019/2/19. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | // alert actionSheet 17 | _ = UIAlertController(title: "", message: "", preferredStyle: .actionSheet) 18 | } 19 | 20 | @IBAction func addtoastViewAction(_ sender: Any) { 21 | 22 | presentToast(title: "这是一条从底部弹出来的Toast,当文本过长的话可以支持自动换行哦") 23 | } 24 | 25 | @IBAction func addActionSheetAction(_ sender: Any) { 26 | 27 | let viewController = CustomActionsheetController() 28 | present(viewController, animated: true, completion: nil) 29 | } 30 | 31 | private func presentToast(title: String) { 32 | let toast = ToastViewController(title: title) 33 | present(toast, animated: true) 34 | Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in 35 | toast.dismiss(animated: true) 36 | } 37 | } 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts/Assets.xcassets/feature_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "feature_icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts/Assets.xcassets/feature_icon.imageset/feature_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts/Assets.xcassets/feature_icon.imageset/feature_icon.png -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts/FeatureViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FeatureViewController.swift 3 | // AddHomeShortcuts 4 | // 5 | // Created by Dariel on 2019/3/12. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Swifter 11 | 12 | class FeatureViewController: UIViewController { 13 | lazy var server = HttpServer() 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | } 19 | @IBAction func addShortcutsTouch(_ sender: Any) { 20 | 21 | guard let deeplink = URL(string: "addshortcuts://profile") else { 22 | return 23 | } 24 | guard let shortcutUrl = URL(string: "http://localhost:8244/s") else { 25 | return 26 | } 27 | 28 | guard let iconData = UIImage(named: "feature_icon")?.jpegData(compressionQuality: 0.5) else { 29 | return 30 | } 31 | 32 | let html = htmlFor(title: "功能快捷方式", urlToRedirect: deeplink.absoluteString, icon: iconData.base64EncodedString()) 33 | 34 | guard let base64 = html.data(using: .utf8)?.base64EncodedString() else { 35 | return 36 | } 37 | server["/s"] = { request in 38 | return .movedPermanently("data:text/html;base64,\(base64)") 39 | } 40 | try? server.start(8244) 41 | UIApplication.shared.open(shortcutUrl) 42 | 43 | } 44 | 45 | func htmlFor(title: String, urlToRedirect: String, icon: String) -> String { 46 | let shortcutsPath = Bundle.main.path(forResource: "shortcuts", ofType: "html") 47 | 48 | var shortcutsContent = try! String(contentsOfFile: shortcutsPath!) as String 49 | shortcutsContent = shortcutsContent.replacingOccurrences(of: "\\(title)", with: title) 50 | shortcutsContent = shortcutsContent.replacingOccurrences(of: "\\(urlToRedirect.absoluteString)", with: urlToRedirect) 51 | shortcutsContent = shortcutsContent.replacingOccurrences(of: "\\(feature_icon)", with: icon) 52 | 53 | print(shortcutsContent) 54 | return shortcutsContent 55 | } 56 | 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts/HomeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // AddHomeShortcuts 4 | // 5 | // Created by Dariel on 2019/3/12. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class HomeViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | 17 | 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/AddHomeShortcuts/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleURLTypes 20 | 21 | 22 | CFBundleTypeRole 23 | Editor 24 | CFBundleURLSchemes 25 | 26 | addshortcuts 27 | 28 | 29 | 30 | CFBundleVersion 31 | 1 32 | LSRequiresIPhoneOS 33 | 34 | UILaunchStoryboardName 35 | LaunchScreen 36 | UIMainStoryboardFile 37 | Main 38 | UIRequiredDeviceCapabilities 39 | 40 | armv7 41 | 42 | UISupportedInterfaceOrientations 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | UISupportedInterfaceOrientations~ipad 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationPortraitUpsideDown 52 | UIInterfaceOrientationLandscapeLeft 53 | UIInterfaceOrientationLandscapeRight 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'AddHomeShortcuts' do 5 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | pod 'Swifter' 9 | 10 | # Pods for AddHomeShortcuts 11 | 12 | end 13 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Swifter (1.4.5) 3 | 4 | DEPENDENCIES: 5 | - Swifter 6 | 7 | SPEC REPOS: 8 | https://github.com/cocoapods/specs.git: 9 | - Swifter 10 | 11 | SPEC CHECKSUMS: 12 | Swifter: eb2bc1d192a1c09169c7fefd01971565fa940521 13 | 14 | PODFILE CHECKSUM: 181acaa524d3e7395c5a86ceca4de47c5e5bb0a8 15 | 16 | COCOAPODS: 1.5.3 17 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Swifter (1.4.5) 3 | 4 | DEPENDENCIES: 5 | - Swifter 6 | 7 | SPEC REPOS: 8 | https://github.com/cocoapods/specs.git: 9 | - Swifter 10 | 11 | SPEC CHECKSUMS: 12 | Swifter: eb2bc1d192a1c09169c7fefd01971565fa940521 13 | 14 | PODFILE CHECKSUM: 181acaa524d3e7395c5a86ceca4de47c5e5bb0a8 15 | 16 | COCOAPODS: 1.5.3 17 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Swifter/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Damian Kołakowski 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Swifter/Sources/Errno.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Errno.swift 3 | // Swifter 4 | // 5 | // Copyright © 2016 Damian Kołakowski. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | public class Errno { 11 | 12 | public class func description() -> String { 13 | return String(cString: UnsafePointer(strerror(errno))) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Swifter/Sources/Process.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Process 3 | // Swifter 4 | // 5 | // Copyright (c) 2014-2016 Damian Kołakowski. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | public class Process { 11 | 12 | public static var pid: Int { 13 | return Int(getpid()) 14 | } 15 | 16 | public static var tid: UInt64 { 17 | #if os(Linux) 18 | return UInt64(pthread_self()) 19 | #else 20 | var tid: __uint64_t = 0 21 | pthread_threadid_np(nil, &tid); 22 | return UInt64(tid) 23 | #endif 24 | } 25 | 26 | private static var signalsWatchers = Array<(Int32) -> Void>() 27 | private static var signalsObserved = false 28 | 29 | public static func watchSignals(_ callback: @escaping (Int32) -> Void) { 30 | if !signalsObserved { 31 | [SIGTERM, SIGHUP, SIGSTOP, SIGINT].forEach { item in 32 | signal(item) { 33 | signum in Process.signalsWatchers.forEach { $0(signum) } 34 | } 35 | } 36 | signalsObserved = true 37 | } 38 | signalsWatchers.append(callback) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Swifter/Sources/Socket+File.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Socket+File.swift 3 | // Swifter 4 | // 5 | // Created by Damian Kolakowski on 13/07/16. 6 | // 7 | 8 | import Foundation 9 | 10 | #if os(iOS) || os(tvOS) || os (Linux) 11 | struct sf_hdtr { } 12 | 13 | private func sendfileImpl(_ source: UnsafeMutablePointer, _ target: Int32, _: off_t, _: UnsafeMutablePointer, _: UnsafeMutablePointer, _: Int32) -> Int32 { 14 | var buffer = [UInt8](repeating: 0, count: 1024) 15 | while true { 16 | let readResult = fread(&buffer, 1, buffer.count, source) 17 | guard readResult > 0 else { 18 | return Int32(readResult) 19 | } 20 | var writeCounter = 0 21 | while writeCounter < readResult { 22 | #if os(Linux) 23 | let writeResult = send(target, &buffer + writeCounter, readResult - writeCounter, Int32(MSG_NOSIGNAL)) 24 | #else 25 | let writeResult = write(target, &buffer + writeCounter, readResult - writeCounter) 26 | #endif 27 | guard writeResult > 0 else { 28 | return Int32(writeResult) 29 | } 30 | writeCounter = writeCounter + writeResult 31 | } 32 | } 33 | } 34 | #endif 35 | 36 | extension Socket { 37 | 38 | public func writeFile(_ file: String.File) throws -> Void { 39 | var offset: off_t = 0 40 | var sf: sf_hdtr = sf_hdtr() 41 | 42 | #if os(iOS) || os(tvOS) || os (Linux) 43 | let result = sendfileImpl(file.pointer, self.socketFileDescriptor, 0, &offset, &sf, 0) 44 | #else 45 | let result = sendfile(fileno(file.pointer), self.socketFileDescriptor, 0, &offset, &sf, 0) 46 | #endif 47 | 48 | if result == -1 { 49 | throw SocketError.writeFailed("sendfile: " + Errno.description()) 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Swifter/Sources/String+BASE64.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+BASE64.swift 3 | // Swifter 4 | // 5 | // Copyright © 2016 Damian Kołakowski. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | 11 | extension String { 12 | 13 | private static let CODES = [UInt8]("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".utf8) 14 | 15 | public static func toBase64(_ data: [UInt8]) -> String? { 16 | 17 | // Based on: https://en.wikipedia.org/wiki/Base64#Sample_Implementation_in_Java 18 | 19 | var result = [UInt8]() 20 | var tmp: UInt8 21 | for index in stride(from: 0, to: data.count, by: 3) { 22 | let byte = data[index] 23 | tmp = (byte & 0xFC) >> 2; 24 | result.append(CODES[Int(tmp)]) 25 | tmp = (byte & 0x03) << 4; 26 | if index + 1 < data.count { 27 | tmp |= (data[index + 1] & 0xF0) >> 4; 28 | result.append(CODES[Int(tmp)]); 29 | tmp = (data[index + 1] & 0x0F) << 2; 30 | if (index + 2 < data.count) { 31 | tmp |= (data[index + 2] & 0xC0) >> 6; 32 | result.append(CODES[Int(tmp)]); 33 | tmp = data[index + 2] & 0x3F; 34 | result.append(CODES[Int(tmp)]); 35 | } else { 36 | result.append(CODES[Int(tmp)]); 37 | result.append(contentsOf: [UInt8]("=".utf8)); 38 | } 39 | } else { 40 | result.append(CODES[Int(tmp)]); 41 | result.append(contentsOf: [UInt8]("==".utf8)); 42 | } 43 | } 44 | return String(bytes: result, encoding: .utf8) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Swifter/Sources/String+Misc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+Misc.swift 3 | // Swifter 4 | // 5 | // Copyright (c) 2014-2016 Damian Kołakowski. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | 11 | extension String { 12 | 13 | public func unquote() -> String { 14 | var scalars = self.unicodeScalars; 15 | if scalars.first == "\"" && scalars.last == "\"" && scalars.count >= 2 { 16 | scalars.removeFirst(); 17 | scalars.removeLast(); 18 | return String(scalars) 19 | } 20 | return self 21 | } 22 | } 23 | 24 | extension UnicodeScalar { 25 | 26 | public func asWhitespace() -> UInt8? { 27 | if self.value >= 9 && self.value <= 13 { 28 | return UInt8(self.value) 29 | } 30 | if self.value == 32 { 31 | return UInt8(self.value) 32 | } 33 | return nil 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Pods-AddHomeShortcuts/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Pods-AddHomeShortcuts/Pods-AddHomeShortcuts-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Swifter 5 | 6 | Copyright (c) 2014, Damian Kołakowski 7 | All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | 12 | * Redistributions of source code must retain the above copyright notice, this 13 | list of conditions and the following disclaimer. 14 | 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | 19 | * Neither the name of the {organization} nor the names of its 20 | contributors may be used to endorse or promote products derived from 21 | this software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 27 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | Generated by CocoaPods - https://cocoapods.org 34 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Pods-AddHomeShortcuts/Pods-AddHomeShortcuts-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_AddHomeShortcuts : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_AddHomeShortcuts 5 | @end 6 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Pods-AddHomeShortcuts/Pods-AddHomeShortcuts-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_AddHomeShortcutsVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_AddHomeShortcutsVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Pods-AddHomeShortcuts/Pods-AddHomeShortcuts.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Swifter" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Swifter/Swifter.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "Swifter" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Pods-AddHomeShortcuts/Pods-AddHomeShortcuts.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_AddHomeShortcuts { 2 | umbrella header "Pods-AddHomeShortcuts-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Pods-AddHomeShortcuts/Pods-AddHomeShortcuts.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Swifter" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Swifter/Swifter.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "Swifter" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Swifter/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.4.5 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Swifter/Swifter-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Swifter : NSObject 3 | @end 4 | @implementation PodsDummy_Swifter 5 | @end 6 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Swifter/Swifter-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Swifter/Swifter-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double SwifterVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char SwifterVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Swifter/Swifter.modulemap: -------------------------------------------------------------------------------- 1 | framework module Swifter { 2 | umbrella header "Swifter-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/47.给App的某个功能添加快捷方式/Pods/Target Support Files/Swifter/Swifter.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Swifter 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Swifter 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Demo/49.线程保活的封装/keepThreadAlive.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/49.线程保活的封装/keepThreadAlive.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/49.线程保活的封装/keepThreadAlive/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Demo/49.线程保活的封装/keepThreadAlive/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/49.线程保活的封装/keepThreadAlive/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demo/49.线程保活的封装/keepThreadAlive/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Demo/49.线程保活的封装/keepThreadAlive/PermenantThread.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PermenantThread.swift 3 | // keepThreadAlive 4 | // 5 | // Created by Dariel on 2019/3/26. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DCThread: Thread { 12 | deinit { 13 | print("DCThread被销毁") 14 | } 15 | } 16 | 17 | class PermenantThread: NSObject { 18 | 19 | private var innerThread: DCThread? 20 | private var isStopped = false 21 | 22 | override init() { 23 | super.init() 24 | 25 | innerThread = DCThread(block: { [weak self] in 26 | 27 | RunLoop.current.add(Port(), forMode: RunLoop.Mode.default) 28 | while self?.isStopped == false { 29 | RunLoop.current.run(mode: RunLoop.Mode.default, before: NSDate.distantFuture) 30 | } 31 | }) 32 | 33 | innerThread?.name = "PermenantThread" 34 | innerThread?.start() 35 | } 36 | 37 | func executeTask(task: @escaping @convention(block)() -> Void) { 38 | 39 | guard let innerThread = innerThread else{ 40 | return 41 | } 42 | 43 | self.perform(#selector(innerExecuteTask(task:)), on: innerThread, with: task, waitUntilDone: false) 44 | } 45 | 46 | func stop() { 47 | 48 | guard let innerThread = innerThread else{ 49 | return 50 | } 51 | self.perform(#selector(innerStop), on: innerThread, with: nil, waitUntilDone: true) 52 | } 53 | 54 | @objc private func innerExecuteTask(task: @escaping @convention(block)() -> Void) { 55 | task() 56 | } 57 | 58 | @objc private func innerStop() { 59 | isStopped = true 60 | CFRunLoopStop(CFRunLoopGetCurrent()); 61 | self.innerThread = nil 62 | } 63 | 64 | deinit { 65 | stop() 66 | print("PermenantThread被销毁") 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Demo/49.线程保活的封装/keepThreadAlive/TestViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController.swift 3 | // keepThreadAlive 4 | // 5 | // Created by Dariel on 2019/3/26. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TestViewController: UIViewController { 12 | 13 | let thread = PermenantThread() 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | } 19 | 20 | @IBAction func excuteTaskTouch(_ sender: Any) { 21 | thread.executeTask { 22 | print(Thread.current) 23 | } 24 | } 25 | @IBAction func stopTaskTouch(_ sender: Any) { 26 | thread.stop() 27 | } 28 | 29 | deinit { 30 | print("TestViewController被销毁") 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Demo/49.线程保活的封装/keepThreadAlive/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // keepThreadAlive 4 | // 5 | // Created by Dariel on 2019/3/26. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /Demo/50.GCD定时器/GCDTimer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/50.GCD定时器/GCDTimer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/50.GCD定时器/GCDTimer/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Demo/50.GCD定时器/GCDTimer/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/50.GCD定时器/GCDTimer/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demo/50.GCD定时器/GCDTimer/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Demo/50.GCD定时器/GCDTimer/GCD/GCDGroup.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GCDGroup.swift 3 | // GCDTimer 4 | // 5 | // Created by Dariel on 2019/4/2. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class GCDGroup { 12 | 13 | public let dispatchGroup : DispatchGroup 14 | 15 | init() { 16 | 17 | self.dispatchGroup = DispatchGroup() 18 | } 19 | 20 | /// 在指定的queue里面获取消息 21 | /// 22 | /// - Parameters: 23 | /// - queue: 指定的queue 24 | /// - execute: 执行的block 25 | func notifyIn(_ queue : GCDQueue, execute: @escaping () -> Void) { 26 | 27 | self.dispatchGroup.notify(queue: queue.dispatchQueue, execute: execute) 28 | } 29 | 30 | /// 进入group 31 | func enter() { 32 | 33 | self.dispatchGroup.enter() 34 | } 35 | 36 | /// 从group出来 37 | func leave() { 38 | 39 | self.dispatchGroup.leave() 40 | } 41 | 42 | /// [阻塞操作] 无限等待 43 | func wait() { 44 | 45 | self.dispatchGroup.wait() 46 | } 47 | 48 | /// [阻塞操作] 等待指定的时间 49 | /// 50 | /// - Parameter seconds: 等待的时间,最多精确到1ms 51 | /// - Returns: DispatchTimeoutResult对象 52 | func waitForSeconds(seconds : Float) -> DispatchTimeoutResult { 53 | 54 | return self.dispatchGroup.wait(timeout: .now() + .milliseconds(Int(seconds * 1000))) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Demo/50.GCD定时器/GCDTimer/GCD/GCDSemaphore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GCDSemaphore.swift 3 | // GCDTimer 4 | // 5 | // Created by Dariel on 2019/4/2. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class GCDSemaphore { 12 | 13 | public let dispatchSemaphore : DispatchSemaphore 14 | 15 | init(initialSignal : Int = 0) { 16 | 17 | self.dispatchSemaphore = DispatchSemaphore(value: initialSignal) 18 | } 19 | 20 | // MARK: Singal 21 | 22 | /// 发信号 23 | func signal() { 24 | 25 | self.dispatchSemaphore.signal() 26 | } 27 | 28 | // MARK: Wait 29 | 30 | /// [阻塞操作] 无限等待 31 | func wait() { 32 | 33 | self.dispatchSemaphore.wait() 34 | } 35 | 36 | /// [阻塞操作] 等待指定的时间 37 | /// 38 | /// - Parameter seconds: 等待的时间,最多精确到1ms 39 | /// - Returns: DispatchTimeoutResult对象 40 | func waitForSeconds(_ seconds : Float) -> DispatchTimeoutResult { 41 | 42 | return self.dispatchSemaphore.wait(timeout: DispatchTime.now() + .milliseconds(Int(seconds * 1000))) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Demo/50.GCD定时器/GCDTimer/GCD/GCDTimer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GCDTimer.swift 3 | // GCDTimer 4 | // 5 | // Created by Dariel on 2019/4/2. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class GCDTimer { 12 | 13 | public let dispatchSourceTimer : DispatchSourceTimer 14 | 15 | init(in : GCDQueue, delay : Float = 0, interval : Float) { 16 | dispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: `in`.dispatchQueue) 17 | dispatchSourceTimer.schedule(deadline: .now() + .milliseconds(Int(delay * 1000)), repeating: .milliseconds(Int(interval * 1000))) 18 | } 19 | 20 | /// 设定定时器任务的回调函数 21 | /// 22 | /// - Parameter eventHandler: 回调函数 23 | func setTimerEventHandler(eventHandler: @escaping (GCDTimer) -> Void) { 24 | dispatchSourceTimer.setEventHandler { 25 | eventHandler(self) 26 | } 27 | } 28 | 29 | /// 设定定时器销毁时候的回调函数 30 | /// 31 | /// - Parameter eventHandler: 回调函数 32 | func setDestroyEventHandler(eventHandler: @escaping () -> Void) { 33 | 34 | dispatchSourceTimer.setCancelHandler { 35 | eventHandler() 36 | } 37 | } 38 | 39 | /// 挂起 40 | func suspend() { 41 | dispatchSourceTimer.suspend() 42 | } 43 | 44 | /// 开始定时 45 | func start() { 46 | dispatchSourceTimer.resume() 47 | } 48 | 49 | /// 定时器销毁(执行了此方法后,start就会变得无效) 50 | func destroy() { 51 | dispatchSourceTimer.cancel() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Demo/50.GCD定时器/GCDTimer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // CoordinateDemo 4 | // 5 | // Created by Dariel on 2019/5/29. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | var app: AppCoordinator? 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | 19 | let window = UIWindow(frame: UIScreen.main.bounds) 20 | let navController = UINavigationController() 21 | app = AppCoordinator(navController: navController, window: window) 22 | 23 | app?.start() 24 | 25 | return true 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/Auth/AuthViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthViewController.swift 3 | // CoordinateDemo 4 | // 5 | // Created by Dariel on 2019/5/29. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol AuthViewControllerDelegate: AnyObject { 12 | func signIn() 13 | } 14 | 15 | class AuthViewController: UIViewController { 16 | 17 | weak var delegate: AuthViewControllerDelegate? 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | 22 | } 23 | 24 | @IBAction func signInTouch(_ sender: Any) { 25 | delegate?.signIn() 26 | } 27 | 28 | deinit { 29 | print("AuthViewController销毁") 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/Coordinate/AppCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppCoordinator.swift 3 | // CoordinateDemo 4 | // 5 | // Created by Dariel on 2019/5/29. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol Coordinator { 12 | func start() 13 | } 14 | 15 | final class AppCoordinator: Coordinator { 16 | 17 | // MARK: - 属性 18 | private let navController: UINavigationController 19 | private let window: UIWindow 20 | private var childCoordinators: [Coordinator] = [] 21 | 22 | 23 | // MARK: - 构造方法 24 | init(navController: UINavigationController, window: UIWindow) { 25 | self.navController = navController 26 | self.window = window 27 | } 28 | 29 | 30 | func start() { 31 | window.rootViewController = navController 32 | window.makeKeyAndVisible() 33 | 34 | // showMain() 35 | showAuth() 36 | } 37 | 38 | // MARK: - 导航 39 | private func showMain() { 40 | let mainVc = UIStoryboard.instantiateMainViewController(delegate: self) 41 | navController.setViewControllers([mainVc], animated: true) 42 | 43 | // childCoordinators.removeAll() 44 | } 45 | 46 | private func showAuth() { 47 | let authCoordinator = AuthCoordinator(navController: navController, delegate: self) 48 | childCoordinators.append(authCoordinator) 49 | 50 | authCoordinator.start() 51 | } 52 | 53 | private func showMessage() { 54 | let messageCoordinator = MessageCoordinator(navController: navController) 55 | 56 | messageCoordinator.start() 57 | } 58 | 59 | } 60 | 61 | 62 | extension AppCoordinator: MainViewControllerDelegate { 63 | func toMessage() { 64 | showMessage() 65 | } 66 | 67 | func logout() { 68 | showAuth() 69 | } 70 | } 71 | 72 | extension AppCoordinator: AuthCoordinatorDelegate { 73 | func didAuthenticate() { 74 | showMain() 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/Coordinate/AuthCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthCoordinator.swift 3 | // CoordinateDemo 4 | // 5 | // Created by Dariel on 2019/5/29. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol AuthCoordinatorDelegate: AnyObject { 12 | func didAuthenticate() 13 | } 14 | 15 | // 用户授权模块的Coordinator 16 | final class AuthCoordinator: Coordinator { 17 | 18 | private let navController: UINavigationController 19 | weak var delegate: AuthCoordinatorDelegate? 20 | 21 | init(navController: UINavigationController, delegate: AuthCoordinatorDelegate) { 22 | self.navController = navController 23 | self.delegate = delegate 24 | } 25 | 26 | func start() { 27 | let authVc = UIStoryboard.instantiateAuthViewController(delegate: self) 28 | navController.setViewControllers([authVc], animated: true) 29 | } 30 | } 31 | 32 | extension AuthCoordinator: AuthViewControllerDelegate { 33 | func signIn() { 34 | delegate?.didAuthenticate() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/Coordinate/MessageCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MessageCoordinator.swift 3 | // CoordinateDemo 4 | // 5 | // Created by Dariel on 2019/5/29. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | final class MessageCoordinator: Coordinator { 12 | 13 | private let navController: UINavigationController 14 | 15 | init(navController: UINavigationController) { 16 | self.navController = navController 17 | } 18 | 19 | func start() { 20 | let messageVc = MessageViewController() 21 | messageVc.delegate = self 22 | navController.pushViewController(messageVc, animated: true) 23 | } 24 | 25 | private func toDetailMessageVc() { 26 | let messageDetailVc = MessageDetailController() 27 | navController.pushViewController(messageDetailVc, animated: true) 28 | } 29 | } 30 | 31 | 32 | extension MessageCoordinator: MessageViewControllerDelegate { 33 | func toDetailMessage() { 34 | toDetailMessageVc() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/Coordinate/UIStoryboard+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIStoryboard+Extension.swift 3 | // CoordinateDemo 4 | // 5 | // Created by Dariel on 2019/5/29. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIStoryboard { 12 | 13 | // MARK: - 获取对应的Storyboard 14 | private static var main: UIStoryboard { 15 | return UIStoryboard(name: "Main", bundle: nil) 16 | } 17 | 18 | private static var auth: UIStoryboard { 19 | return UIStoryboard(name: "Auth", bundle: nil) 20 | } 21 | 22 | // MARK: - Storyboard中控制器管理 23 | static func instantiateMainViewController(delegate: MainViewControllerDelegate) -> MainViewController { 24 | let mainVc = main.instantiateViewController(withIdentifier: "MainViewController") as! MainViewController 25 | mainVc.delegate = delegate 26 | return mainVc 27 | } 28 | 29 | static func instantiateAuthViewController(delegate: AuthViewControllerDelegate) -> AuthViewController { 30 | let authVc = auth.instantiateViewController(withIdentifier: "AuthViewController") as! AuthViewController 31 | authVc.delegate = delegate 32 | return authVc 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | 33 | UISupportedInterfaceOrientations~ipad 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationPortraitUpsideDown 37 | UIInterfaceOrientationLandscapeLeft 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/Main/MainViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // CoordinateDemo 4 | // 5 | // Created by Dariel on 2019/5/29. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol MainViewControllerDelegate: AnyObject { 12 | func logout() 13 | func toMessage() 14 | } 15 | 16 | class MainViewController: UIViewController { 17 | weak var delegate: MainViewControllerDelegate? 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | } 22 | 23 | @IBAction func logoutAction(_ sender: Any) { 24 | delegate?.logout() 25 | } 26 | 27 | @IBAction func messageTouch(_ sender: Any) { 28 | delegate?.toMessage() 29 | } 30 | 31 | deinit { 32 | print("MainViewController销毁") 33 | } 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/Message/MessageDetailController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MessageDetailController.swift 3 | // CoordinateDemo 4 | // 5 | // Created by Dariel on 2019/5/29. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MessageDetailController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | view.backgroundColor = UIColor.white 16 | 17 | let label = UILabel() 18 | label.text = "MessageDetailController" 19 | label.font = UIFont.systemFont(ofSize: 22) 20 | 21 | view.addSubview(label) 22 | 23 | label.sizeToFit() 24 | label.center = view.center 25 | } 26 | 27 | deinit { 28 | print("MessageDetailController销毁") 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Demo/55.使用协调器模式管理控制器/CoordinateDemo/Message/MessageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MessageViewController.swift 3 | // CoordinateDemo 4 | // 5 | // Created by Dariel on 2019/5/29. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol MessageViewControllerDelegate: AnyObject { 12 | func toDetailMessage() 13 | } 14 | 15 | class MessageViewController: UIViewController { 16 | var delegate: MessageViewControllerDelegate? 17 | 18 | override func viewDidLoad() { 19 | super.viewDidLoad() 20 | view.backgroundColor = UIColor.white 21 | 22 | let label = UILabel() 23 | label.text = "MessageViewController" 24 | label.font = UIFont.systemFont(ofSize: 22) 25 | 26 | view.addSubview(label) 27 | 28 | label.sizeToFit() 29 | label.center = view.center 30 | } 31 | 32 | override func touchesBegan(_ touches: Set, with event: UIEvent?) { 33 | delegate?.toDetailMessage() 34 | } 35 | 36 | deinit { 37 | print("MessageViewController销毁") 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Demo/58.恢复非正常终止的应用状态/RestoreApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/58.恢复非正常终止的应用状态/RestoreApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/58.恢复非正常终止的应用状态/RestoreApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // RestoreApp 4 | // 5 | // Created by Dariel on 2019/6/19. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func application(_ application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool { 23 | 24 | return true 25 | } 26 | 27 | func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool { 28 | 29 | return true 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /Demo/58.恢复非正常终止的应用状态/RestoreApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Demo/58.恢复非正常终止的应用状态/RestoreApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/58.恢复非正常终止的应用状态/RestoreApp/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demo/58.恢复非正常终止的应用状态/RestoreApp/FirstViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewController.swift 3 | // RestoreApp 4 | // 5 | // Created by Dariel on 2019/6/19. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FirstViewController: UIViewController { 12 | 13 | @IBOutlet weak var sliderView: UISlider! 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | 17 | restorationIdentifier = String(describing: type(of: self)) 18 | } 19 | 20 | 21 | } 22 | 23 | 24 | extension FirstViewController { 25 | 26 | override func encodeRestorableState(with coder: NSCoder) { 27 | super.encodeRestorableState(with: coder) 28 | 29 | guard let loadedSlider = sliderView, isViewLoaded else { 30 | return 31 | } 32 | coder.encode(loadedSlider.value, forKey: .encodingKeySliderValue) 33 | } 34 | 35 | override func decodeRestorableState(with coder: NSCoder) { 36 | super.decodeRestorableState(with: coder) 37 | assert(isViewLoaded, "We assume the controller is never restored without loading its view first.") 38 | sliderView?.value = coder.decodeFloat(forKey: .encodingKeySliderValue) 39 | } 40 | 41 | override func applicationFinishedRestoringState() { 42 | print("Finished restoring everything.") 43 | } 44 | } 45 | 46 | 47 | fileprivate extension String { 48 | static let encodingKeySliderValue = "encodingKeySliderValue" 49 | } 50 | 51 | -------------------------------------------------------------------------------- /Demo/58.恢复非正常终止的应用状态/RestoreApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Demo/58.恢复非正常终止的应用状态/RestoreApp/LastViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LastViewController.swift 3 | // RestoreApp 4 | // 5 | // Created by Dariel on 2019/6/19. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class LastViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | view.backgroundColor = UIColor.white 17 | navigationItem.title = "LastViewController" 18 | 19 | restorationIdentifier = "LastViewController" 20 | restorationClass = LastViewController.self 21 | 22 | } 23 | 24 | override func applicationFinishedRestoringState() { 25 | print("Finished restoring everything.") 26 | } 27 | } 28 | 29 | extension LastViewController: UIViewControllerRestoration { 30 | static func viewController(withRestorationIdentifierPath identifierComponents: [String], coder: NSCoder) -> UIViewController? { 31 | let vc = LastViewController() 32 | return vc 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Demo/58.恢复非正常终止的应用状态/RestoreApp/NavController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // RestoreApp 4 | // 5 | // Created by Dariel on 2019/6/19. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class NavController: UINavigationController { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Demo/58.恢复非正常终止的应用状态/RestoreApp/SecondViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.swift 3 | // RestoreApp 4 | // 5 | // Created by Dariel on 2019/6/19. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SecondViewController: UIViewController { 12 | 13 | @IBOutlet weak var inputField: UITextField! 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | } 18 | 19 | @IBAction func touch(_ sender: Any) { 20 | let vc = LastViewController() 21 | navigationController?.pushViewController(vc, animated: true) 22 | } 23 | } 24 | 25 | extension SecondViewController { 26 | 27 | override func encodeRestorableState(with coder: NSCoder) { 28 | super.encodeRestorableState(with: coder) 29 | 30 | guard let input = inputField.text, isViewLoaded else { 31 | return 32 | } 33 | coder.encode(input, forKey: .encodingKeyFieldValue) 34 | } 35 | 36 | override func decodeRestorableState(with coder: NSCoder) { 37 | super.decodeRestorableState(with: coder) 38 | assert(isViewLoaded, "We assume the controller is never restored without loading its view first.") 39 | inputField.text = coder.decodeObject(forKey: .encodingKeyFieldValue) as? String 40 | } 41 | 42 | override func applicationFinishedRestoringState() { 43 | print("Finished restoring everything.") 44 | } 45 | } 46 | 47 | 48 | fileprivate extension String { 49 | static let encodingKeyFieldValue = "encodingKeyFieldValue" 50 | } 51 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/chili.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "chili.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/chili.imageset/chili.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/62.插件化TableView/PluginTableView/Assets.xcassets/chili.imageset/chili.png -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/lemon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "lemon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/lemon.imageset/lemon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/62.插件化TableView/PluginTableView/Assets.xcassets/lemon.imageset/lemon.png -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/mushroom.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "mushroom.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/mushroom.imageset/mushroom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/62.插件化TableView/PluginTableView/Assets.xcassets/mushroom.imageset/mushroom.png -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/orange.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "orange.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/orange.imageset/orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/62.插件化TableView/PluginTableView/Assets.xcassets/orange.imageset/orange.png -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/radish.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "radish.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/radish.imageset/radish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/62.插件化TableView/PluginTableView/Assets.xcassets/radish.imageset/radish.png -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/watermelon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "watermelon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Assets.xcassets/watermelon.imageset/watermelon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/62.插件化TableView/PluginTableView/Assets.xcassets/watermelon.imageset/watermelon.png -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/BaseController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // PluginTableView 4 | // 5 | // Created by Dariel on 2019/8/6. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class BaseController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | setUpTableView() 17 | } 18 | 19 | func setUpTableView() { 20 | 21 | let section = Section(items: ["1.纯代码创建Cell", "2.Xib创建Cell", "3.不同类型cell分组"]) 22 | let dataSource = DataSource(sections: [section]) 23 | 24 | let configuartor = Configurator{ (cell, model: String, tableView, indexPath) -> UITableViewCell in 25 | cell.textLabel?.text = model 26 | return cell 27 | } 28 | 29 | let pluginTableView = PluginTableView(frame: view.bounds, style: .plain, dataSource: dataSource, configurator: configuartor) 30 | pluginTableView.tableView.tableFooterView = UIView() 31 | view.addSubview(pluginTableView) 32 | 33 | pluginTableView.didSelectRow = { [weak self] (tableView, indexPath) in 34 | 35 | switch indexPath.row { 36 | 37 | case 0: 38 | self?.navigationController?.pushViewController(FirstViewController(), animated: true) 39 | break 40 | case 1: 41 | self?.navigationController?.pushViewController(SecondViewController(), animated: true) 42 | break 43 | case 2: 44 | self?.navigationController?.pushViewController(ThirdViewController(), animated: true) 45 | break 46 | default: 47 | break 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Cell/CodeableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomTableViewCell.swift 3 | // PluginTableView 4 | // 5 | // Created by Dariel on 2019/8/7. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CodeTableViewCell: UITableViewCell { 12 | var iconLabel: UILabel 13 | var iconView: UIImageView 14 | 15 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 16 | 17 | iconLabel = UILabel() 18 | iconView = UIImageView() 19 | 20 | super.init(style: style, reuseIdentifier: reuseIdentifier) 21 | 22 | self.contentView.addSubview(iconLabel) 23 | self.contentView.addSubview(iconView) 24 | 25 | setUpViews() 26 | } 27 | 28 | @available(*, unavailable) 29 | required init?(coder aDecoder: NSCoder) { 30 | fatalError("init(coder:) has not been implemented") 31 | } 32 | 33 | private func setUpViews() { 34 | iconLabel.translatesAutoresizingMaskIntoConstraints = false 35 | iconView.translatesAutoresizingMaskIntoConstraints = false 36 | 37 | NSLayoutConstraint.activate([ 38 | 39 | iconView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 8), 40 | iconView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 8), 41 | iconView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -8), 42 | iconView.widthAnchor.constraint(equalTo: iconView.heightAnchor), 43 | 44 | iconLabel.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor), 45 | iconLabel.leadingAnchor.constraint(equalTo: iconView.trailingAnchor, constant: 16) 46 | ]) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Cell/NibTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NibTableViewCell.swift 3 | // PluginTableView 4 | // 5 | // Created by Dariel on 2019/8/7. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class NibTableViewCell: UITableViewCell { 12 | 13 | @IBOutlet weak var iconView: UIImageView! 14 | @IBOutlet weak var iconLabel: UILabel! 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/FirstViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewController.swift 3 | // PluginTableView 4 | // 5 | // Created by Dariel on 2019/8/7. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FirstViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | view.backgroundColor = .groupTableViewBackground 17 | setUpTableView() 18 | } 19 | 20 | func setUpTableView() { 21 | 22 | let section = Section(items: [ 23 | CNCellModel(name: "柠檬", imageStr: "lemon"), 24 | CNCellModel(name: "橙子", imageStr: "orange"), 25 | CNCellModel(name: "西瓜", imageStr: "watermelon") 26 | ]) 27 | let dataSource = DataSource(sections: [section]) 28 | 29 | let configuartor = Configurator { (cell, model: CNCellModel, tableView, indexPath) -> CodeTableViewCell in 30 | cell.iconLabel.text = model.name 31 | cell.iconView.image = UIImage(named: model.imageStr) 32 | return cell 33 | } 34 | 35 | let pluginTableView = PluginTableView(frame: view.bounds, style: .plain, dataSource: dataSource, configurator: configuartor) 36 | pluginTableView.tableView.tableFooterView = UIView() 37 | pluginTableView.tableView.rowHeight = 80 38 | view.addSubview(pluginTableView) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/Model/CellModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CellModel.swift 3 | // PluginTableView 4 | // 5 | // Created by Dariel on 2019/8/7. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct CNCellModel { 12 | var name: String 13 | var imageStr: String 14 | } 15 | 16 | struct ENCellModel { 17 | var name: String 18 | var imageStr: String 19 | } 20 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/PluginTableView/Configurator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Configurator.swift 3 | // PluginTableView 4 | // 5 | // Created by Dariel on 2019/8/7. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol ConfiguratorType { 12 | associatedtype Item 13 | associatedtype Cell: UITableViewCell 14 | 15 | func reuseIdentifier(for item: Item, indexPath: IndexPath) -> String 16 | func registerCells(in tableView: UITableView) 17 | func configure(cell: Cell, item: Item, tableView: UITableView, indexPath: IndexPath) -> Cell 18 | 19 | } 20 | extension ConfiguratorType { 21 | 22 | func configuredCell(for item: Item, tableView: UITableView, indexPath: IndexPath) -> Cell { 23 | let reuseIdentifier = self.reuseIdentifier(for: item, indexPath: indexPath) 24 | let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! Cell 25 | return self.configure(cell: cell, item: item, tableView: tableView, indexPath: indexPath) 26 | } 27 | } 28 | struct Configurator: ConfiguratorType { 29 | 30 | func configure(cell: Cell, item: Item, tableView: UITableView, indexPath: IndexPath) -> Cell { 31 | return configurator(cell, item, tableView, indexPath) 32 | } 33 | 34 | typealias CellConfigurator = (Cell, Item, UITableView, IndexPath) -> Cell 35 | 36 | let configurator: CellConfigurator 37 | let reuseIdentifier = "\(Cell.self)" 38 | 39 | func reuseIdentifier(for item: Item, indexPath: IndexPath) -> String { 40 | return reuseIdentifier 41 | } 42 | 43 | func registerCells(in tableView: UITableView) { 44 | if let path = Bundle.main.path(forResource: "\(Cell.self)", ofType: "nib"), 45 | FileManager.default.fileExists(atPath: path) { 46 | let nib = UINib(nibName: "\(Cell.self)", bundle: .main) 47 | tableView.register(nib, forCellReuseIdentifier: reuseIdentifier) 48 | } else { 49 | tableView.register(Cell.self, forCellReuseIdentifier: reuseIdentifier) 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/PluginTableView/DataSource.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataSource.swift 3 | // PluginTableView 4 | // 5 | // Created by Dariel on 2019/8/7. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct DataSource { 12 | var sections: [Section] 13 | 14 | func numberOfSections() -> Int { 15 | return sections.count 16 | } 17 | 18 | func numberOfItems(in section: Int) -> Int { 19 | guard section < sections.count else { return 0 } 20 | return sections[section].items.count 21 | } 22 | 23 | func item(at indexPath: IndexPath) -> Item { 24 | return sections[indexPath.section].items[indexPath.row] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/PluginTableView/PluginTableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PluginTableView.swift 3 | // PluginTableView 4 | // 5 | // Created by Dariel on 2019/8/7. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PluginTableView: UIView, UITableViewDataSource, UITableViewDelegate { 12 | 13 | var tableView: UITableView 14 | private let dataSource: DataSource 15 | private let configurator: Configurator 16 | 17 | var didSelectRow: ((UITableView, IndexPath) -> Void)? 18 | 19 | init(frame: CGRect, style: UITableView.Style, dataSource: DataSource, configurator: Configurator) { 20 | self.dataSource = dataSource 21 | self.configurator = configurator 22 | 23 | self.tableView = UITableView(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height), style: style) 24 | super.init(frame: frame) 25 | 26 | tableView.dataSource = self 27 | tableView.delegate = self 28 | self.addSubview(tableView) 29 | configurator.registerCells(in: tableView) 30 | } 31 | 32 | @available(*, unavailable) 33 | required init?(coder aDecoder: NSCoder) { 34 | fatalError("init(coder:) has not been implemented") 35 | } 36 | 37 | 38 | // MARK: - 数据源 39 | func numberOfSections(in tableView: UITableView) -> Int { 40 | return dataSource.numberOfSections() 41 | } 42 | 43 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 44 | return dataSource.numberOfItems(in: section) 45 | } 46 | 47 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 48 | let item = dataSource.item(at: indexPath) 49 | return configurator.configuredCell(for: item, tableView: tableView, indexPath: indexPath) 50 | } 51 | 52 | // MARK: - 代理 53 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 54 | didSelectRow?(tableView, indexPath) 55 | } 56 | 57 | // ... 58 | 59 | } 60 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/PluginTableView/Section.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Section.swift 3 | // PluginTableView 4 | // 5 | // Created by Dariel on 2019/8/7. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Section { 12 | var items: [Item] 13 | } 14 | -------------------------------------------------------------------------------- /Demo/62.插件化TableView/PluginTableView/SecondViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.swift 3 | // PluginTableView 4 | // 5 | // Created by Dariel on 2019/8/7. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SecondViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | view.backgroundColor = .groupTableViewBackground 17 | setUpTableView() 18 | } 19 | 20 | func setUpTableView() { 21 | 22 | let section = Section(items: [ 23 | ENCellModel(name: "chili", imageStr: "chili"), 24 | ENCellModel(name: "mushroom", imageStr: "mushroom"), 25 | ENCellModel(name: "radish", imageStr: "radish") 26 | ]) 27 | let dataSource = DataSource(sections: [section]) 28 | 29 | let configuartor = Configurator{ (cell, model: ENCellModel, tableView, indexPath) -> NibTableViewCell in 30 | cell.iconLabel.text = model.name 31 | cell.iconView.image = UIImage(named: model.imageStr) 32 | return cell 33 | } 34 | 35 | let pluginTableView = PluginTableView(frame: view.bounds, style: .plain, dataSource: dataSource, configurator: configuartor) 36 | pluginTableView.tableView.tableFooterView = UIView() 37 | pluginTableView.tableView.rowHeight = 80 38 | view.addSubview(pluginTableView) 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Demo/63.自定义底部弹层控制器/PresentPartController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/63.自定义底部弹层控制器/PresentPartController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/63.自定义底部弹层控制器/PresentPartController/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PresentPartController 4 | // 5 | // Created by Dariel on 2020/4/8. 6 | // Copyright © 2020 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Demo/63.自定义底部弹层控制器/PresentPartController/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Demo/63.自定义底部弹层控制器/PresentPartController/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/63.自定义底部弹层控制器/PresentPartController/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demo/63.自定义底部弹层控制器/PresentPartController/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // PresentPartController 4 | // 5 | // Created by Dariel on 2020/4/8. 6 | // Copyright © 2020 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | } 16 | @IBAction func btnTouch(_ sender: Any) { 17 | present(PresentPartController(), animated: true, completion: nil) 18 | 19 | } 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // DCTheme 4 | // 5 | // Created by Dariel on 2018/10/9. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | 19 | return true 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | public protocol With {} 28 | 29 | public extension With where Self: Any { 30 | 31 | /// 初始化之后通过闭包设置属性 32 | /// 33 | /// let label = UILabel().with { 34 | /// $0.textAlignment = .center 35 | /// $0.textColor = UIColor.black 36 | /// $0.text = "Hello, World!" 37 | /// } 38 | @discardableResult 39 | func with(_ block: (Self) -> Void) -> Self { 40 | // https://github.com/devxoul/Then 41 | block(self) 42 | return self 43 | } 44 | } 45 | extension NSObject: With {} 46 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Assets.xcassets/one.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "one@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "one@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Assets.xcassets/one.imageset/one@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/9.使用面向协议实现app的主题功能/DCTheme/Assets.xcassets/one.imageset/one@2x.png -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Assets.xcassets/one.imageset/one@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/9.使用面向协议实现app的主题功能/DCTheme/Assets.xcassets/one.imageset/one@3x.png -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Assets.xcassets/two.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "two@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "two@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Assets.xcassets/two.imageset/two@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/9.使用面向协议实现app的主题功能/DCTheme/Assets.xcassets/two.imageset/two@2x.png -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Assets.xcassets/two.imageset/two@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Demo/9.使用面向协议实现app的主题功能/DCTheme/Assets.xcassets/two.imageset/two@3x.png -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Extensions/UIColor+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Extension.swift 3 | // DCTheme 4 | // 5 | // Created by Dariel on 2018/10/10. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIColor { 12 | public class var darkNight: UIColor { 13 | return UIColor(2, 21, 40) 14 | } 15 | public class var dayBlue: UIColor { 16 | return UIColor(43, 89, 185) 17 | } 18 | public class var darkText: UIColor { 19 | return UIColor(75, 79, 103) 20 | } 21 | public class var lightText: UIColor { 22 | return UIColor(83, 115, 169) 23 | } 24 | public class var selectdLightBlue: UIColor { 25 | return UIColor(153, 189, 223) 26 | } 27 | public convenience init(_ r: CGFloat, _ g: CGFloat, _ b: CGFloat, _ a: CGFloat = 1) { 28 | self.init(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: a) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Extensions/UITableViewCell+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UITableViewCell+Extension.swift 3 | // DCTheme 4 | // 5 | // Created by Dariel on 2018/10/10. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UITableViewCell { 12 | /// cell选中时的颜色 13 | @objc dynamic var selectedColor: UIColor? { 14 | get { return selectedBackgroundView?.backgroundColor } 15 | set { 16 | guard selectionStyle != .none else { return } 17 | selectedBackgroundView = UIView().with { 18 | $0.backgroundColor = newValue 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Extensions/UIView+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extension.swift 3 | // DCTheme 4 | // 5 | // Created by Dariel on 2018/10/10. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView { 12 | /// 边框颜色 13 | @IBInspectable var borderColor: UIColor? { 14 | get { 15 | guard let color = layer.borderColor else { return nil } 16 | return UIColor(cgColor: color) 17 | } 18 | 19 | set { 20 | guard let color = newValue else { 21 | layer.borderColor = nil 22 | return 23 | } 24 | 25 | layer.borderColor = color.cgColor 26 | } 27 | } 28 | /// 边框宽度 29 | @IBInspectable var borderWidth: CGFloat { 30 | get { return layer.borderWidth } 31 | set { layer.borderWidth = newValue } 32 | } 33 | /// 圆角半径 34 | @IBInspectable var cornerRadius: CGFloat { 35 | get { return layer.cornerRadius } 36 | 37 | set { 38 | layer.masksToBounds = true 39 | layer.cornerRadius = newValue 40 | } 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Extensions/UIWindow+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIWindow+Extension.swift 3 | // DCTheme 4 | // 5 | // Created by Dariel on 2018/10/10. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIWindow { 12 | /// 刷新所有子控件 13 | func reload() { 14 | subviews.forEach { view in 15 | view.removeFromSuperview() 16 | addSubview(view) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/MainViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // DCTheme 4 | // 5 | // Created by Dariel on 2018/10/9. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MainViewController: UIViewController { 12 | @IBOutlet weak var segmentedControl: UISegmentedControl! 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | 17 | segmentedControl.selectedSegmentIndex = 0 18 | LightTheme().apply(for: UIApplication.shared) 19 | } 20 | 21 | @IBAction func themeSegmentedControlChanged(_ sender: UISegmentedControl) { 22 | 23 | let theme: Theme 24 | switch sender.selectedSegmentIndex { 25 | case 0: theme = LightTheme() 26 | case 1: theme = BlueTheme() 27 | default: theme = DarkTheme() 28 | } 29 | theme.apply(for: UIApplication.shared) 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Theme/BlueTheme.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BlueTheme.swift 3 | // DCTheme 4 | // 5 | // Created by Dariel on 2018/10/9. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | struct BlueTheme: Theme { 12 | 13 | let tint: UIColor = UIColor.dayBlue 14 | let barStyle: UIBarStyle = .black 15 | 16 | let labelColor: UIColor = UIColor(32, 42, 46) 17 | let labelSelectedColor: UIColor = UIColor.white 18 | 19 | let backgroundColor: UIColor = UIColor(219, 242, 255) 20 | let separatorColor: UIColor = UIColor(210, 234, 250) 21 | let selectedColor: UIColor = UIColor.selectdLightBlue 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Theme/DarkTheme.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DarkTheme.swift 3 | // DCTheme 4 | // 5 | // Created by Dariel on 2018/10/9. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | struct DarkTheme: Theme { 12 | 13 | let tint: UIColor = UIColor.darkNight 14 | let barStyle: UIBarStyle = .black 15 | 16 | let labelColor: UIColor = UIColor.lightText 17 | let labelSelectedColor: UIColor = .white 18 | 19 | let backgroundColor: UIColor = UIColor(23, 35, 61) 20 | let separatorColor: UIColor = UIColor(12, 23, 45) 21 | let selectedColor: UIColor = UIColor(22, 37, 66) 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/Theme/LightTheme.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LightTheme.swift 3 | // DCTheme 4 | // 5 | // Created by Dariel on 2018/10/9. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | struct LightTheme: Theme { 12 | 13 | let tint: UIColor = .white 14 | let barStyle: UIBarStyle = .default 15 | 16 | let labelColor: UIColor = UIColor.darkText 17 | let labelSelectedColor: UIColor = UIColor.lightText 18 | 19 | let backgroundColor: UIColor = .white 20 | let separatorColor: UIColor = .lightGray 21 | let selectedColor: UIColor = UIColor(236, 236, 236) 22 | 23 | } 24 | 25 | extension LightTheme { 26 | 27 | // 需要自定义的部分写在这边 28 | func extend() { 29 | 30 | UISegmentedControl.appearance().with { 31 | $0.tintColor = UIColor.darkText 32 | $0.setTitleTextAttributes([.foregroundColor : labelColor], for: .normal) 33 | $0.setTitleTextAttributes([.foregroundColor : UIColor.white], for: .selected) 34 | } 35 | 36 | UISlider.appearance().tintColor = UIColor.darkText 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Demo/9.使用面向协议实现app的主题功能/DCTheme/View/BackgroundView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BackgroundView.swift 3 | // DCTheme 4 | // 5 | // Created by Dariel on 2018/10/10. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class BackgroundView: UIView { 12 | } 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Dariel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MyPlayground.playground/Pages/1.常用的几个高阶函数.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | let intArr = [13, 45, 27, 80, 22, 53] 6 | 7 | let sortOneArr = intArr.sorted { (a: Int, b: Int) -> Bool in 8 | return a < b 9 | } 10 | sortOneArr 11 | 12 | let sortTwoArr = intArr.sorted { (a: Int, b: Int) in 13 | return a < b 14 | } 15 | sortTwoArr 16 | 17 | let sortThreeArr = intArr.sorted { (a, b) in 18 | return a < b 19 | } 20 | sortThreeArr 21 | 22 | let sortFourArr = intArr.sorted { 23 | return $0 < $1 24 | } 25 | sortFourArr 26 | 27 | let sortFiveArr = intArr.sorted { 28 | $0 < $1 29 | } 30 | sortFiveArr 31 | 32 | let sortSixArr = intArr.sorted(by: <) 33 | sortSixArr 34 | 35 | 36 | let mapArr = intArr.map { $0 * $0 } 37 | mapArr 38 | 39 | let optionalArr = [nil, 4, 12, 7, Optional(3), 9] 40 | let compactMapArr = optionalArr.compactMap { $0 } 41 | compactMapArr 42 | 43 | let evenArr = intArr.filter { $0 % 2 == 0 } 44 | evenArr 45 | 46 | let stringArr = ["1", "2", "3", "*", "a"] 47 | let allStr = stringArr.reduce("") { $0 + $1 } 48 | allStr 49 | 50 | 51 | let chainArr = [4, 3, 5, 8, 6, 2, 4, 7] 52 | let resultArr = chainArr.filter { 53 | $0 % 2 == 0 54 | }.map { 55 | $0 * $0 56 | }.reduce(0) { 57 | $0 + $1 58 | } 59 | resultArr 60 | -------------------------------------------------------------------------------- /MyPlayground.playground/Pages/2.高阶函数扩展.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class Pet { 4 | let type: String 5 | let age: Int 6 | 7 | init(type: String, age: Int) { 8 | self.type = type 9 | self.age = age 10 | } 11 | } 12 | 13 | var pets = [ 14 | Pet(type: "dog", age: 5), 15 | Pet(type: "cat", age: 3), 16 | Pet(type: "sheep", age: 1), 17 | Pet(type: "pig", age: 2), 18 | Pet(type: "cat", age: 3), 19 | ] 20 | 21 | pets.forEach { p in 22 | print(p.type) 23 | } 24 | 25 | let cc = pets.contains { $0.type == "cat" } 26 | cc 27 | 28 | let firstIndex = pets.firstIndex { $0.age == 3 } 29 | firstIndex 30 | 31 | let lastIndex = pets.lastIndex { $0.age == 3 } 32 | lastIndex 33 | 34 | let sortArr = pets.sorted { $0.age < $1.age } 35 | sortArr 36 | 37 | let arr1 = pets.prefix { $0.age > 3 } 38 | arr1 39 | 40 | let arr2 = pets.drop { $0.age > 3 } 41 | arr2 42 | 43 | 44 | let line = "BLANCHE: I don't want realism. I want magic!" 45 | 46 | let wordArr = line.split(whereSeparator: { $0 == " " }) 47 | wordArr 48 | -------------------------------------------------------------------------------- /MyPlayground.playground/Pages/3.优雅的判断多个值中是否包含某一个值.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | let string = "One" 6 | 7 | // 方案1 8 | if string == "One" || string == "Two" || string == "Three" { 9 | print("One") 10 | } 11 | 12 | // 方案2 13 | if ["One", "Two", "Three"].contains(where: { $0 == "One"}) { 14 | print("One") 15 | } 16 | 17 | 18 | // 方案3 19 | func any(of values: T...) -> EquatableValueSequence { 20 | return EquatableValueSequence(values: values) 21 | } 22 | 23 | struct EquatableValueSequence { 24 | static func ==(lhs: EquatableValueSequence, rhs: T) -> Bool { 25 | return lhs.values.contains(rhs) 26 | } 27 | 28 | static func ==(lhs: T, rhs: EquatableValueSequence) -> Bool { 29 | return rhs == lhs 30 | } 31 | 32 | fileprivate let values: [T] 33 | } 34 | 35 | if string == any(of: "One", "Two", "Three") { 36 | print("One") 37 | } 38 | -------------------------------------------------------------------------------- /MyPlayground.playground/Pages/4. Hashable、Equatable和Comparable协议.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | struct Pet: Equatable { 6 | let name: String 7 | let age: Int 8 | } 9 | 10 | 11 | let p1 = Pet(name: "Cat", age: 2) 12 | let p2 = Pet(name: "Dog", age: 3) 13 | 14 | p1 == p2 15 | 16 | 17 | enum Season: Equatable { 18 | case spring(mouth: String) 19 | case summer 20 | case autumn(mouth: String) 21 | case winter 22 | } 23 | 24 | let season1 = Season.spring(mouth: "4") 25 | let season2 = Season.autumn(mouth: "4") 26 | 27 | season1 == season2 28 | 29 | 30 | class Animal: Equatable, Hashable, Comparable { 31 | 32 | static func < (lhs: Animal, rhs: Animal) -> Bool { 33 | if lhs.age < rhs.age{ 34 | return true 35 | }else { 36 | return false 37 | } 38 | } 39 | 40 | static func == (lhs: Animal, rhs: Animal) -> Bool { 41 | if lhs.type == rhs.type && lhs.age == rhs.age{ 42 | return true 43 | }else { 44 | return false 45 | } 46 | } 47 | 48 | var hashValue: Int { 49 | return self.type.hashValue ^ self.age.hashValue 50 | 51 | } 52 | 53 | let type: String 54 | let age: Int 55 | 56 | init(type: String, age: Int) { 57 | self.type = type 58 | self.age = age 59 | } 60 | } 61 | 62 | 63 | let a1 = Animal(type: "Cat", age: 3) 64 | let a2 = Animal(type: "Cat", age: 4) 65 | let a3 = Animal(type: "Cat", age: 1) 66 | let a4 = Animal(type: "Cat", age: 6) 67 | 68 | 69 | a1 == a2 70 | 71 | a1.hashValue 72 | a2.hashValue 73 | 74 | 75 | let animals = [a1, a2, a3, a4] 76 | 77 | 78 | let b = a1 < a2 79 | let sortedAnimals = animals.sorted(by: <) 80 | sortedAnimals 81 | -------------------------------------------------------------------------------- /MyPlayground.playground/Pages/5.可变参数函数.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | 6 | /// 求和 7 | // 常用的姿势 8 | let sum2 = [2, 3, 4, 5, 6, 7, 8, 9].reduce(0) { $0 + $1 } 9 | sum2 10 | 11 | // 使用可变参数函数 12 | sum(values: 2, 3, 4, 5, 6, 7, 8, 9) 13 | 14 | // 可变参数的类型是个数组 15 | func sum(values:Int...) -> Int { 16 | var result = 0 17 | values.forEach({ a in 18 | result += a 19 | }) 20 | return result 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /MyPlayground.playground/Pages/6.where关键字.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // for循环的时候添加限定条件 6 | let arr = [11, 12, 13, 14, 15, 16, 17, 18] 7 | for num in arr where num % 2 == 0 { 8 | // 12 14 16 18 9 | num 10 | } 11 | 12 | 13 | // 在try catch的时候做条件判断 14 | enum ExceptionError:Error{ 15 | case httpCode(Int) 16 | } 17 | 18 | func throwError() throws { 19 | throw ExceptionError.httpCode(500) 20 | } 21 | 22 | do{ 23 | try throwError() 24 | }catch ExceptionError.httpCode(let httpCode) where httpCode >= 500{ 25 | print("server error") 26 | }catch { 27 | print("other error") 28 | } 29 | 30 | 31 | // switch语句做限定条件 32 | let student:(name:String, score:Int) = ("小明", 59) 33 | switch student { 34 | case let (_,score) where score < 60: 35 | print("不及格") 36 | default: 37 | print("及格") 38 | } 39 | 40 | // 限定泛型需要遵守的协议 41 | //第一种写法 42 | func genericFunctionA(str:S) where S:ExpressibleByStringLiteral{ 43 | print(str) 44 | } 45 | //第二种写法 46 | func genericFunctionB(str:S){ 47 | print(str) 48 | } 49 | 50 | 51 | // 为指定的类添加对应的协议扩展 52 | extension Sequence where Element: Numeric { 53 | var sum: Element { 54 | var result: Element = 0 55 | for item in self { 56 | result += item 57 | } 58 | return result 59 | } 60 | } 61 | 62 | print([1,2,3,4].sum) 63 | 64 | 65 | // 做某些高阶函数的限定条件 66 | let names = ["Joan", "John", "Jack"] 67 | let firstJname = names.first(where: { (name) -> Bool in 68 | return name.first == "J" 69 | }) 70 | firstJname 71 | 72 | let fruits = ["Banana", "Apple", "Kiwi"] 73 | let containsBanana = fruits.contains(where: { (fruit) in 74 | return fruit == "Banana" 75 | }) 76 | containsBanana 77 | -------------------------------------------------------------------------------- /MyPlayground.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Source/IBDesignableView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/IBDesignableView.png -------------------------------------------------------------------------------- /Source/TableViewRefreshAnimation2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/TableViewRefreshAnimation2.gif -------------------------------------------------------------------------------- /Source/addContainerView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/addContainerView.png -------------------------------------------------------------------------------- /Source/addshortcuts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/addshortcuts.png -------------------------------------------------------------------------------- /Source/addshortcutsgif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/addshortcutsgif.gif -------------------------------------------------------------------------------- /Source/anchor_autoLayout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/anchor_autoLayout.png -------------------------------------------------------------------------------- /Source/attributed_url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/attributed_url.png -------------------------------------------------------------------------------- /Source/blink_scale_corner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/blink_scale_corner.gif -------------------------------------------------------------------------------- /Source/changeStatusBarStyle2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/changeStatusBarStyle2.gif -------------------------------------------------------------------------------- /Source/color_wheel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/color_wheel.png -------------------------------------------------------------------------------- /Source/custom_actionsheet.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/custom_actionsheet.gif -------------------------------------------------------------------------------- /Source/embedTableViewController.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/embedTableViewController.png -------------------------------------------------------------------------------- /Source/namespace_module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/namespace_module.png -------------------------------------------------------------------------------- /Source/padding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/padding.png -------------------------------------------------------------------------------- /Source/popOverView.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/popOverView.gif -------------------------------------------------------------------------------- /Source/present_part_controller.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/present_part_controller.gif -------------------------------------------------------------------------------- /Source/restoration_id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/restoration_id.png -------------------------------------------------------------------------------- /Source/shadow_move.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/shadow_move.gif -------------------------------------------------------------------------------- /Source/showStyle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/showStyle.png -------------------------------------------------------------------------------- /Source/tabbarAnimating.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/tabbarAnimating.gif -------------------------------------------------------------------------------- /Source/themeDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/themeDemo.gif -------------------------------------------------------------------------------- /Source/toast_view.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/toast_view.gif -------------------------------------------------------------------------------- /Source/yellow_pixel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/Source/yellow_pixel.png -------------------------------------------------------------------------------- /SwiftTipsDemo/DCTool/DCTool/DCTool.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DCTool.swift 3 | // SwiftTipsDemo 4 | // 5 | // Created by Dariel on 2018/9/30. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | /// 判断多个值中是否包含某一个值 11 | /// 12 | /// - Parameter values: 需要比较的值,可以是多个 13 | /// - Returns: 可以用` ==`比较的类型 14 | /// 15 | /// let string = "One" 16 | /// 17 | /// if string == any(of: "One", "Two", "Three") { 18 | /// 19 | /// } 20 | func any(of values: T...) -> EquatableValueSequence { 21 | return EquatableValueSequence(values: values) 22 | } 23 | 24 | struct EquatableValueSequence { 25 | static func == (lhs: EquatableValueSequence, rhs: T) -> Bool { 26 | return lhs.values.contains(rhs) 27 | } 28 | static func == (lhs: T, rhs: EquatableValueSequence) -> Bool { 29 | return rhs == lhs 30 | } 31 | fileprivate let values: [T] 32 | } 33 | -------------------------------------------------------------------------------- /SwiftTipsDemo/DCTool/DCTool/EdgeInsetLabel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EdgeInsetLabel.swift 3 | // SwiftTipsDemo 4 | // 5 | // Created by Dariel on 2018/12/11. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @IBDesignable 12 | class EdgeInsetLabel: UILabel { 13 | var textInsets = UIEdgeInsets.zero { 14 | didSet { invalidateIntrinsicContentSize() } 15 | } 16 | override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect { 17 | let insetRect = bounds.inset(by: textInsets) 18 | let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines) 19 | let invertedInsets = UIEdgeInsets(top: -textInsets.top, 20 | left: -textInsets.left, 21 | bottom: -textInsets.bottom, 22 | right: -textInsets.right) 23 | return textRect.inset(by: invertedInsets) 24 | } 25 | override func drawText(in rect: CGRect) { 26 | super.drawText(in: rect.inset(by: textInsets)) 27 | } 28 | } 29 | 30 | extension EdgeInsetLabel { 31 | @IBInspectable 32 | var leftTextInset: CGFloat { 33 | set { textInsets.left = newValue } 34 | get { return textInsets.left } 35 | } 36 | @IBInspectable 37 | var rightTextInset: CGFloat { 38 | set { textInsets.right = newValue } 39 | get { return textInsets.right } 40 | } 41 | @IBInspectable 42 | var topTextInset: CGFloat { 43 | set { textInsets.top = newValue } 44 | get { return textInsets.top } 45 | } 46 | @IBInspectable 47 | var bottomTextInset: CGFloat { 48 | set { textInsets.bottom = newValue } 49 | get { return textInsets.bottom } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /SwiftTipsDemo/DCTool/DCTool/ViewControllerInjector.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewDidLoadInjector.swift 3 | // SwiftTipsDemo 4 | // 5 | // Created by Dariel on 2018/10/17. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ObjectiveC.runtime 11 | 12 | class ViewControllerInjector { 13 | typealias MethodRef = @convention(c)(UIViewController, Selector) -> Void 14 | static func inject(into supportedClasses: [UIViewController.Type], selector: Selector, 15 | injection: @escaping (UIViewController) -> Void) { 16 | guard let originalMethod = class_getInstanceMethod(UIViewController.self, selector) else { 17 | fatalError("\(selector) must be implemented") 18 | } 19 | var originalIMP: IMP? 20 | let swizzledViewDidLoadBlock: @convention(block) (UIViewController) -> Void = { receiver in 21 | if let originalIMP = originalIMP { 22 | let castedIMP = unsafeBitCast(originalIMP, to: MethodRef.self) 23 | castedIMP(receiver, selector) 24 | } 25 | if ViewControllerInjector.canInject(to: receiver, supportedClasses: supportedClasses) { 26 | injection(receiver) 27 | } 28 | } 29 | let swizzledIMP = imp_implementationWithBlock(unsafeBitCast(swizzledViewDidLoadBlock, to: AnyObject.self)) 30 | originalIMP = method_setImplementation(originalMethod, swizzledIMP) 31 | } 32 | private static func canInject(to receiver: Any, supportedClasses: [UIViewController.Type]) -> Bool { 33 | let supportedClassesIDs = supportedClasses.map { ObjectIdentifier($0) } 34 | let receiverType = type(of: receiver) 35 | return supportedClassesIDs.contains(ObjectIdentifier(receiverType)) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SwiftTipsDemo/DCTool/Extension/Collection+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Collection+Extension.swift 3 | // SwiftTipsDemo 4 | // 5 | // Created by Dariel on 2018/10/16. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension Collection { 12 | /// 判断是否有满足条件的元素 13 | /// 14 | /// [1, 2, 3, 4, 5].all { $0 > 10 } 15 | /// false 16 | func all(_ predicate: (Element) throws -> Bool) rethrows -> Bool { 17 | for item in self { 18 | let result = try predicate(item) 19 | if !result { 20 | return false 21 | } 22 | } 23 | return true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SwiftTipsDemo/DCTool/Extension/UIColor+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Extension.swift 3 | // SwiftTipsDemo 4 | // 5 | // Created by Dariel on 2018/10/9. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIColor { 12 | class var darkNight: UIColor { 13 | return UIColor(2, 21, 51) 14 | } 15 | public convenience init(_ red: CGFloat, _ green: CGFloat, _ blue: CGFloat, _ alpha: CGFloat = 1) { 16 | self.init(red: red / 255.0, green: green / 255.0, blue: blue / 255.0, alpha: alpha) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SwiftTipsDemo/DCTool/Extension/UITableView+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UITableView+Extension.swift 3 | // SwiftTipsDemo 4 | // 5 | // Created by Dariel on 2019/3/19. 6 | // Copyright © 2019 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UITableView { 12 | /// 添加空白页 13 | /// 14 | /// - Parameter message: 空白页文字 15 | func setNoDataPlaceholder(_ message: String) { 16 | let label = UILabel(frame: CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.bounds.size.height)) 17 | label.text = message 18 | label.textAlignment = .center 19 | label.sizeToFit() 20 | self.isScrollEnabled = false 21 | self.backgroundView = label 22 | self.separatorStyle = .none 23 | } 24 | /// 删除空白页 25 | func removeNoDataPlaceholder() { 26 | self.isScrollEnabled = true 27 | self.backgroundView = nil 28 | self.separatorStyle = .singleLine 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SwiftTipsDemo/DCTool/Extension/UIViewController+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Extension.swift 3 | // SwiftTipsDemo 4 | // 5 | // Created by Dariel on 2018/10/15. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIViewController { 12 | public func dch_checkDeallocation(afterDelay delay: TimeInterval = 2.0) { 13 | let rootParentViewController = dchRootParentViewController 14 | if isMovingFromParent || rootParentViewController.isBeingDismissed { 15 | let disappearanceSource: String = isMovingFromParent ? "removed from its parent" : "dismissed" 16 | DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: { [weak self] in 17 | if let controller = self { 18 | assert(self == nil, "\(controller.description) not deallocated after being \(disappearanceSource)") 19 | } 20 | }) 21 | } 22 | } 23 | private var dchRootParentViewController: UIViewController { 24 | var root = self 25 | while let parent = root.parent { 26 | root = parent 27 | } 28 | return root 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SwiftTipsDemo/DCTool/Extension/UIWindow+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIWindow+Extension.swift 3 | // SwiftTipsDemo 4 | // 5 | // Created by Dariel on 2018/10/9. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIWindow { 12 | /// 刷新所有的子控件 13 | func reload() { 14 | subviews.forEach { view in 15 | view.removeFromSuperview() 16 | addSubview(view) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SwiftTipsDemo/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'SwiftTipsDemo' do 5 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | pod 'SwiftLint' 9 | 10 | # Pods for SwiftTipsDemo 11 | 12 | end 13 | -------------------------------------------------------------------------------- /SwiftTipsDemo/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SwiftLint (0.27.0) 3 | 4 | DEPENDENCIES: 5 | - SwiftLint 6 | 7 | SPEC REPOS: 8 | https://github.com/cocoapods/specs.git: 9 | - SwiftLint 10 | 11 | SPEC CHECKSUMS: 12 | SwiftLint: 3207c1faa2240bf8973b191820a116113cd11073 13 | 14 | PODFILE CHECKSUM: 22de33a6ef19ed5ccc457ade870ff1ac04fbde91 15 | 16 | COCOAPODS: 1.5.3 17 | -------------------------------------------------------------------------------- /SwiftTipsDemo/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SwiftLint (0.27.0) 3 | 4 | DEPENDENCIES: 5 | - SwiftLint 6 | 7 | SPEC REPOS: 8 | https://github.com/cocoapods/specs.git: 9 | - SwiftLint 10 | 11 | SPEC CHECKSUMS: 12 | SwiftLint: 3207c1faa2240bf8973b191820a116113cd11073 13 | 14 | PODFILE CHECKSUM: 22de33a6ef19ed5ccc457ade870ff1ac04fbde91 15 | 16 | COCOAPODS: 1.5.3 17 | -------------------------------------------------------------------------------- /SwiftTipsDemo/Pods/SwiftLint/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Realm Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SwiftTipsDemo/Pods/SwiftLint/swiftlint: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/SwiftTipsDemo/Pods/SwiftLint/swiftlint -------------------------------------------------------------------------------- /SwiftTipsDemo/Pods/Target Support Files/Pods-SwiftTipsDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SwiftTipsDemo/Pods/Target Support Files/Pods-SwiftTipsDemo/Pods-SwiftTipsDemo-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## SwiftLint 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2015 Realm Inc. 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | Generated by CocoaPods - https://cocoapods.org 29 | -------------------------------------------------------------------------------- /SwiftTipsDemo/Pods/Target Support Files/Pods-SwiftTipsDemo/Pods-SwiftTipsDemo-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_SwiftTipsDemo : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_SwiftTipsDemo 5 | @end 6 | -------------------------------------------------------------------------------- /SwiftTipsDemo/Pods/Target Support Files/Pods-SwiftTipsDemo/Pods-SwiftTipsDemo-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_SwiftTipsDemoVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_SwiftTipsDemoVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /SwiftTipsDemo/Pods/Target Support Files/Pods-SwiftTipsDemo/Pods-SwiftTipsDemo.debug.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 3 | PODS_BUILD_DIR = ${BUILD_DIR} 4 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 5 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 6 | PODS_ROOT = ${SRCROOT}/Pods 7 | -------------------------------------------------------------------------------- /SwiftTipsDemo/Pods/Target Support Files/Pods-SwiftTipsDemo/Pods-SwiftTipsDemo.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_SwiftTipsDemo { 2 | umbrella header "Pods-SwiftTipsDemo-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftTipsDemo/Pods/Target Support Files/Pods-SwiftTipsDemo/Pods-SwiftTipsDemo.release.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 3 | PODS_BUILD_DIR = ${BUILD_DIR} 4 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 5 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 6 | PODS_ROOT = ${SRCROOT}/Pods 7 | -------------------------------------------------------------------------------- /SwiftTipsDemo/SwiftTipsDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftTipsDemo/SwiftTipsDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftTipsDemo/SwiftTipsDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SwiftTipsDemo/SwiftTipsDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftTipsDemo/SwiftTipsDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SwiftTipsDemo 4 | // 5 | // Created by Dariel on 2018/9/28. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, 17 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | return true 19 | } 20 | func applicationWillResignActive(_ application: UIApplication) { 21 | } 22 | func applicationDidEnterBackground(_ application: UIApplication) { 23 | } 24 | func applicationWillEnterForeground(_ application: UIApplication) { 25 | } 26 | func applicationDidBecomeActive(_ application: UIApplication) { 27 | } 28 | func applicationWillTerminate(_ application: UIApplication) { 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SwiftTipsDemo/SwiftTipsDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /SwiftTipsDemo/SwiftTipsDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SwiftTipsDemo/SwiftTipsDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SwiftTipsDemo/SwiftTipsDemo/DetailViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.swift 3 | // SwiftTipsDemo 4 | // 5 | // Created by Dariel on 2018/10/18. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DetailViewController: UIViewController { 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SwiftTipsDemo/SwiftTipsDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /SwiftTipsDemo/SwiftTipsDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SwiftTipsDemo 4 | // 5 | // Created by Dariel on 2018/9/28. 6 | // Copyright © 2018年 Dariel. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /XcodeTips/source/after_refactor_storyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/XcodeTips/source/after_refactor_storyboard.png -------------------------------------------------------------------------------- /XcodeTips/source/breakpoint_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/XcodeTips/source/breakpoint_view.png -------------------------------------------------------------------------------- /XcodeTips/source/control_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/XcodeTips/source/control_distance.png -------------------------------------------------------------------------------- /XcodeTips/source/lock_control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/XcodeTips/source/lock_control.png -------------------------------------------------------------------------------- /XcodeTips/source/more_layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/XcodeTips/source/more_layer.png -------------------------------------------------------------------------------- /XcodeTips/source/refactor_storyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/XcodeTips/source/refactor_storyboard.png -------------------------------------------------------------------------------- /XcodeTips/source/rename.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/XcodeTips/source/rename.png -------------------------------------------------------------------------------- /XcodeTips/source/set_storyboard_reference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/XcodeTips/source/set_storyboard_reference.png -------------------------------------------------------------------------------- /XcodeTips/source/storyboard_reference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarielChen/iOSTips/0b1dcf69a63cf24c2858cf80ace0882580cd1072/XcodeTips/source/storyboard_reference.png --------------------------------------------------------------------------------