├── Codable ├── Codable.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── ahmedmasoud.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── ahmedmasoud.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── Codable.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── ahmedmasoud.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist ├── Codable │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── Model │ │ ├── CompanyModel.swift │ │ ├── PostModel.swift │ │ └── UserModel.swift │ ├── SceneDelegate.swift │ └── ViewController.swift ├── Podfile ├── Podfile.lock └── Pods │ ├── Alamofire │ ├── LICENSE │ ├── README.md │ └── Source │ │ ├── AFError.swift │ │ ├── Alamofire.swift │ │ ├── AlamofireExtended.swift │ │ ├── CachedResponseHandler.swift │ │ ├── DispatchQueue+Alamofire.swift │ │ ├── EventMonitor.swift │ │ ├── HTTPHeaders.swift │ │ ├── HTTPMethod.swift │ │ ├── MultipartFormData.swift │ │ ├── MultipartUpload.swift │ │ ├── NetworkReachabilityManager.swift │ │ ├── Notifications.swift │ │ ├── OperationQueue+Alamofire.swift │ │ ├── ParameterEncoder.swift │ │ ├── ParameterEncoding.swift │ │ ├── Protector.swift │ │ ├── RedirectHandler.swift │ │ ├── Request.swift │ │ ├── RequestInterceptor.swift │ │ ├── RequestTaskMap.swift │ │ ├── Response.swift │ │ ├── ResponseSerialization.swift │ │ ├── Result+Alamofire.swift │ │ ├── RetryPolicy.swift │ │ ├── ServerTrustEvaluation.swift │ │ ├── Session.swift │ │ ├── SessionDelegate.swift │ │ ├── URLConvertible+URLRequestConvertible.swift │ │ ├── URLEncodedFormEncoder.swift │ │ ├── URLRequest+Alamofire.swift │ │ ├── URLSessionConfiguration+Alamofire.swift │ │ └── Validation.swift │ ├── Manifest.lock │ ├── Pods.xcodeproj │ ├── project.pbxproj │ └── xcuserdata │ │ └── ahmedmasoud.xcuserdatad │ │ └── xcschemes │ │ ├── Alamofire.xcscheme │ │ ├── Pods-Codable.xcscheme │ │ └── xcschememanagement.plist │ └── Target Support Files │ ├── Alamofire │ ├── Alamofire-Info.plist │ ├── Alamofire-dummy.m │ ├── Alamofire-prefix.pch │ ├── Alamofire-umbrella.h │ ├── Alamofire.modulemap │ └── Alamofire.xcconfig │ └── Pods-Codable │ ├── Pods-Codable-Info.plist │ ├── Pods-Codable-acknowledgements.markdown │ ├── Pods-Codable-acknowledgements.plist │ ├── Pods-Codable-dummy.m │ ├── Pods-Codable-frameworks-Debug-input-files.xcfilelist │ ├── Pods-Codable-frameworks-Debug-output-files.xcfilelist │ ├── Pods-Codable-frameworks-Release-input-files.xcfilelist │ ├── Pods-Codable-frameworks-Release-output-files.xcfilelist │ ├── Pods-Codable-frameworks.sh │ ├── Pods-Codable-umbrella.h │ ├── Pods-Codable.debug.xcconfig │ ├── Pods-Codable.modulemap │ └── Pods-Codable.release.xcconfig ├── CustomTransitions ├── CustomTransitions.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── ahmedmasoud.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── ahmedmasoud.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── CustomTransitions │ ├── Animator │ └── StretchAnimator.swift │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── SceneDelegate.swift │ └── Views │ ├── DetailVC.swift │ └── ViewController.swift ├── DispatchGroups └── DispatchGroups.playground │ ├── Contents.swift │ ├── contents.xcplayground │ └── playground.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ └── ahmedmasoud.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── FacebookStoryAnimation ├── FacebookStoryAnnimation.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── ahmedmasoud.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── ahmedmasoud.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist └── FacebookStoryAnnimation │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── SceneDelegate.swift │ └── ViewController.swift ├── LocalizationManager ├── LocalizationManager.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── ahmedmasoud.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── ahmedmasoud.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── LocalizationManager │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── arrow.imageset │ │ ├── Contents.json │ │ └── arrow.png │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── LocalizationManager.swift │ ├── ViewController.swift │ ├── ar.lproj │ └── Localizable.strings │ └── en.lproj │ └── localizable.strings ├── LoginAnimation ├── LoginAnimation.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── ahmedmasoud.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── ahmedmasoud.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist └── LoginAnimation │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── logo.imageset │ │ ├── Contents.json │ │ └── icon-4399622_960_720.png │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── ButtonsVC.swift │ ├── Info.plist │ ├── SceneDelegate.swift │ └── ViewController.swift ├── NetworkLayer ├── NetworkLayer.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── ahmedmasoud.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ ├── ahmedmasoud.xcuserdatad │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ │ └── fatema.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── NetworkLayer.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ ├── ahmedmasoud.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── fatema.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── NetworkLayer │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Constants.swift │ ├── Info.plist │ ├── Models │ │ └── UserModel.swift │ ├── Networkinng │ │ ├── Base │ │ │ ├── BaseAPI.swift │ │ │ ├── BaseResponse.swift │ │ │ └── TargetType.swift │ │ └── Users │ │ │ ├── UsersAPI.swift │ │ │ └── UsersNetworking.swift │ ├── SceneDelegate.swift │ └── ViewController.swift ├── Podfile ├── Podfile.lock └── Pods │ ├── Alamofire │ ├── LICENSE │ ├── README.md │ └── Source │ │ ├── AFError.swift │ │ ├── Alamofire.swift │ │ ├── AlamofireExtended.swift │ │ ├── CachedResponseHandler.swift │ │ ├── DispatchQueue+Alamofire.swift │ │ ├── EventMonitor.swift │ │ ├── HTTPHeaders.swift │ │ ├── HTTPMethod.swift │ │ ├── MultipartFormData.swift │ │ ├── MultipartUpload.swift │ │ ├── NetworkReachabilityManager.swift │ │ ├── Notifications.swift │ │ ├── OperationQueue+Alamofire.swift │ │ ├── ParameterEncoder.swift │ │ ├── ParameterEncoding.swift │ │ ├── Protector.swift │ │ ├── RedirectHandler.swift │ │ ├── Request.swift │ │ ├── RequestInterceptor.swift │ │ ├── RequestTaskMap.swift │ │ ├── Response.swift │ │ ├── ResponseSerialization.swift │ │ ├── Result+Alamofire.swift │ │ ├── RetryPolicy.swift │ │ ├── ServerTrustEvaluation.swift │ │ ├── Session.swift │ │ ├── SessionDelegate.swift │ │ ├── URLConvertible+URLRequestConvertible.swift │ │ ├── URLEncodedFormEncoder.swift │ │ ├── URLRequest+Alamofire.swift │ │ ├── URLSessionConfiguration+Alamofire.swift │ │ └── Validation.swift │ ├── Manifest.lock │ ├── Pods.xcodeproj │ ├── project.pbxproj │ └── xcuserdata │ │ ├── ahmedmasoud.xcuserdatad │ │ └── xcschemes │ │ │ ├── Alamofire.xcscheme │ │ │ ├── Pods-NetworkLayer.xcscheme │ │ │ └── xcschememanagement.plist │ │ └── fatema.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist │ └── Target Support Files │ ├── Alamofire │ ├── Alamofire-Info.plist │ ├── Alamofire-dummy.m │ ├── Alamofire-prefix.pch │ ├── Alamofire-umbrella.h │ ├── Alamofire.modulemap │ └── Alamofire.xcconfig │ └── Pods-NetworkLayer │ ├── Pods-NetworkLayer-Info.plist │ ├── Pods-NetworkLayer-acknowledgements.markdown │ ├── Pods-NetworkLayer-acknowledgements.plist │ ├── Pods-NetworkLayer-dummy.m │ ├── Pods-NetworkLayer-frameworks-Debug-input-files.xcfilelist │ ├── Pods-NetworkLayer-frameworks-Debug-output-files.xcfilelist │ ├── Pods-NetworkLayer-frameworks-Release-input-files.xcfilelist │ ├── Pods-NetworkLayer-frameworks-Release-output-files.xcfilelist │ ├── Pods-NetworkLayer-frameworks.sh │ ├── Pods-NetworkLayer-umbrella.h │ ├── Pods-NetworkLayer.debug.xcconfig │ ├── Pods-NetworkLayer.modulemap │ └── Pods-NetworkLayer.release.xcconfig ├── README.md ├── StretchyTableHeader ├── StretchyTableHeader.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── ahmedmasoud.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── ahmedmasoud.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── StretchyTableHeader │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── header.imageset │ │ ├── Contents.json │ │ └── header.png │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── SceneDelegate.swift │ └── ViewController.swift └── ToastManager ├── ToastManager.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── ahmedmasoud.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── ahmedmasoud.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist └── ToastManager ├── AppDelegate.swift ├── Assets.xcassets ├── AppIcon.appiconset │ └── Contents.json └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── Info.plist ├── Managers ├── KeyboardStateManager.swift └── ToastManager.swift ├── SceneDelegate.swift └── Views ├── ToastView ├── ToastView.swift └── ToastView.xib └── ViewController.swift /Codable/Codable.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Codable/Codable.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Codable/Codable.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/Codable/Codable.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Codable/Codable.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Codable.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 2 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Codable/Codable.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Codable/Codable.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Codable/Codable.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/Codable/Codable.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Codable/Codable.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /Codable/Codable/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Codable 4 | // 5 | // Created by Ahmed masoud on 3/30/20. 6 | // Copyright © 2020 Ahmed Masoud. 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 | -------------------------------------------------------------------------------- /Codable/Codable/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 | } -------------------------------------------------------------------------------- /Codable/Codable/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Codable/Codable/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 | -------------------------------------------------------------------------------- /Codable/Codable/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 | -------------------------------------------------------------------------------- /Codable/Codable/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UISupportedInterfaceOrientations~ipad 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationPortraitUpsideDown 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /Codable/Codable/Model/CompanyModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CompanyModel.swift 3 | // Codable 4 | // 5 | // Created by Ahmed masoud on 3/30/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class CompanyModel: Decodable { 12 | var name: String? 13 | } 14 | 15 | -------------------------------------------------------------------------------- /Codable/Codable/Model/PostModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostModel.swift 3 | // Codable 4 | // 5 | // Created by Ahmed masoud on 3/30/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class PostModel: Decodable { 12 | var title: String? 13 | var body: String? 14 | } 15 | -------------------------------------------------------------------------------- /Codable/Codable/Model/UserModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserModel.swift 3 | // Codable 4 | // 5 | // Created by Ahmed masoud on 3/30/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class UserModel: Decodable { 12 | //MARK:- Properties 13 | var id: Int? 14 | var name: String? 15 | var email: String? 16 | var userName: String? 17 | var company: CompanyModel? 18 | 19 | enum CodingKeys: String, CodingKey { 20 | case id 21 | case name 22 | case email 23 | case userName = "username" 24 | case company 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Codable/Codable/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // Codable 4 | // 5 | // Created by Ahmed masoud on 3/30/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 20 | guard let _ = (scene as? UIWindowScene) else { return } 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | } 34 | 35 | func sceneWillResignActive(_ scene: UIScene) { 36 | // Called when the scene will move from an active state to an inactive state. 37 | // This may occur due to temporary interruptions (ex. an incoming phone call). 38 | } 39 | 40 | func sceneWillEnterForeground(_ scene: UIScene) { 41 | // Called as the scene transitions from the background to the foreground. 42 | // Use this method to undo the changes made on entering the background. 43 | } 44 | 45 | func sceneDidEnterBackground(_ scene: UIScene) { 46 | // Called as the scene transitions from the foreground to the background. 47 | // Use this method to save data, release shared resources, and store enough scene-specific state information 48 | // to restore the scene back to its current state. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /Codable/Codable/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Codable 4 | // 5 | // Created by Ahmed masoud on 3/30/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Alamofire 11 | 12 | class ViewController: UIViewController { 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | 17 | fetchData(url: "https://jsonplaceholder.typicode.com/users", responseClass: [UserModel].self) { (response) in 18 | switch response { 19 | case .success(let users): 20 | guard let users = users else { return } 21 | for user in users { 22 | print("name -> \(user.name)") 23 | } 24 | case .failure(_): 25 | print("ERROR") 26 | } 27 | } 28 | 29 | } 30 | 31 | func fetchData(url: String, responseClass: T.Type , completion:@escaping (Result) -> Void) { 32 | AF.request(url, method: .get, parameters: [:], headers: [:]).responseJSON { (response) in 33 | guard let statusCode = response.response?.statusCode else { return } 34 | if statusCode == 200 { // Success 35 | guard let jsonResponse = try? response.result.get() else { return } 36 | guard let theJSONData = try? JSONSerialization.data(withJSONObject: jsonResponse, options: []) else { return } 37 | guard let responseObj = try? JSONDecoder().decode(T.self, from: theJSONData) else { return } 38 | completion(.success(responseObj)) 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Codable/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'Codable' do 5 | # Comment the next line if you don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | # Pods for Codable 9 | pod 'Alamofire' 10 | end 11 | -------------------------------------------------------------------------------- /Codable/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (5.0.2) 3 | 4 | DEPENDENCIES: 5 | - Alamofire 6 | 7 | SPEC REPOS: 8 | https://github.com/cocoapods/specs.git: 9 | - Alamofire 10 | 11 | SPEC CHECKSUMS: 12 | Alamofire: 3ba7a4db18b4f62c4a1c0e1cb39d7f3d52e10ada 13 | 14 | PODFILE CHECKSUM: dfbe2768ec522903afa51e515607c7b55f473ff4 15 | 16 | COCOAPODS: 1.7.5 17 | -------------------------------------------------------------------------------- /Codable/Pods/Alamofire/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2020 Alamofire Software Foundation (http://alamofire.org/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Codable/Pods/Alamofire/Source/Alamofire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Alamofire.swift 3 | // 4 | // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | /// Reference to `Session.default` for quick bootstrapping and examples. 26 | public let AF = Session.default 27 | 28 | /// Current Alamofire version. Necessary since SPM doesn't use dynamic libraries. Plus this will be more accurate. 29 | let version = "5.0.2" 30 | -------------------------------------------------------------------------------- /Codable/Pods/Alamofire/Source/AlamofireExtended.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlamofireExtended.swift 3 | // 4 | // Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | /// Type that acts as a generic extension point for all `AlamofireExtended` types. 26 | public struct AlamofireExtension { 27 | /// Stores the type or meta-type of any extended type. 28 | public private(set) var type: ExtendedType 29 | 30 | /// Create an instance from the provided value. 31 | /// 32 | /// - Parameter type: Instance being extended. 33 | public init(_ type: ExtendedType) { 34 | self.type = type 35 | } 36 | } 37 | 38 | /// Protocol describing the `af` extension points for Alamofire extended types. 39 | public protocol AlamofireExtended { 40 | /// Type being extended. 41 | associatedtype ExtendedType 42 | 43 | /// Static Alamofire extension point. 44 | static var af: AlamofireExtension.Type { get set } 45 | /// Instance Alamofire extension point. 46 | var af: AlamofireExtension { get set } 47 | } 48 | 49 | public extension AlamofireExtended { 50 | /// Static Alamofire extension point. 51 | static var af: AlamofireExtension.Type { 52 | get { return AlamofireExtension.self } 53 | set {} 54 | } 55 | 56 | /// Instance Alamofire extension point. 57 | var af: AlamofireExtension { 58 | get { return AlamofireExtension(self) } 59 | set {} 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Codable/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DispatchQueue+Alamofire.swift 3 | // 4 | // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Dispatch 26 | import Foundation 27 | 28 | extension DispatchQueue { 29 | /// Execute the provided closure after a `TimeInterval`. 30 | /// 31 | /// - Parameters: 32 | /// - delay: `TimeInterval` to delay execution. 33 | /// - closure: Closure to execute. 34 | func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) { 35 | asyncAfter(deadline: .now() + delay, execute: closure) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Codable/Pods/Alamofire/Source/HTTPMethod.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HTTPMethod.swift 3 | // 4 | // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | /// Type representing HTTP methods. Raw `String` value is stored and compared case-sensitively, so 26 | /// `HTTPMethod.get != HTTPMethod(rawValue: "get")`. 27 | /// 28 | /// See https://tools.ietf.org/html/rfc7231#section-4.3 29 | public struct HTTPMethod: RawRepresentable, Equatable, Hashable { 30 | /// `CONNECT` method. 31 | public static let connect = HTTPMethod(rawValue: "CONNECT") 32 | /// `DELETE` method. 33 | public static let delete = HTTPMethod(rawValue: "DELETE") 34 | /// `GET` method. 35 | public static let get = HTTPMethod(rawValue: "GET") 36 | /// `HEAD` method. 37 | public static let head = HTTPMethod(rawValue: "HEAD") 38 | /// `OPTIONS` method. 39 | public static let options = HTTPMethod(rawValue: "OPTIONS") 40 | /// `PATCH` method. 41 | public static let patch = HTTPMethod(rawValue: "PATCH") 42 | /// `POST` method. 43 | public static let post = HTTPMethod(rawValue: "POST") 44 | /// `PUT` method. 45 | public static let put = HTTPMethod(rawValue: "PUT") 46 | /// `TRACE` method. 47 | public static let trace = HTTPMethod(rawValue: "TRACE") 48 | 49 | public let rawValue: String 50 | 51 | public init(rawValue: String) { 52 | self.rawValue = rawValue 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Codable/Pods/Alamofire/Source/OperationQueue+Alamofire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OperationQueue+Alamofire.swift 3 | // 4 | // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | extension OperationQueue { 28 | /// Creates an instance using the provided parameters. 29 | /// 30 | /// - Parameters: 31 | /// - qualityOfService: `QualityOfService` to be applied to the queue. `.default` by default. 32 | /// - maxConcurrentOperationCount: Maximum concurrent operations. 33 | /// `OperationQueue.defaultMaxConcurrentOperationCount` by default. 34 | /// - underlyingQueue: Underlying `DispatchQueue`. `nil` by default. 35 | /// - name: Name for the queue. `nil` by default. 36 | /// - startSuspended: Whether the queue starts suspended. `false` by default. 37 | convenience init(qualityOfService: QualityOfService = .default, 38 | maxConcurrentOperationCount: Int = OperationQueue.defaultMaxConcurrentOperationCount, 39 | underlyingQueue: DispatchQueue? = nil, 40 | name: String? = nil, 41 | startSuspended: Bool = false) { 42 | self.init() 43 | self.qualityOfService = qualityOfService 44 | self.maxConcurrentOperationCount = maxConcurrentOperationCount 45 | self.underlyingQueue = underlyingQueue 46 | self.name = name 47 | isSuspended = startSuspended 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Codable/Pods/Alamofire/Source/URLRequest+Alamofire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLRequest+Alamofire.swift 3 | // 4 | // Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | public extension URLRequest { 28 | /// Returns the `httpMethod` as Alamofire's `HTTPMethod` type. 29 | var method: HTTPMethod? { 30 | get { return httpMethod.flatMap(HTTPMethod.init) } 31 | set { httpMethod = newValue?.rawValue } 32 | } 33 | 34 | func validate() throws { 35 | if method == .get, let bodyData = httpBody { 36 | throw AFError.urlRequestValidationFailed(reason: .bodyDataInGETRequest(bodyData)) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Codable/Pods/Alamofire/Source/URLSessionConfiguration+Alamofire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLSessionConfiguration+Alamofire.swift 3 | // 4 | // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | extension URLSessionConfiguration: AlamofireExtended {} 28 | extension AlamofireExtension where ExtendedType: URLSessionConfiguration { 29 | /// Alamofire's default configuration. Same as `URLSessionConfiguration.default` but adds Alamofire default 30 | /// `Accept-Language`, `Accept-Encoding`, and `User-Agent` headers. 31 | public static var `default`: URLSessionConfiguration { 32 | let configuration = URLSessionConfiguration.default 33 | configuration.headers = .default 34 | 35 | return configuration 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Codable/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (5.0.2) 3 | 4 | DEPENDENCIES: 5 | - Alamofire 6 | 7 | SPEC REPOS: 8 | https://github.com/cocoapods/specs.git: 9 | - Alamofire 10 | 11 | SPEC CHECKSUMS: 12 | Alamofire: 3ba7a4db18b4f62c4a1c0e1cb39d7f3d52e10ada 13 | 14 | PODFILE CHECKSUM: dfbe2768ec522903afa51e515607c7b55f473ff4 15 | 16 | COCOAPODS: 1.7.5 17 | -------------------------------------------------------------------------------- /Codable/Pods/Pods.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/Alamofire.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Codable/Pods/Pods.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/Pods-Codable.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /Codable/Pods/Pods.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Alamofire.xcscheme 8 | 9 | isShown 10 | 11 | orderHint 12 | 0 13 | 14 | Pods-Codable.xcscheme 15 | 16 | isShown 17 | 18 | orderHint 19 | 1 20 | 21 | 22 | SuppressBuildableAutocreation 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Alamofire/Alamofire-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 | 5.0.2 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Alamofire/Alamofire-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Alamofire : NSObject 3 | @end 4 | @implementation PodsDummy_Alamofire 5 | @end 6 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Alamofire/Alamofire-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 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Alamofire/Alamofire-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 AlamofireVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char AlamofireVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Alamofire/Alamofire.modulemap: -------------------------------------------------------------------------------- 1 | framework module Alamofire { 2 | umbrella header "Alamofire-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Alamofire/Alamofire.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Alamofire 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" 4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Alamofire 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Pods-Codable/Pods-Codable-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 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Pods-Codable/Pods-Codable-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Alamofire 5 | 6 | Copyright (c) 2014-2020 Alamofire Software Foundation (http://alamofire.org/) 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Pods-Codable/Pods-Codable-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2014-2020 Alamofire Software Foundation (http://alamofire.org/) 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | License 38 | MIT 39 | Title 40 | Alamofire 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Pods-Codable/Pods-Codable-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Codable : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Codable 5 | @end 6 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Pods-Codable/Pods-Codable-frameworks-Debug-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-Codable/Pods-Codable-frameworks.sh 2 | ${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Pods-Codable/Pods-Codable-frameworks-Debug-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Pods-Codable/Pods-Codable-frameworks-Release-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-Codable/Pods-Codable-frameworks.sh 2 | ${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Pods-Codable/Pods-Codable-frameworks-Release-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Pods-Codable/Pods-Codable-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_CodableVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_CodableVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Pods-Codable/Pods-Codable.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "CFNetwork" 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 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Pods-Codable/Pods-Codable.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Codable { 2 | umbrella header "Pods-Codable-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Codable/Pods/Target Support Files/Pods-Codable/Pods-Codable.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "CFNetwork" 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 | -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/CustomTransitions/CustomTransitions.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CustomTransitions.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions/Animator/StretchAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StretchAnimator.swift 3 | // CustomTransitions 4 | // 5 | // Created by Ahmed masoud on 3/27/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class StretchAnimator: NSObject { 12 | //MARK:- Properties 13 | private let duration = 0.8 14 | var presenting = true 15 | var originFrame = CGRect.zero 16 | } 17 | 18 | // MARK:- Transition Animation Delegate conformance 19 | extension StretchAnimator: UIViewControllerAnimatedTransitioning { 20 | 21 | func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 22 | return duration 23 | } 24 | 25 | func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 26 | let containerView = transitionContext.containerView 27 | let toView = transitionContext.view(forKey: .to)! 28 | let detailView = presenting ? toView : transitionContext.view(forKey: .from)! 29 | let initialFrame = presenting ? originFrame : detailView.frame 30 | let finalFrame = presenting ? detailView.frame : originFrame 31 | 32 | let xScaleFactor = presenting ? 33 | initialFrame.width / finalFrame.width : 34 | finalFrame.width / initialFrame.width 35 | 36 | let yScaleFactor = presenting ? 37 | initialFrame.height / finalFrame.height : 38 | finalFrame.height / initialFrame.height 39 | 40 | let scaleTransform = CGAffineTransform(scaleX: xScaleFactor, y: yScaleFactor) 41 | 42 | if presenting { 43 | detailView.transform = scaleTransform 44 | detailView.center = CGPoint( 45 | x: initialFrame.midX, 46 | y: initialFrame.midY) 47 | detailView.clipsToBounds = true 48 | } 49 | 50 | containerView.addSubview(toView) 51 | containerView.bringSubviewToFront(detailView) 52 | 53 | UIView.animate( 54 | withDuration: duration, 55 | delay:0.0, 56 | animations: { [weak self] in 57 | guard let self = self else { return } 58 | detailView.transform = self.presenting ? .identity : scaleTransform 59 | detailView.center = CGPoint(x: finalFrame.midX, y: finalFrame.midY) 60 | }, completion: { _ in 61 | transitionContext.completeTransition(true) 62 | }) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // CustomTransitions 4 | // 5 | // Created by Ahmed masoud on 3/27/20. 6 | // Copyright © 2020 Ahmed Masoud. 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 | @available(iOS 13.0, *) 24 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 25 | // Called when a new scene session is being created. 26 | // Use this method to select a configuration to create the new scene with. 27 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 28 | } 29 | 30 | @available(iOS 13.0, *) 31 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 32 | // Called when the user discards a scene session. 33 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 34 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 35 | } 36 | 37 | 38 | } 39 | 40 | -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions/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 | } -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions/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 | -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | 54 | UISupportedInterfaceOrientations~ipad 55 | 56 | UIInterfaceOrientationPortrait 57 | UIInterfaceOrientationPortraitUpsideDown 58 | UIInterfaceOrientationLandscapeLeft 59 | UIInterfaceOrientationLandscapeRight 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // CustomTransitions 4 | // 5 | // Created by Ahmed masoud on 3/27/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @available(iOS 13.0, *) 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | guard let _ = (scene as? UIWindowScene) else { return } 22 | } 23 | 24 | func sceneDidDisconnect(_ scene: UIScene) { 25 | // Called as the scene is being released by the system. 26 | // This occurs shortly after the scene enters the background, or when its session is discarded. 27 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 28 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 29 | } 30 | 31 | func sceneDidBecomeActive(_ scene: UIScene) { 32 | // Called when the scene has moved from an inactive state to an active state. 33 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 34 | } 35 | 36 | func sceneWillResignActive(_ scene: UIScene) { 37 | // Called when the scene will move from an active state to an inactive state. 38 | // This may occur due to temporary interruptions (ex. an incoming phone call). 39 | } 40 | 41 | func sceneWillEnterForeground(_ scene: UIScene) { 42 | // Called as the scene transitions from the background to the foreground. 43 | // Use this method to undo the changes made on entering the background. 44 | } 45 | 46 | func sceneDidEnterBackground(_ scene: UIScene) { 47 | // Called as the scene transitions from the foreground to the background. 48 | // Use this method to save data, release shared resources, and store enough scene-specific state information 49 | // to restore the scene back to its current state. 50 | } 51 | 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions/Views/DetailVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DetailVC.swift 3 | // CustomTransitions 4 | // 5 | // Created by Ahmed masoud on 3/27/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class DetailVC: UIViewController { 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | } 17 | 18 | class func create() -> DetailVC { 19 | let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "\(DetailVC.self)") as! DetailVC 20 | vc.modalPresentationStyle = .fullScreen 21 | return vc 22 | } 23 | @IBAction func dismissVC(_ sender: Any) { 24 | self.dismiss(animated: true, completion: nil) 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /CustomTransitions/CustomTransitions/Views/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // CustomTransitions 4 | // 5 | // Created by Ahmed masoud on 3/27/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | //MARK:- Properties 14 | let transition = StretchAnimator() 15 | @IBOutlet weak var searchContainerView: UIView! 16 | 17 | //MARK:- LifeCycle 18 | override func viewDidLoad() { 19 | super.viewDidLoad() 20 | // Do any additional setup after loading the view. 21 | } 22 | 23 | //MARK:- Methods 24 | @IBAction func openDetailVC(_ sender: Any) { 25 | let vc = DetailVC.create() 26 | vc.transitioningDelegate = self 27 | self.present(vc, animated: true, completion: nil) 28 | } 29 | 30 | } 31 | 32 | //MARK:- Transition Delegate Conformance 33 | extension ViewController: UIViewControllerTransitioningDelegate { 34 | func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 35 | transition.originFrame = searchContainerView.frame 36 | transition.presenting = true 37 | return transition 38 | } 39 | 40 | func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 41 | transition.presenting = false 42 | return transition 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /DispatchGroups/DispatchGroups.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | 4 | 5 | func heavyDuty(identifier: String, _ completion: @escaping ()->()) { 6 | var i = 0 7 | while i < 5000 { 8 | print("\(identifier) ======> \(i)") 9 | i+=1 10 | } 11 | completion() 12 | } 13 | 14 | 15 | let queue1 = DispatchQueue(label: "queue 1") 16 | let queue2 = DispatchQueue(label: "queue 2") 17 | let dispatchGroup = DispatchGroup() 18 | 19 | dispatchGroup.enter() 20 | queue1.async { 21 | heavyDuty(identifier: "call 1") { 22 | dispatchGroup.leave() 23 | } 24 | } 25 | dispatchGroup.enter() 26 | queue2.async { 27 | heavyDuty(identifier: "call 2") { 28 | dispatchGroup.leave() 29 | } 30 | } 31 | 32 | dispatchGroup.notify(queue: .main) { 33 | print("Done") 34 | } 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /DispatchGroups/DispatchGroups.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /DispatchGroups/DispatchGroups.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DispatchGroups/DispatchGroups.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /DispatchGroups/DispatchGroups.playground/playground.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/DispatchGroups/DispatchGroups.playground/playground.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /FacebookStoryAnimation/FacebookStoryAnnimation.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FacebookStoryAnimation/FacebookStoryAnnimation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FacebookStoryAnimation/FacebookStoryAnnimation.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/FacebookStoryAnimation/FacebookStoryAnnimation.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /FacebookStoryAnimation/FacebookStoryAnnimation.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /FacebookStoryAnimation/FacebookStoryAnnimation.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | FacebookStoryAnnimation.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /FacebookStoryAnimation/FacebookStoryAnnimation/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // FacebookStoryAnnimation 4 | // 5 | // Created by Ahmed masoud on 5/5/20. 6 | // Copyright © 2020 Ahmed Masoud. 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 | -------------------------------------------------------------------------------- /FacebookStoryAnimation/FacebookStoryAnnimation/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 | -------------------------------------------------------------------------------- /FacebookStoryAnimation/FacebookStoryAnnimation/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FacebookStoryAnimation/FacebookStoryAnnimation/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 | -------------------------------------------------------------------------------- /FacebookStoryAnimation/FacebookStoryAnnimation/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UISupportedInterfaceOrientations~ipad 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationPortraitUpsideDown 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /FacebookStoryAnimation/FacebookStoryAnnimation/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // FacebookStoryAnnimation 4 | // 5 | // Created by Ahmed masoud on 5/5/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 20 | guard let _ = (scene as? UIWindowScene) else { return } 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | } 34 | 35 | func sceneWillResignActive(_ scene: UIScene) { 36 | // Called when the scene will move from an active state to an inactive state. 37 | // This may occur due to temporary interruptions (ex. an incoming phone call). 38 | } 39 | 40 | func sceneWillEnterForeground(_ scene: UIScene) { 41 | // Called as the scene transitions from the background to the foreground. 42 | // Use this method to undo the changes made on entering the background. 43 | } 44 | 45 | func sceneDidEnterBackground(_ scene: UIScene) { 46 | // Called as the scene transitions from the foreground to the background. 47 | // Use this method to save data, release shared resources, and store enough scene-specific state information 48 | // to restore the scene back to its current state. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/LocalizationManager/LocalizationManager.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | LocalizationManager.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // LocalizationManager 4 | // 5 | // Created by Ahmed masoud on 8/10/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | LocalizationManager.shared.delegate = self 18 | LocalizationManager.shared.setAppInnitLanguage() 19 | return true 20 | } 21 | 22 | 23 | } 24 | 25 | extension AppDelegate: LocalizationDelegate { 26 | func resetApp() { 27 | guard let window = window else { return } 28 | let storyboard = UIStoryboard(name: "Main", bundle: nil) 29 | let vc = storyboard.instantiateViewController(identifier: "ViewController") 30 | window.rootViewController = vc 31 | let options: UIView.AnimationOptions = .transitionCrossDissolve 32 | let duration: TimeInterval = 0.3 33 | UIView.transition(with: window, duration: duration, options: options, animations: nil, completion: nil) 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager/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 | -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager/Assets.xcassets/arrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "arrow.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager/Assets.xcassets/arrow.imageset/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/LocalizationManager/LocalizationManager/Assets.xcassets/arrow.imageset/arrow.png -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager/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 | -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 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 | -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // LocalizationManager 4 | // 5 | // Created by Ahmed masoud on 8/10/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | @IBOutlet weak var myLabel: UILabel! 14 | @IBOutlet weak var myImage: UIImageView! 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | myLabel.text = "Language Check".localized 19 | } 20 | 21 | override func viewDidLayoutSubviews() { 22 | super.viewDidLayoutSubviews() 23 | let image = UIImage(named: "arrow")?.imageFlippedForRightToLeftLayoutDirection() 24 | myImage.image = image 25 | } 26 | 27 | @IBAction func switchLanguage(_ sender: Any) { 28 | if LocalizationManager.shared.getLanguage() == .Arabic { 29 | LocalizationManager.shared.setLanguage(language: .English) 30 | } else { 31 | LocalizationManager.shared.setLanguage(language: .Arabic) 32 | } 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager/ar.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | LocalizationManager 4 | 5 | Created by Ahmed masoud on 8/10/20. 6 | Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | */ 8 | "Language Check"="اختبار اللغه"; 9 | -------------------------------------------------------------------------------- /LocalizationManager/LocalizationManager/en.lproj/localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | LocalizationManager 4 | 5 | Created by Ahmed masoud on 8/10/20. 6 | Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | */ 8 | "Language Check" = "Language Check"; 9 | -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/LoginAnimation/LoginAnimation.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | LoginAnimation.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // LoginAnimation 4 | // 5 | // Created by Ahmed masoud on 4/11/20. 6 | // Copyright © 2020 Ahmed Masoud. 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 | -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation/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 | } -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation/Assets.xcassets/logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon-4399622_960_720.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 | } -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation/Assets.xcassets/logo.imageset/icon-4399622_960_720.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/LoginAnimation/LoginAnimation/Assets.xcassets/logo.imageset/icon-4399622_960_720.png -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation/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 | -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation/ButtonsVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ButtonsVC.swift 3 | // LoginAnimation 4 | // 5 | // Created by Ahmed masoud on 4/12/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ButtonsVC: UIViewController { 12 | 13 | @IBOutlet weak var circleView: UIView! 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | circleView.layer.borderWidth = 2 18 | circleView.layer.borderColor = UIColor.red.cgColor 19 | circleView.backgroundColor = .red 20 | circleView.layer.cornerRadius = 30 21 | } 22 | 23 | @IBAction func tapACtion(_ sender: UIButton) { 24 | UIView.animate(withDuration: 0.5) { 25 | self.circleView.center.x = sender.center.x 26 | } 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UISupportedInterfaceOrientations~ipad 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationPortraitUpsideDown 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // LoginAnimation 4 | // 5 | // Created by Ahmed masoud on 4/11/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 20 | guard let _ = (scene as? UIWindowScene) else { return } 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | } 34 | 35 | func sceneWillResignActive(_ scene: UIScene) { 36 | // Called when the scene will move from an active state to an inactive state. 37 | // This may occur due to temporary interruptions (ex. an incoming phone call). 38 | } 39 | 40 | func sceneWillEnterForeground(_ scene: UIScene) { 41 | // Called as the scene transitions from the background to the foreground. 42 | // Use this method to undo the changes made on entering the background. 43 | } 44 | 45 | func sceneDidEnterBackground(_ scene: UIScene) { 46 | // Called as the scene transitions from the foreground to the background. 47 | // Use this method to save data, release shared resources, and store enough scene-specific state information 48 | // to restore the scene back to its current state. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /LoginAnimation/LoginAnimation/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // LoginAnimation 4 | // 5 | // Created by Ahmed masoud on 4/11/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | @IBOutlet weak var imageView: UIImageView! 14 | @IBOutlet weak var userNameTextField: UITextField! 15 | @IBOutlet weak var passwordTextField: UITextField! 16 | @IBOutlet weak var loginButton: UIButton! 17 | @IBOutlet weak var loginButtonTopConstraint: NSLayoutConstraint! 18 | @IBOutlet weak var loadingSpinner: UIActivityIndicatorView! 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | loadingSpinner.isHidden = true 23 | hideViews() 24 | } 25 | 26 | override func viewDidAppear(_ animated: Bool) { 27 | super.viewDidAppear(animated) 28 | animateViews() 29 | } 30 | 31 | 32 | @IBAction func loginAction(_ sender: Any) { 33 | animateLogin() 34 | } 35 | 36 | 37 | func hideViews() { 38 | let scaleDownTransform = CGAffineTransform(scaleX: 0, y: 0) 39 | imageView.transform = scaleDownTransform 40 | let scaleLeftTransform = CGAffineTransform(translationX: -UIScreen.main.bounds.width, y: 0) 41 | userNameTextField.transform = scaleLeftTransform 42 | let scaleRightTransform = CGAffineTransform(translationX: UIScreen.main.bounds.width, y: 0) 43 | passwordTextField.transform = scaleRightTransform 44 | 45 | } 46 | 47 | func animateViews() { 48 | DispatchQueue.main.async { 49 | UIView.animate(withDuration: 0.2) { 50 | self.imageView.transform = .identity // CGAffineTransform(scaleX: 1, y: 1) 51 | self.userNameTextField.transform = .identity 52 | self.passwordTextField.transform = .identity 53 | } 54 | } 55 | } 56 | 57 | func animateLogin() { 58 | self.loginButtonTopConstraint.constant = 100 59 | UIView.animate(withDuration: 0.2, animations: { 60 | self.view.layoutIfNeeded() 61 | }) { (_) in 62 | self.loadingSpinner.isHidden = false 63 | self.loadingSpinner.startAnimating() 64 | } 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/NetworkLayer/NetworkLayer.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | NetworkLayer.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 2 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer.xcodeproj/xcuserdata/fatema.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | NetworkLayer.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/NetworkLayer/NetworkLayer.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer.xcworkspace/xcuserdata/fatema.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/NetworkLayer/NetworkLayer.xcworkspace/xcuserdata/fatema.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // NetworkLayer 4 | // 5 | // Created by Ahmed masoud on 3/30/20. 6 | // Copyright © 2020 Ahmed Masoud. 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 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/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 | } -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/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 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/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 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // NetworkLayer 4 | // 5 | // Created by Ahmed masoud on 6/19/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | struct ErrorMessage { 13 | static let genericError = "Something went wrong please try again later" 14 | } 15 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSAllowsArbitraryLoads 8 | 9 | 10 | CFBundleDevelopmentRegion 11 | $(DEVELOPMENT_LANGUAGE) 12 | CFBundleExecutable 13 | $(EXECUTABLE_NAME) 14 | CFBundleIdentifier 15 | $(PRODUCT_BUNDLE_IDENTIFIER) 16 | CFBundleInfoDictionaryVersion 17 | 6.0 18 | CFBundleName 19 | $(PRODUCT_NAME) 20 | CFBundlePackageType 21 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 22 | CFBundleShortVersionString 23 | 1.0 24 | CFBundleVersion 25 | 1 26 | LSRequiresIPhoneOS 27 | 28 | UIApplicationSceneManifest 29 | 30 | UIApplicationSupportsMultipleScenes 31 | 32 | UISceneConfigurations 33 | 34 | UIWindowSceneSessionRoleApplication 35 | 36 | 37 | UISceneConfigurationName 38 | Default Configuration 39 | UISceneDelegateClassName 40 | $(PRODUCT_MODULE_NAME).SceneDelegate 41 | UISceneStoryboardFile 42 | Main 43 | 44 | 45 | 46 | 47 | UILaunchStoryboardName 48 | LaunchScreen 49 | UIMainStoryboardFile 50 | Main 51 | UIRequiredDeviceCapabilities 52 | 53 | armv7 54 | 55 | UISupportedInterfaceOrientations 56 | 57 | UIInterfaceOrientationPortrait 58 | UIInterfaceOrientationLandscapeLeft 59 | UIInterfaceOrientationLandscapeRight 60 | 61 | UISupportedInterfaceOrientations~ipad 62 | 63 | UIInterfaceOrientationPortrait 64 | UIInterfaceOrientationPortraitUpsideDown 65 | UIInterfaceOrientationLandscapeLeft 66 | UIInterfaceOrientationLandscapeRight 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/Models/UserModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserModel.swift 3 | // NetworkLayer 4 | // 5 | // Created by Ahmed masoud on 5/21/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class UserModel: Codable { 12 | var name: String? 13 | var salary: String? 14 | 15 | enum CodingKeys: String, CodingKey { 16 | case name = "employee_name" 17 | case salary = "employee_salary" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/Networkinng/Base/BaseAPI.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseAPI.swift 3 | // NetworkLayer 4 | // 5 | // Created by Ahmed masoud on 5/21/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Alamofire 11 | 12 | class BaseAPI { 13 | 14 | func fetchData(target: T, responseClass: M.Type, completion:@escaping (Result) -> Void) { 15 | let method = Alamofire.HTTPMethod(rawValue: target.method.rawValue) 16 | let headers = Alamofire.HTTPHeaders(target.headers ?? [:]) 17 | let params = buildParams(task: target.task) 18 | AF.request(target.baseURL + target.path, method: method, parameters: params.0, encoding: params.1, headers: headers).responseJSON { (response) in 19 | guard let statusCode = response.response?.statusCode else { 20 | // ADD Custom Error 21 | let error = NSError(domain: target.baseURL, code: 0, userInfo: [NSLocalizedDescriptionKey: ErrorMessage.genericError]) 22 | completion(.failure(error)) 23 | return 24 | } 25 | if statusCode == 200 { // 200 reflect success response 26 | // Successful request 27 | guard let jsonResponse = try? response.result.get() else { 28 | // ADD Custom Error 29 | let error = NSError(domain: target.baseURL, code: 0, userInfo: [NSLocalizedDescriptionKey: ErrorMessage.genericError]) 30 | completion(.failure(error)) 31 | return 32 | } 33 | guard let theJSONData = try? JSONSerialization.data(withJSONObject: jsonResponse, options: []) else { 34 | // ADD Custom Error 35 | let error = NSError(domain: target.baseURL, code: 0, userInfo: [NSLocalizedDescriptionKey: ErrorMessage.genericError]) 36 | completion(.failure(error)) 37 | return 38 | } 39 | guard let responseObj = try? JSONDecoder().decode(M.self, from: theJSONData) else { 40 | // ADD Custom Error 41 | let error = NSError(domain: target.baseURL, code: 0, userInfo: [NSLocalizedDescriptionKey: ErrorMessage.genericError]) 42 | completion(.failure(error)) 43 | return 44 | } 45 | completion(.success(responseObj)) 46 | } else { 47 | // ADD custom error base on status code 404 / 401 / 48 | // Error Parsing for the error message from the BE 49 | let message = "Error Message Parsed From BE" 50 | let error = NSError(domain: target.baseURL, code: statusCode, userInfo: [NSLocalizedDescriptionKey: message]) 51 | completion(.failure(error)) 52 | } 53 | } 54 | } 55 | 56 | 57 | private func buildParams(task: Task) -> ([String:Any], ParameterEncoding) { 58 | switch task { 59 | case .requestPlain: 60 | return ([:], URLEncoding.default) 61 | case .requestParameters(parameters: let parameters, encoding: let encoding): 62 | return (parameters, encoding) 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/Networkinng/Base/BaseResponse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseResponse.swift 3 | // NetworkLayer 4 | // 5 | // Created by Ahmed masoud on 6/29/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | class BaseResponse: Codable { 13 | var status: String? 14 | var data: T? 15 | 16 | enum CodingKeys: String, CodingKey { 17 | case status = "status" 18 | case data = "data" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/Networkinng/Base/TargetType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TargetType.swift 3 | // NetworkLayer 4 | // 5 | // Created by Ahmed masoud on 5/21/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Alamofire 11 | 12 | enum HTTPMethod: String { 13 | case get = "GET" 14 | case post = "POST" 15 | case put = "PUT" 16 | case delete = "DELETE" 17 | } 18 | 19 | enum Task { 20 | 21 | /// A request with no additional data. 22 | case requestPlain 23 | 24 | /// A requests body set with encoded parameters. 25 | case requestParameters(parameters: [String: Any], encoding: ParameterEncoding) 26 | } 27 | 28 | protocol TargetType { 29 | 30 | /// The target's base `URL`. 31 | var baseURL: String { get } 32 | 33 | /// The path to be appended to `baseURL` to form the full `URL`. 34 | var path: String { get } 35 | 36 | /// The HTTP method used in the request. 37 | var method: HTTPMethod { get } 38 | 39 | /// The type of HTTP task to be performed. 40 | var task: Task { get } 41 | 42 | /// The headers to be used in the request. 43 | var headers: [String: String]? { get } 44 | } 45 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/Networkinng/Users/UsersAPI.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UsersAPI.swift 3 | // NetworkLayer 4 | // 5 | // Created by Ahmed masoud on 5/21/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol UsersAPIProtocol { 12 | func getUsers(completion: @escaping (Result?, NSError>) -> Void) 13 | } 14 | 15 | 16 | class UsersAPI: BaseAPI, UsersAPIProtocol { 17 | 18 | //MARK:- Requests 19 | 20 | func getUsers(completion: @escaping (Result?, NSError>) -> Void) { 21 | self.fetchData(target: .getUsers, responseClass: BaseResponse<[UserModel]>.self) { (result) in 22 | completion(result) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/Networkinng/Users/UsersNetworking.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UsersNetworking.swift 3 | // NetworkLayer 4 | // 5 | // Created by Ahmed masoud on 5/21/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Alamofire 11 | 12 | enum UsersNetworking { 13 | case getUsers 14 | case createUser(name: String, job: String) 15 | } 16 | 17 | extension UsersNetworking: TargetType { 18 | var baseURL: String { 19 | switch self { 20 | case .getUsers: 21 | return "http://dummy.restapiexample.com/api/v1" 22 | default: 23 | return "https://reqres.in/api" 24 | } 25 | } 26 | 27 | var path: String { 28 | switch self { 29 | case .getUsers: 30 | return "/employees" 31 | case .createUser: 32 | return "/users" 33 | } 34 | } 35 | 36 | var method: HTTPMethod { 37 | switch self { 38 | case .getUsers: 39 | return .get 40 | case .createUser: 41 | return .post 42 | } 43 | } 44 | 45 | var task: Task { 46 | switch self { 47 | case .getUsers: 48 | return .requestPlain 49 | case .createUser(let name, let job): 50 | return .requestParameters(parameters: ["name": name, "job": job], encoding: JSONEncoding.default) 51 | } 52 | } 53 | 54 | var headers: [String : String]? { 55 | switch self { 56 | default: 57 | return [:] 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // NetworkLayer 4 | // 5 | // Created by Ahmed masoud on 3/30/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 20 | guard let _ = (scene as? UIWindowScene) else { return } 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | } 34 | 35 | func sceneWillResignActive(_ scene: UIScene) { 36 | // Called when the scene will move from an active state to an inactive state. 37 | // This may occur due to temporary interruptions (ex. an incoming phone call). 38 | } 39 | 40 | func sceneWillEnterForeground(_ scene: UIScene) { 41 | // Called as the scene transitions from the background to the foreground. 42 | // Use this method to undo the changes made on entering the background. 43 | } 44 | 45 | func sceneDidEnterBackground(_ scene: UIScene) { 46 | // Called as the scene transitions from the foreground to the background. 47 | // Use this method to save data, release shared resources, and store enough scene-specific state information 48 | // to restore the scene back to its current state. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /NetworkLayer/NetworkLayer/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // NetworkLayer 4 | // 5 | // Created by Ahmed masoud on 3/30/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | let api: UsersAPIProtocol = UsersAPI() 16 | api.getUsers { (result) in 17 | switch result { 18 | case .success(let response): 19 | let users = response?.data 20 | for user in users ?? [] { 21 | print("\(user.name ?? "") => \(user.salary ?? "")") 22 | } 23 | case .failure(let error): 24 | print(error.userInfo[NSLocalizedDescriptionKey] as? String ?? "") 25 | } 26 | } 27 | } 28 | 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /NetworkLayer/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'NetworkLayer' do 5 | # Comment the next line if you don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | # Pods for NetworkLayer 9 | pod 'Alamofire' 10 | end 11 | -------------------------------------------------------------------------------- /NetworkLayer/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (5.0.2) 3 | 4 | DEPENDENCIES: 5 | - Alamofire 6 | 7 | SPEC REPOS: 8 | https://github.com/cocoapods/specs.git: 9 | - Alamofire 10 | 11 | SPEC CHECKSUMS: 12 | Alamofire: 3ba7a4db18b4f62c4a1c0e1cb39d7f3d52e10ada 13 | 14 | PODFILE CHECKSUM: c259b15ca909ebe147df21b3c1eee974fe39c59b 15 | 16 | COCOAPODS: 1.7.5 17 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Alamofire/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2020 Alamofire Software Foundation (http://alamofire.org/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Alamofire/Source/Alamofire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Alamofire.swift 3 | // 4 | // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | /// Reference to `Session.default` for quick bootstrapping and examples. 26 | public let AF = Session.default 27 | 28 | /// Current Alamofire version. Necessary since SPM doesn't use dynamic libraries. Plus this will be more accurate. 29 | let version = "5.0.2" 30 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Alamofire/Source/AlamofireExtended.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlamofireExtended.swift 3 | // 4 | // Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | /// Type that acts as a generic extension point for all `AlamofireExtended` types. 26 | public struct AlamofireExtension { 27 | /// Stores the type or meta-type of any extended type. 28 | public private(set) var type: ExtendedType 29 | 30 | /// Create an instance from the provided value. 31 | /// 32 | /// - Parameter type: Instance being extended. 33 | public init(_ type: ExtendedType) { 34 | self.type = type 35 | } 36 | } 37 | 38 | /// Protocol describing the `af` extension points for Alamofire extended types. 39 | public protocol AlamofireExtended { 40 | /// Type being extended. 41 | associatedtype ExtendedType 42 | 43 | /// Static Alamofire extension point. 44 | static var af: AlamofireExtension.Type { get set } 45 | /// Instance Alamofire extension point. 46 | var af: AlamofireExtension { get set } 47 | } 48 | 49 | public extension AlamofireExtended { 50 | /// Static Alamofire extension point. 51 | static var af: AlamofireExtension.Type { 52 | get { return AlamofireExtension.self } 53 | set {} 54 | } 55 | 56 | /// Instance Alamofire extension point. 57 | var af: AlamofireExtension { 58 | get { return AlamofireExtension(self) } 59 | set {} 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DispatchQueue+Alamofire.swift 3 | // 4 | // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Dispatch 26 | import Foundation 27 | 28 | extension DispatchQueue { 29 | /// Execute the provided closure after a `TimeInterval`. 30 | /// 31 | /// - Parameters: 32 | /// - delay: `TimeInterval` to delay execution. 33 | /// - closure: Closure to execute. 34 | func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) { 35 | asyncAfter(deadline: .now() + delay, execute: closure) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Alamofire/Source/HTTPMethod.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HTTPMethod.swift 3 | // 4 | // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | /// Type representing HTTP methods. Raw `String` value is stored and compared case-sensitively, so 26 | /// `HTTPMethod.get != HTTPMethod(rawValue: "get")`. 27 | /// 28 | /// See https://tools.ietf.org/html/rfc7231#section-4.3 29 | public struct HTTPMethod: RawRepresentable, Equatable, Hashable { 30 | /// `CONNECT` method. 31 | public static let connect = HTTPMethod(rawValue: "CONNECT") 32 | /// `DELETE` method. 33 | public static let delete = HTTPMethod(rawValue: "DELETE") 34 | /// `GET` method. 35 | public static let get = HTTPMethod(rawValue: "GET") 36 | /// `HEAD` method. 37 | public static let head = HTTPMethod(rawValue: "HEAD") 38 | /// `OPTIONS` method. 39 | public static let options = HTTPMethod(rawValue: "OPTIONS") 40 | /// `PATCH` method. 41 | public static let patch = HTTPMethod(rawValue: "PATCH") 42 | /// `POST` method. 43 | public static let post = HTTPMethod(rawValue: "POST") 44 | /// `PUT` method. 45 | public static let put = HTTPMethod(rawValue: "PUT") 46 | /// `TRACE` method. 47 | public static let trace = HTTPMethod(rawValue: "TRACE") 48 | 49 | public let rawValue: String 50 | 51 | public init(rawValue: String) { 52 | self.rawValue = rawValue 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Alamofire/Source/OperationQueue+Alamofire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OperationQueue+Alamofire.swift 3 | // 4 | // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | extension OperationQueue { 28 | /// Creates an instance using the provided parameters. 29 | /// 30 | /// - Parameters: 31 | /// - qualityOfService: `QualityOfService` to be applied to the queue. `.default` by default. 32 | /// - maxConcurrentOperationCount: Maximum concurrent operations. 33 | /// `OperationQueue.defaultMaxConcurrentOperationCount` by default. 34 | /// - underlyingQueue: Underlying `DispatchQueue`. `nil` by default. 35 | /// - name: Name for the queue. `nil` by default. 36 | /// - startSuspended: Whether the queue starts suspended. `false` by default. 37 | convenience init(qualityOfService: QualityOfService = .default, 38 | maxConcurrentOperationCount: Int = OperationQueue.defaultMaxConcurrentOperationCount, 39 | underlyingQueue: DispatchQueue? = nil, 40 | name: String? = nil, 41 | startSuspended: Bool = false) { 42 | self.init() 43 | self.qualityOfService = qualityOfService 44 | self.maxConcurrentOperationCount = maxConcurrentOperationCount 45 | self.underlyingQueue = underlyingQueue 46 | self.name = name 47 | isSuspended = startSuspended 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Alamofire/Source/URLRequest+Alamofire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLRequest+Alamofire.swift 3 | // 4 | // Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | public extension URLRequest { 28 | /// Returns the `httpMethod` as Alamofire's `HTTPMethod` type. 29 | var method: HTTPMethod? { 30 | get { return httpMethod.flatMap(HTTPMethod.init) } 31 | set { httpMethod = newValue?.rawValue } 32 | } 33 | 34 | func validate() throws { 35 | if method == .get, let bodyData = httpBody { 36 | throw AFError.urlRequestValidationFailed(reason: .bodyDataInGETRequest(bodyData)) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Alamofire/Source/URLSessionConfiguration+Alamofire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLSessionConfiguration+Alamofire.swift 3 | // 4 | // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | extension URLSessionConfiguration: AlamofireExtended {} 28 | extension AlamofireExtension where ExtendedType: URLSessionConfiguration { 29 | /// Alamofire's default configuration. Same as `URLSessionConfiguration.default` but adds Alamofire default 30 | /// `Accept-Language`, `Accept-Encoding`, and `User-Agent` headers. 31 | public static var `default`: URLSessionConfiguration { 32 | let configuration = URLSessionConfiguration.default 33 | configuration.headers = .default 34 | 35 | return configuration 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (5.0.2) 3 | 4 | DEPENDENCIES: 5 | - Alamofire 6 | 7 | SPEC REPOS: 8 | https://github.com/cocoapods/specs.git: 9 | - Alamofire 10 | 11 | SPEC CHECKSUMS: 12 | Alamofire: 3ba7a4db18b4f62c4a1c0e1cb39d7f3d52e10ada 13 | 14 | PODFILE CHECKSUM: c259b15ca909ebe147df21b3c1eee974fe39c59b 15 | 16 | COCOAPODS: 1.7.5 17 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Pods.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/Alamofire.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Pods.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/Pods-NetworkLayer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Pods.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Alamofire.xcscheme 8 | 9 | isShown 10 | 11 | orderHint 12 | 0 13 | 14 | Pods-NetworkLayer.xcscheme 15 | 16 | isShown 17 | 18 | orderHint 19 | 1 20 | 21 | 22 | SuppressBuildableAutocreation 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Pods.xcodeproj/xcuserdata/fatema.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Alamofire.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | Pods-NetworkLayer.xcscheme 13 | 14 | orderHint 15 | 2 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Alamofire/Alamofire-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 | 5.0.2 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Alamofire/Alamofire-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Alamofire : NSObject 3 | @end 4 | @implementation PodsDummy_Alamofire 5 | @end 6 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Alamofire/Alamofire-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 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Alamofire/Alamofire-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 AlamofireVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char AlamofireVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Alamofire/Alamofire.modulemap: -------------------------------------------------------------------------------- 1 | framework module Alamofire { 2 | umbrella header "Alamofire-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Alamofire/Alamofire.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Alamofire 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" 4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Alamofire 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer-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 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Alamofire 5 | 6 | Copyright (c) 2014-2020 Alamofire Software Foundation (http://alamofire.org/) 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2014-2020 Alamofire Software Foundation (http://alamofire.org/) 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | License 38 | MIT 39 | Title 40 | Alamofire 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_NetworkLayer : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_NetworkLayer 5 | @end 6 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer-frameworks-Debug-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer-frameworks.sh 2 | ${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer-frameworks-Debug-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer-frameworks-Release-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer-frameworks.sh 2 | ${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer-frameworks-Release-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer-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_NetworkLayerVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_NetworkLayerVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "CFNetwork" 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 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_NetworkLayer { 2 | umbrella header "Pods-NetworkLayer-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /NetworkLayer/Pods/Target Support Files/Pods-NetworkLayer/Pods-NetworkLayer.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "CFNetwork" 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tutorials 2 | This repo will contain source codes for my tutorials on my youtube channel 3 | check it out: https://www.youtube.com/user/Iphone284 4 | -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/StretchyTableHeader/StretchyTableHeader.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | StretchyTableHeader.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // StretchyTableHeader 4 | // 5 | // Created by Ahmed masoud on 5/3/20. 6 | // Copyright © 2020 Ahmed Masoud. 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 | -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader/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 | -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader/Assets.xcassets/header.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "header.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader/Assets.xcassets/header.imageset/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/StretchyTableHeader/StretchyTableHeader/Assets.xcassets/header.imageset/header.png -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader/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 | -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | 54 | UISupportedInterfaceOrientations~ipad 55 | 56 | UIInterfaceOrientationPortrait 57 | UIInterfaceOrientationPortraitUpsideDown 58 | UIInterfaceOrientationLandscapeLeft 59 | UIInterfaceOrientationLandscapeRight 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // StretchyTableHeader 4 | // 5 | // Created by Ahmed masoud on 5/3/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 20 | guard let _ = (scene as? UIWindowScene) else { return } 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | } 34 | 35 | func sceneWillResignActive(_ scene: UIScene) { 36 | // Called when the scene will move from an active state to an inactive state. 37 | // This may occur due to temporary interruptions (ex. an incoming phone call). 38 | } 39 | 40 | func sceneWillEnterForeground(_ scene: UIScene) { 41 | // Called as the scene transitions from the background to the foreground. 42 | // Use this method to undo the changes made on entering the background. 43 | } 44 | 45 | func sceneDidEnterBackground(_ scene: UIScene) { 46 | // Called as the scene transitions from the foreground to the background. 47 | // Use this method to save data, release shared resources, and store enough scene-specific state information 48 | // to restore the scene back to its current state. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /StretchyTableHeader/StretchyTableHeader/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // StretchyTableHeader 4 | // 5 | // Created by Ahmed masoud on 5/3/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { 12 | 13 | @IBOutlet weak var myTable: UITableView! 14 | var headerView: UIView! 15 | let headerHeight: CGFloat = 250 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | headerView = myTable.tableHeaderView 20 | myTable.tableHeaderView = nil 21 | myTable.addSubview(headerView) 22 | myTable.contentInset = UIEdgeInsets(top: headerHeight, left: 0, bottom: 0, right: 0) 23 | myTable.contentOffset = CGPoint(x: 0, y: -headerHeight) 24 | updateHeader() 25 | } 26 | 27 | func updateHeader() { 28 | print(myTable.contentOffset.y) 29 | if myTable.contentOffset.y < -headerHeight { 30 | headerView.frame.origin.y = myTable.contentOffset.y 31 | headerView.frame.size.height = -myTable.contentOffset.y 32 | } 33 | } 34 | 35 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 36 | return 20 37 | } 38 | 39 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 40 | let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) 41 | cell.textLabel?.text = "[\(indexPath.section),\(indexPath.row)]" 42 | return cell 43 | } 44 | 45 | func scrollViewDidScroll(_ scrollView: UIScrollView) { 46 | updateHeader() 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /ToastManager/ToastManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ToastManager/ToastManager.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ToastManager/ToastManager.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ahmed-Masoud/Tutorials/5bbaf498957c7d8d6ba545cea930bceb515889ec/ToastManager/ToastManager.xcodeproj/project.xcworkspace/xcuserdata/ahmedmasoud.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ToastManager/ToastManager.xcodeproj/xcuserdata/ahmedmasoud.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ToastManager.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ToastManager/ToastManager/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ToastManager 4 | // 5 | // Created by Ahmed masoud on 4/3/20. 6 | // Copyright © 2020 Ahmed Masoud. 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 | KeyboardStateManager.shared.start() 19 | return true 20 | } 21 | 22 | // MARK: UISceneSession Lifecycle 23 | 24 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 25 | // Called when a new scene session is being created. 26 | // Use this method to select a configuration to create the new scene with. 27 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 28 | } 29 | 30 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 31 | // Called when the user discards a scene session. 32 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 33 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 34 | } 35 | 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /ToastManager/ToastManager/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 | } -------------------------------------------------------------------------------- /ToastManager/ToastManager/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ToastManager/ToastManager/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 | -------------------------------------------------------------------------------- /ToastManager/ToastManager/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UISupportedInterfaceOrientations~ipad 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationPortraitUpsideDown 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /ToastManager/ToastManager/Managers/KeyboardStateManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KeyboardStateManager.swift 3 | // ToastManager 4 | // 5 | // Created by Ahmed masoud on 4/3/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class KeyboardStateManager { 13 | 14 | static let shared = KeyboardStateManager() 15 | 16 | var isVisible = false 17 | var keyboardOffset: CGFloat = 0 18 | 19 | func start() { 20 | NotificationCenter.default.addObserver(self, selector: #selector(handleShow), 21 | name: UIResponder.keyboardWillShowNotification, object: nil) 22 | NotificationCenter.default.addObserver(self, selector: #selector(handleHide), 23 | name: UIResponder.keyboardWillHideNotification, object: nil) 24 | } 25 | 26 | @objc func handleShow(_ notification: Notification) { 27 | isVisible = true 28 | if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue { 29 | let keyboardRectangle = keyboardFrame.cgRectValue 30 | keyboardOffset = keyboardRectangle.height 31 | } 32 | } 33 | 34 | @objc func handleHide() 35 | { 36 | isVisible = false 37 | } 38 | 39 | func stop() { 40 | NotificationCenter.default.removeObserver(self) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ToastManager/ToastManager/Managers/ToastManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ToastManager.swift 3 | // ToastManager 4 | // 5 | // Created by Ahmed masoud on 4/3/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class ToastManager { 13 | //MARK: Properties 14 | static let shared = ToastManager() 15 | private var view: UIView = UIView() 16 | private var message: String = "" 17 | private var bottomAnchor: NSLayoutConstraint! 18 | private var errorHeaders: [ToastView?] = [] 19 | 20 | //MARK: Methods 21 | private init() {} 22 | 23 | func showError(message: String, view: UIView) { 24 | let errorHeader: ToastView? = ToastView() 25 | errorHeaders.forEach({ 26 | hideBanner(errorHeader: $0) 27 | }) 28 | errorHeaders.append(errorHeader) 29 | self.view = view 30 | self.message = message 31 | createBannerWithInitialPosition(errorHeader: errorHeader) 32 | DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in 33 | self?.hideBanner(errorHeader: errorHeader) 34 | } 35 | } 36 | 37 | private func createBannerWithInitialPosition(errorHeader: ToastView?) { 38 | guard let errorHeader = errorHeader else { return } 39 | errorHeader.errorLabel.text = message 40 | errorHeader.layer.cornerRadius = 10 41 | errorHeader.layer.masksToBounds = true 42 | view.addSubview(errorHeader) 43 | let guide = view.safeAreaLayoutGuide 44 | errorHeader.translatesAutoresizingMaskIntoConstraints = false 45 | bottomAnchor = errorHeader.bottomAnchor.constraint(equalTo: guide.bottomAnchor, constant: 100) 46 | bottomAnchor.isActive = true 47 | errorHeader.trailingAnchor.constraint(lessThanOrEqualTo: guide.trailingAnchor, constant: -20).isActive = true 48 | errorHeader.leadingAnchor.constraint(greaterThanOrEqualTo: guide.leadingAnchor, constant: 20).isActive = true 49 | errorHeader.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true 50 | errorHeader.heightAnchor.constraint(equalToConstant: errorHeader.viewHeight).isActive = true 51 | view.layoutIfNeeded() 52 | animateBannerPresentation() 53 | } 54 | 55 | private func animateBannerPresentation() { 56 | if KeyboardStateManager.shared.isVisible { 57 | bottomAnchor.constant = -KeyboardStateManager.shared.keyboardOffset 58 | } else { 59 | bottomAnchor.constant = -20 60 | } 61 | UIView.animate(withDuration: 0.5, delay: 0.3, options: [], animations: { [weak self] in self?.view.layoutIfNeeded() }, completion: nil) 62 | } 63 | 64 | private func hideBanner(errorHeader: ToastView?) { 65 | UIView.animate(withDuration: 0.5, animations: { 66 | errorHeader?.alpha = 0 67 | }) { _ in 68 | errorHeader?.removeFromSuperview() 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /ToastManager/ToastManager/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // ToastManager 4 | // 5 | // Created by Ahmed masoud on 4/3/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 20 | guard let _ = (scene as? UIWindowScene) else { return } 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | } 34 | 35 | func sceneWillResignActive(_ scene: UIScene) { 36 | // Called when the scene will move from an active state to an inactive state. 37 | // This may occur due to temporary interruptions (ex. an incoming phone call). 38 | } 39 | 40 | func sceneWillEnterForeground(_ scene: UIScene) { 41 | // Called as the scene transitions from the background to the foreground. 42 | // Use this method to undo the changes made on entering the background. 43 | } 44 | 45 | func sceneDidEnterBackground(_ scene: UIScene) { 46 | // Called as the scene transitions from the foreground to the background. 47 | // Use this method to save data, release shared resources, and store enough scene-specific state information 48 | // to restore the scene back to its current state. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /ToastManager/ToastManager/Views/ToastView/ToastView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ToastView.swift 3 | // ToastManager 4 | // 5 | // Created by Ahmed masoud on 4/3/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ToastView: UIView { 12 | 13 | //MARK: Outlets 14 | @IBOutlet var contentView: UIView! 15 | @IBOutlet weak var imageView: UIImageView! 16 | @IBOutlet weak var errorLabel: UILabel! 17 | 18 | //MARK: Properties 19 | var viewHeight: CGFloat { 20 | let textString = (errorLabel.text ?? "") as NSString 21 | let textAttributes: [NSAttributedString.Key: Any] = [.font: errorLabel.font!] 22 | let estimatedTextHeight = textString.boundingRect(with: CGSize(width: 320, height: 2000), options: .usesLineFragmentOrigin, attributes: textAttributes, context: nil).height 23 | let height = estimatedTextHeight + 30 24 | return height 25 | 26 | } 27 | //MARK: Methods 28 | override init(frame: CGRect) { 29 | super.init(frame: frame) 30 | commonInit() 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | commonInit() 36 | } 37 | 38 | private func commonInit() { 39 | Bundle.main.loadNibNamed("ToastView", owner: self, options: nil) 40 | addSubview(contentView) 41 | contentView.frame = self.bounds 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ToastManager/ToastManager/Views/ToastView/ToastView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /ToastManager/ToastManager/Views/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // ToastManager 4 | // 5 | // Created by Ahmed masoud on 4/3/20. 6 | // Copyright © 2020 Ahmed Masoud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view. 16 | } 17 | 18 | @IBAction func showToast(_ sender: Any) { 19 | ToastManager.shared.showError(message: "Hello", view: self.view) 20 | } 21 | 22 | } 23 | 24 | --------------------------------------------------------------------------------