рдПрдкреАрдЖрдИ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП рдХреЛрдбреЗрдмрд▓ рдФрд░ рдХреЛрдб рдХреЛ рдХреНрд░рдо рдореЗрдВ рдХреИрд╕реЗ рд░рдЦрд╛ рдЬрд╛рдП

рдирдорд╕реНрдХрд╛рд░, рд╣реЗрдмреНрд░!

рд╕реНрд╡рд┐рдлреНрдЯ 4 рдХреЗ рд╕рд╛рде рд╢реБрд░реВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирдП рдХреЛрдбреЗрдмрд▓ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рддрдХ рдкрд╣реБрдВрдЪ рд╣реИ, рдЬреЛ рдореЙрдбрд▓ рдХреЛ рдПрдирдХреЛрдб / рдбрд┐рдХреЛрдб рдХрд░рдирд╛ рдЖрд╕рд╛рди рдмрдирд╛рддрд╛ рд╣реИред рдореЗрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдПрдкреАрдЖрдИ рдХреЙрд▓ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд╛рд░реЗ рдХреЛрдб рд╣реИрдВ, рдФрд░ рдкрд┐рдЫрд▓реЗ рд╕рд╛рд▓ рдореИрдВрдиреЗ рдХреЛрдб рдХреЗ рдЗрд╕ рд╡рд┐рд╢рд╛рд▓ рд╕рд░рдгреА рдХреЛ рджреЛрд╣рд░рд╛рдиреЗ, рдХреЛрдб рдХреЛ рдорд╛рд░рдиреЗ рдФрд░ рдорд▓реНрдЯреАрдкрд╛рд░реНрдЯ рдЕрдиреБрд░реЛрдзреЛрдВ рдФрд░ url рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд▓рд┐рдП рднреА рдХреЛрдбреЗрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрд╣реБрдд рд╣рд▓реНрдХреЗ, рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдФрд░ рд╕рд░рд▓ рдореЗрдВ рдмрд╣реБрдд рд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рд╣реИред рд╕рд░реНрд╡рд░ рд╕реЗ рдЕрдиреБрд░реЛрдз рдФрд░ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдПрдВ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдореЗрд░реА рд░рд╛рдп рдореЗрдВ рдпрд╣ рдХрдИ рдЙрддреНрдХреГрд╖реНрдЯ рдХрдХреНрд╖рд╛рдПрдВ рдереАрдВред рд╕рд╛рде рд╣реА рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдлрд╝рд╛рдЗрд▓ рд╕рдВрд░рдЪрдирд╛, рдЬреЛ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рд╕рдореВрд╣ рдХреЗ рд▓рд┐рдП рдирд┐рдпрдВрддреНрд░рдХ рд╣реИ, рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдмреИрдХреЗрдВрдб рдкрд░ рд╡рд╛рд╖реНрдк 3 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рд░реВрдЯ рдХрд┐рдпрд╛ рдерд╛ред рдХреБрдЫ рджрд┐рдиреЛрдВ рдкрд╣рд▓реЗ, рдореИрдВрдиреЗ рдЕрдкрдиреЗ рд╕рднреА рдШрдЯрдирд╛рдХреНрд░рдореЛрдВ рдХреЛ рдПрдХ рдЕрд▓рдЧ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЛ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдФрд░ рдЗрд╕реЗ рдХреЛрдбреАрдлрд╛рдпрд░ рдирд╛рдо рджрд┐рдпрд╛ред рдореИрдВ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдЙрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред

рддреНрдпрд╛рдЧ


рдХреЛрдбреАрдлрд╛рдпрд░ рдЕрд▓рдореЛрдлрд╛рдпрд░ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЖрд▓рдореЛрдлрд╛рдпрд░ рдкрд░ рд╕рд┐рд░реНрдл рдПрдХ рдЖрд╡рд░рдг рд╕реЗ рдЕрдзрд┐рдХ рд╣реИ, рдпрд╣ рдЖрдИрдУрдПрд╕ рдХреЗ рд▓рд┐рдП рд░реАрд╕реНрдЯ рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреВрд░реА рдкреНрд░рдгрд╛рд▓реА рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реИред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдореБрдЭреЗ рдЪрд┐рдВрддрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЕрд▓реНрдореЛрдлрд╛рдпрд░ рдкрд╛рдВрдЪрд╡реЗрдВ рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рджреЗрдЦ рд░рд╣рд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдХреЛрдбреЗрдмрд▓ рд╕рдорд░реНрдерди рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдореЗрд░реА рд░рдЪрдирд╛ рдХреЛ рдирд╣реАрдВ рдорд╛рд░реЗрдЧрд╛ред

рдкреНрд░рд╛рд░рдВрдн


рдЖрдЗрдП, рдереЛрдбрд╝реА рджреВрд░ рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВ, рдЕрд░реНрдерд╛рддреН рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрдХреНрд╕рд░ рддреАрди рд╕рд░реНрд╡рд░ рд╣реЛрддреЗ рд╣реИрдВ:

рджреЗрд╡ - рд╡рд┐рдХрд╛рд╕ рдХреЗ рд▓рд┐рдП, рдЬреЛ рд╣рдо Xcode рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ
рд╕реНрдЯреЗрдЬ - рд░рд┐рд▓реАрдЬ рд╕реЗ рдкрд╣рд▓реЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП, рдЖрдорддреМрд░ рдкрд░ рдЯреЗрд╕реНрдЯрдлрд▓рд╛рдЗрдЯ рдпрд╛ рдЗрдирд╣рд╛рдЙрд╕ рдореЗрдВ
рдареЗрд╕ - рдЙрддреНрдкрд╛рджрди, AppStore рдХреЗ рд▓рд┐рдП

рдФрд░ рдХрдИ рдЖрдИрдУрдПрд╕ рдбреЗрд╡рд▓рдкрд░реНрд╕, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ рдФрд░ Xcode рдореЗрдВ рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рдЕрд╕реНрддрд┐рддреНрд╡ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореЗрд░реЗ (8+ рд╡рд░реНрд╖) рдХреЗ рдЕрднреНрдпрд╛рд╕ рд╕реЗ, 90% рдбреЗрд╡рд▓рдкрд░реНрд╕ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╕рдордп, рдпрд╛ рд╡рд┐рдзрд╛рдирд╕рднрд╛ рд╕реЗ рдкрд╣рд▓реЗ рдХреБрдЫ рд╕рд░реНрд╡рд░ рдореЗрдВ рд╕рд╣реА рд╕рд░реНрд╡рд░ рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рдФрд░ рдпрд╣ рдореИрдВ рдЗрд╕реЗ рд╕рд╣реА рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИ, рдЗрд╕рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрджрд╛рд╣рд░рдг рджрд┐рдЦрд╛ рдХрд░ рдареАрдХ рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред

рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдХреЛрдбреАрдпрд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдХрд┐рд╕ рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЪрд▓ рд░рд╣рд╛ рд╣реИ, рдпрд╣ рдЗрд╕реЗ рдмрд╣реБрдд рд╕рд░рд▓ рдмрдирд╛рддрд╛ рд╣реИ:

#if DEBUG //DEV environment #else if Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt" { //TESTFLIGHT environment } else { //APPSTORE environment } #endif 

рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╣реБрдб рдХреЗ рддрд╣рдд рд╣реИ, рдФрд░ рдРрдкрдбреЗрд▓рдЧреЗрдЯ рдореЗрдВ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдЖрдкрдХреЛ рдХреЗрд╡рд▓ рддреАрди URL рдкрдВрдЬреАрдХреГрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ

 import CodyFire @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { let dev = CodyFireEnvironment(baseURL: "http://localhost:8080") let testFlight = CodyFireEnvironment(baseURL: "https://stage.myapi.com") let appStore = CodyFireEnvironment(baseURL: "https://api.myapi.com") CodyFire.shared.configureEnvironments(dev: dev, testFlight: testFlight, appStore: appStore) return true } } 

рдФрд░ рдХрд┐рд╕реА рдХреЛ рд╕рд┐рд░реНрдл рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдЦреБрд╢реА рд╣реЛ рд╕рдХрддреА рд╣реИ рдФрд░ рдХреБрдЫ рдирд╣реАрдВред

рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЬреАрд╡рди рдореЗрдВ, рд╣рдореЗрдВ рдЕрдХреНрд╕рд░ рдПрдХреНрд╕рдХреЛрдб рдореЗрдВ рджреЗрд╡, рдордВрдЪ рдФрд░ рдареЗрд╕ рд╕рд░реНрд╡рд░ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдореИрдВ рдЖрдкрд╕реЗ рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рдпреЛрдЬрдирд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдЖрдЧреНрд░рд╣ рдХрд░рддрд╛ рд╣реВрдВред

рдЫрд╡рд┐
рдпреБрдХреНрддрд┐: рдпреЛрдЬрдирд╛рдУрдВ рдХреЛ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░реЗрдВ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ, рдкреНрд░рддреНрдпреЗрдХ рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП 'рд╕рд╛рдЭрд╛ рдХрд┐рдП рдЧрдП' рдЪреЗрдХрдмреЙрдХреНрд╕ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдирд╛ рди рднреВрд▓реЗрдВ рддрд╛рдХрд┐ рд╡реЗ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╕рднреА рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рд╣реЛрдВред

рдкреНрд░рддреНрдпреЗрдХ рдпреЛрдЬрдирд╛ рдореЗрдВ, рдЖрдкрдХреЛ рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ рдХреЛ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ `env` рдЬреЛ рддреАрди рдорд╛рди рд▓реЗ рд╕рдХрддрд╛ рд╣реИ: dev, testFlight, appStoreред

рдЫрд╡рд┐

рдФрд░ рдХреЛрдбреАрдлрд╛рдпрд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрди рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдХреЛрдбреАрдлрд╝рд╛рдпрд░ рдХреЛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж AppDelegate.didFinishLaunchingWithOptions рдкрд░ рдирд┐рдореНрди рдХреЛрдб рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ред

 CodyFire.shared.setupEnvByProjectScheme() 

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЕрдХреНрд╕рд░ рдЖрдкрдХреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рдмреЙрд╕ рдпрд╛ рдкрд░реАрдХреНрд╖рдХ рдЖрдкрдХреЛ рд▓реЙрдЧрд┐рдирд╕реНрдХреНрд░реАрди рдкрд░ рд╕рд░реНрд╡рд░ рдХреЛ рдХрд╣реАрдВ рдФрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВред рдХреЛрдбреАрдлрд╝рд╛рдпрд░ рдХреЗ рд╕рд╛рде, рдЖрдк рдЖрд╕рд╛рдиреА рд╕реЗ рд╕рд░реНрд╡рд░ рдХреЛ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рдмрджрд▓рдХрд░, рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЛ рдмрджрд▓рдХрд░ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

 CodyFire.shared.environmentMode = .appStore 

рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдкреБрдирд░рд╛рд░рдВрдн рд╣реЛрдиреЗ рддрдХ рдпрд╣ рдХрд╛рдо рдХрд░реЗрдЧрд╛, рдФрд░ рдпрджрд┐ рдЖрдк рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рд▓реЙрдиреНрдЪ рдХреЗ рдмрд╛рдж рдЗрд╕реЗ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рдП, рддреЛ UserDefaults рдореЗрдВ рдорд╛рди рдХреЛ рд╕рд╣реЗрдЬреЗрдВ , рдЬрдм AppDelegate рдореЗрдВ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЛ рдЖрд╡рд╢реНрдпрдХ рдПрдХ рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░реЗрдВред
рдореИрдВрдиреЗ рдЗрд╕ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдВрджреБ рдХреЛ рдмрддрд╛рдпрд╛, рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЕрдзрд┐рдХ рдкрд░рд┐рдпреЛрдЬрдирд╛рдПрдВ рд╣реЛрдВрдЧреА рдЬрд┐рдирдореЗрдВ рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЛ рд╕реБрдВрджрд░ рддрд░реАрдХреЗ рд╕реЗ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛ред рдФрд░ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ, рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ рд╣реИред

рдлрд╝рд╛рдЗрд▓ рд╕рдВрд░рдЪрдирд╛ рдФрд░ рдирд┐рдпрдВрддреНрд░рдХ


рдЕрдм рдЖрдк рд╕рднреА API рдХреЙрд▓ рдХреЗ рд▓рд┐рдП рдлрд╝рд╛рдЗрд▓ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореЗрд░реА рджреГрд╖реНрдЯрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕реЗ рдХреЛрдбреАрдлрд╛рдпрд░ рдХреА рд╡рд┐рдЪрд╛рд░рдзрд╛рд░рд╛ рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдЖрдЦрд┐рд░ рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ

рдЫрд╡рд┐

рдЕрдм рдлрд╛рдЗрд▓ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдкрд░ рдирдЬрд░ рдбрд╛рд▓рддреЗ рд╣реИрдВ, рдЪрд▓рд┐рдП API.swift рд╕реЗ рд╢реБрд░реБрдЖрдд рдХрд░рддреЗ рд╣реИрдВред

 class API { typealias auth = AuthController typealias post = PostController } 

рд╕рднреА рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдХреЗ рд▓рд┐рдВрдХ рдпрд╣рд╛рдВ рд╕реВрдЪреАрдмрджреНрдз рд╣реИрдВ рддрд╛рдХрд┐ рдЙрдиреНрд╣реЗрдВ рдЖрд╕рд╛рдиреА рд╕реЗ `API.controller.method` рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХреЗред

 class AuthController {} 

API + Login.swift

 extension AuthController { struct LoginResponse: Codable { var token: String } static func login(email: String, password: String) -> APIRequest<LoginResponse> { return APIRequest("login").method(.post) .basicAuth(email: email, password: password) .addCustomError(.notFound, "User not found") } } 

рдЗрд╕ рдбреЗрдХреЛрд░реЗрдЯрд░ рдореЗрдВ, рд╣рдо рдЕрдкрдиреЗ рдПрдкреАрдЖрдИ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╣реИрдВ:

- рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВ
- HTTP POST рд╡рд┐рдзрд┐
- рдореВрд▓ рд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рдЖрд╡рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
- рд╕рд░реНрд╡рд░ рд╕реЗ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рд╡рд╛рдВрдЫрд┐рдд рдкрд╛рда рдШреЛрд╖рд┐рдд рдХрд░реЗрдВ (рдпрд╣ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ)
- рдФрд░ рдЙрд╕ рдореЙрдбрд▓ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВ рдЬрд┐рд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рдбреЗрдЯрд╛ рдбрд┐рдХреЛрдб рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛

рдХреНрдпрд╛ рдЫрд┐рдкрд╛ рд░рд╣рддрд╛ рд╣реИ?

- рдкреВрд░реНрдг рд╕рд░реНрд╡рд░ URL рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╡рд┐рд╢реНрд╡ рд╕реНрддрд░ рдкрд░ рд╕реНрдерд╛рдкрд┐рдд рд╣реИ
- рдпрд╣ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдерд╛ рдХрд┐ рдЕрдЧрд░ рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИ рддреЛ рд╣рдореЗрдВ 200 рдУрдХреЗ рдорд┐рд▓рдиреЗ рдХреА рдЙрдореНрдореАрдж рд╣реИ
200 OK рд╕рднреА рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП рдХреЛрдбреАрдлрд╛рдпрд░ рджреНрд╡рд╛рд░рд╛ рдЕрдкреЗрдХреНрд╖рд┐рдд рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╕реНрдерд┐рддрд┐ рдХреЛрдб рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдбреЗрдЯрд╛ рдХреЛ рдбрд┐рдХреЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдХреЙрд▓рдмреИрдХ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХрд┐ рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИ, рдпрд╣рд╛рдВ рдЖрдкрдХрд╛ рдбреЗрдЯрд╛ рд╣реИред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдХрд╣реАрдВ рдЖрдкрдХреЗ LoginScreen рдХреЗ рдХреЛрдб рдореЗрдВ , рдЖрдк рдмрд╕ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ

 API.auth.login(email: "test@mail.com", password: "qwerty").onError { error in switch error.code { case .notFound: print(error.description) //: User not found default: print(error.description) } }.onSuccess { token in //TODO:  auth token    print("Received auth token: "+ token) } 

onError рдФрд░ onSuccess рдХреЗрд╡рд▓ рдЙрди рдХреЙрд▓рдмреИрдХ рдХрд╛ рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ рдЬреЛ APIRequest рд╡рд╛рдкрд╕ рдЖ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдо рдЙрдирдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдж рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗред

рдЗрдирдкреБрдЯ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдордиреЗ рдХреЗрд╡рд▓ рд╡рд┐рдХрд▓реНрдк рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЬрдм рд▓реМрдЯрд╛ рдбреЗрдЯрд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдбрд┐рдХреЛрдб рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЖрдк рд╕реНрд╡рдпрдВ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдЖрдк рд╕рд╣реА рд╣реЛрдВрдЧреЗред рдЗрд╕рд▓рд┐рдП, рдЖрдЗрдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдкрдВрдЬреАрдХрд░рдг рдлреЙрд░реНрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдореЙрдбрд▓ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдбреЗрдЯрд╛ рднреЗрдЬрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред

API + Signup.swift

 extension AuthController { struct SignupRequest: JSONPayload { let email, password: String let firstName, lastName, mobileNumber: String init(email: String, password: String, firstName: String, lastName: String, mobileNumber: String) { self.email = email self.password = password self.firstName = firstName self.lastName = lastName self.mobileNumber = mobileNumber } } struct SignupResponse: Codable { let token: String } static func signup(_ request: SignupRequest) -> APIRequest<SignupResponse> { return APIRequest("signup", payload: request).method(.post) .addError(.conflict, "Account already exists") } } 

рд▓реЙрдЧрд┐рди рдХреЗ рд╡рд┐рдкрд░реАрдд, рдкрдВрдЬреАрдХрд░рдг рдХреЗ рджреМрд░рд╛рди рд╣рдо рдмрдбрд╝реА рдорд╛рддреНрд░рд╛ рдореЗрдВ рдбреЗрдЯрд╛ рд╕рдВрдЪрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред

рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ SignupRequest рдореЙрдбрд▓ рд╣реИ рдЬреЛ JSONPayload рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИ (рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЛрдбреАрдлрд╝рд╛рдпрд░ рдкреЗрд▓реЛрдб рдкреНрд░рдХрд╛рд░ рдХреЛ рд╕рдордЭрддрд╛ рд╣реИ) рддрд╛рдХрд┐ рд╣рдорд╛рд░реЗ рдЕрдиреБрд░реЛрдз рдХрд╛ рдореБрдЦреНрдп рднрд╛рдЧ JSON рдХреЗ рд░реВрдк рдореЗрдВ рд╣реЛред рдпрджрд┐ рдЖрдкрдХреЛ x-www-form-urlencoded рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ FormURLEncodedPayload рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ ред

рдирддреАрдЬрддрди, рдЖрдкрдХреЛ рдПрдХ рд╕рд░рд▓ рдлрд╝рдВрдХреНрд╢рди рдорд┐рд▓рддрд╛ рд╣реИ рдЬреЛ рдкреЗрд▓реЛрдб рдореЙрдбрд▓ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ
 API.auth.signup(request) 

рдФрд░ рдЬреЛ рд╕рдлрд▓ рд╣реЛрдиреЗ рдкрд░ рдЖрдкрдХреЛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЙрдбрд▓ рд▓реМрдЯрд╛рдПрдЧрд╛ред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЕрдЪреНрдЫрд╛ рд╣реИ, рд╣реИ рдирд╛?

рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдорд▓реНрдЯреАрдкрд╛рд░реНрдЯ?


рдЖрдЗрдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВ рдЬрдм рдЖрдк рдкреЛрд╕реНрдЯ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред

рдкреЛрд╕реНрдЯ + Create.swift

 extension PostController { struct CreateRequest: MultipartPayload { var text: String var tags: [String] var images: [Attachment] var video: Data init (text: String, tags: [String], images: [Attachment], video: Data) { self.text = text self.tags = tags self.images = images self.video = video } } struct Post: Codable { let text: String let tags: [String] let linksToImages: [String] let linkToVideo: String } static func create(_ request: CreateRequest) -> APIRequest<CreateRequest> { return APIRequest("post", payload: request).method(.post) } } 

рдпрд╣ рдХреЛрдб рдЫрд╡рд┐ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рдФрд░ рдПрдХ рд╡реАрдбрд┐рдпреЛ рдХреЗ рд╕рд╛рде рдПрдХ рдорд▓реНрдЯреАрдкрд╛рд░реНрдЯ рдлреЙрд░реНрдо рднреЗрдЬрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдЧрд╛ред
рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдПрдХ рдкреНрд░реЗрд╖рдг рдХреИрд╕реЗ рдХреЙрд▓ рдХрд░реЗрдВред рдпрд╣рд╛рдВ рдЕрдЯреИрдЪрдореЗрдВрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рдХреНрд╖рдг рд╣реИред

 let videoData = FileManager.default.contents(atPath: "/path/to/video.mp4")! let imageAttachment = Attachment(data: UIImage(named: "cat")!.jpeg(.high)!, fileName: "cat.jpg", mimeType: .jpg) let payload = PostController.CreateRequest(text: "CodyFire is awesome", tags: ["codyfire", "awesome"], images: [imageAttachment], video: videoData) API.post.create(payload).onProgress { progress in print(" : \(progress)") }.onError { error in print(error.description) }.onSuccess { createdPost in print("  : \(createdPost)") } 

рдЕрдЯреИрдЪрдореЗрдВрдЯ рдПрдХ рдореЙрдбрд▓ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдбреЗрдЯрд╛ рдХреЗ рдЕрд▓рд╛рд╡рд╛ , рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рдФрд░ рдЗрд╕рдХреЗ рдорд╛рдЗрдорд╛рдЗрдк рдХреЛ рднреА рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдпрджрд┐ рдЖрдкрдиреЗ рдХрднреА рднреА Alamofire рдпрд╛ рдПрдХ рдирдЧреНрди URLRequest рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рд╕реНрд╡рд┐рдлреНрдЯ рд╕реЗ рдПрдХ рдорд▓реНрдЯреАрдкрд╛рд░реНрдЯ рдлреЙрд░реНрдо рдЬрдорд╛ рдХрд┐рдпрд╛ рд╣реИ , рддреЛ рдореБрдЭреЗ рдпрдХреАрди рд╣реИ рдХрд┐ рдЖрдк CodyFire рдХреА рд╕рд╛рджрдЧреА рдХреА рд╕рд░рд╛рд╣рдирд╛ рдХрд░реЗрдВрдЧреЗред

рдЕрдм рд╕рд░рд▓ рд▓реЗрдХрд┐рди GET рдХреЙрд▓ рдХрд╛ рдХреЛрдИ рдХрдо рд╢рд╛рдВрдд рдЙрджрд╛рд╣рд░рдг рдирд╣реАрдВ рд╣реИред

рдкреЛрд╕реНрдЯ + Get.swift

 extension PostController { struct ListQuery: Codable { let offset, limit: Int init (offset: Int, limit: Int) { self.offset = offset self.limit = limit } } static func get(_ query: ListQuery? = nil) -> APIRequest<[Post]> { return APIRequest("post").query(query) } static func get(id: UUID) -> APIRequest<Post> { return APIRequest("post/" + id.uuidString) } } 

рд╕рдмрд╕реЗ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рд╣реИ

 API.post.get(id:) 

рдЬреЛ onSuccess рдореЗрдВ рдкреЛрд╕реНрдЯ рдореЙрдбрд▓ рдЖрдкрдХреЛ рд▓реМрдЯрд╛ рджреЗрдЧрд╛ред

рдпрд╣рд╛рдБ рдПрдХ рдФрд░ рджрд┐рд▓рдЪрд╕реНрдк рдЙрджрд╛рд╣рд░рдг рд╣реИред

 API.post.get(PostController.ListQuery(offset: 0, limit: 100)) 

рдЬреЛ рдЗрдирдкреБрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╕реВрдЪрд┐рдмрджреНрдз рдореЙрдбрд▓ рд▓реЗрддрд╛ рд╣реИ,
рдЬреЛ APIRequest рдЕрдВрддрддрдГ рдлрд╝реЙрд░реНрдо рдХреЗ URL рдкрде рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ

 post?limit=0&offset=100 

рдФрд░ onSuccess рдореЗрдВ [рдкреЛрд╕реНрдЯ] рд╕рд░рдгреА рд▓реМрдЯрд╛рдПрдЧрд╛ред

рдмреЗрд╢рдХ, рдЖрдк рдкреБрд░рд╛рдиреЗ рддрд░реАрдХреЗ рд╕реЗ URL рдкрде рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрдм рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЖрдк рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХреЛрдбреЗрдмрд▓ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред

рдЕрдВрддрд┐рдо рдЙрджрд╛рд╣рд░рдг рдЕрдиреБрд░реЛрдз DELETE рд╣реЛрдЧрд╛

рдкреЛрд╕реНрдЯ + Delete.swift

 extension PostController { static func delete(id: UUID) -> APIRequest<Nothing> { return APIRequest("post/" + id.uuidString) .method(.delete) .desiredStatusCode(.noContent) } } 

рджреЛ рджрд┐рд▓рдЪрд╕реНрдк рдмрд┐рдВрджреБ рд╣реИрдВред

- рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ APIRequest рд╣реИ, рдпрд╣ рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░ рдХреБрдЫ рдирд╣реАрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдПрдХ рдЦрд╛рд▓реА рдХреЛрдбреЗрдмрд▓ рдореЙрдбрд▓ рд╣реИред
- рд╣рдордиреЗ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рдерд╛ рдХрд┐ рд╣рдо 204 NO CONTENT рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдХреЛрдбреАрдлрд╛рдпрд░ рдХреЗрд╡рд▓ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЕрд╕рдлрд▓ рдХреЙрд▓ рдХрд░реЗрдЧрд╛ред

рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдкрдиреЗ ViewController рд╕реЗ рдЗрд╕ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреИрд╕реЗ рдкрддрд╛ рд╣реИред

рд▓реЗрдХрд┐рди рджреЛ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ, рдкрд╣рд▓рд╛ onSuccess рдХреЗ рд╕рд╛рде, рдФрд░ рджреВрд╕рд░рд╛ рдмрд┐рдирд╛ред рд╣рдо рдЙрд╕реЗ рджреЗрдЦреЗрдВрдЧреЗ

 API.post.delete(id:).execute() 

рдпрд╣реА рд╣реИ, рдЕрдЧрд░ рдпрд╣ рдЖрдкрдХреЗ рд▓рд┐рдП рдорд╛рдпрдиреЗ рдирд╣реАрдВ рд░рдЦрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдЕрдиреБрд░реЛрдз рдмрд╛рд╣рд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рддреЛ рдЖрдк рдмрд╕ рдЗрд╕ рдкрд░ .execute () рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдпрд╣ рд╣реИ, рдЕрдиреНрдпрдерд╛ рдпрд╣ рд╣реИрдВрдбрд▓рд░ рдХреА рдЕрд╕рдлрд▓ рдШреЛрд╖рдгрд╛ рдХреЗ рдмрд╛рдж рд╢реБрд░реВ рд╣реЛрдЧрд╛ред

рдЙрдкрд▓рдмреНрдз рдХрд╛рд░реНрдп


рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдХрд╛ рдкреНрд░рд╛рдзрд┐рдХрд░рдг


рдХрд┐рд╕реА рднреА http-рд╣реЗрдбрд░ рдХреЗ рд╕рд╛рде рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдПрдкреАрдЖрдИ рдкрд░ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рд╣реИрдВрдбрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдЖрдк рдРрдкрдбреЗрд▓реЗрдЧреЗрдЯ рдореЗрдВ рдХрд╣реАрдВ рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдк рдХреНрд▓рд╛рд╕рд┐рдХ [рд╕реНрдЯреНрд░рд┐рдВрдЧ: рд╕реНрдЯреНрд░рд┐рдВрдЧ] рдпрд╛ рдХреЛрдбреЗрдмрд▓ рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдмрд┐рдпрд░рд░ рдХреЗ рд▓рд┐рдП рдЙрджрд╛рд╣рд░рдгред

1. рдХреЛрдбреЗрдмрд▓ (рдЕрдиреБрд╢рдВрд╕рд┐рдд)
 CodyFire.shared.fillCodableHeaders = { struct Headers: Codable { //NOTE:  nil,     headers var Authorization: String? var anythingElse: String } return Headers(Authorization: nil, anythingElse: "hello") } 

2. рдХреНрд▓рд╛рд╕рд┐рдХ [рд╕реНрдЯреНрд░рд┐рдВрдЧ: рд╕реНрдЯреНрд░рд┐рдВрдЧ]
 CodyFire.shared.fillHeaders = { guard let apiToken = LocalAuthStorage.savedToken else { return [:] } return ["Authorization": "Bearer \(apiToken)"] } 

рдЕрдиреБрд░реЛрдз рдкрд░ рдХреБрдЫ http-headers рдЬреЛрдбрд╝реЗрдВ


рдпрд╣ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрдм APIRequest рдмрдирд╛рддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:

 APIRequest("some/endpoint").headers(["someKey": "someValue"]) 

рдЕрдирдзрд┐рдХреГрдд рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдирд╛


рдЖрдк рдЙрдиреНрд╣реЗрдВ рд╡рд┐рд╢реНрд╡ рд╕реНрддрд░ рдкрд░ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП AppDelegate рдореЗрдВ

 CodyFire.shared.unauthorizedHandler = { //   WelcomeScreen } 

рдпрд╛ рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдореЗрдВ

 API.post.create(request).onNotAuthorized { //   } 

рдпрджрд┐ рдиреЗрдЯрд╡рд░реНрдХ рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИ


 API.post.create(request). onNetworkUnavailable { //   ,  ,     } 
рдЕрдиреНрдпрдерд╛ onrrror рдореЗрдВ рдЖрдкрдХреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рдорд┐рд▓рддреА рд╣реИ ред_notConnectedToInternet

рдЕрдиреБрд░реЛрдз рд╢реБрд░реВ рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдХреБрдЫ рд╢реБрд░реВ рдХрд░рдирд╛


рдЖрдк .onRequestStarted рдХреЛ рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рджрд┐рдЦрд╛рдирд╛ рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕рдореЗрдВ рд▓реЛрдбрд░ред
рдпрд╣ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЬрдЧрд╣ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕реЗ рдЗрдВрдЯрд░рдиреЗрдЯ рдХреА рдХрдореА рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЖрдкрдХреЛ рд▓реЛрдбрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡реНрдпрд░реНрде рдирд╣реАрдВ рджрд┐рдЦрд╛рдирд╛ рд╣реЛрдЧрд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдПред

рд╡рд┐рд╢реНрд╡ рд╕реНрддрд░ рдкрд░ рд▓реЙрдЧ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдЕрдХреНрд╖рдо / рд╕рдХреНрд╖рдо рдХреИрд╕реЗ рдХрд░реЗрдВ


 CodyFire.shared.logLevel = .debug CodyFire.shared.logLevel = .error CodyFire.shared.logLevel = .info CodyFire.shared.logLevel = .off 

рдХрд┐рд╕реА рдПрдХрд▓ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рд▓реЙрдЧ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдЕрдХреНрд╖рдо рдХреИрд╕реЗ рдХрд░реЗрдВ


 .avoidLogError() 

рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЕрдкрдиреЗ рддрд░реАрдХреЗ рд╕реЗ рд▓реЙрдЧ рдХрд░рддреА рд╣реИ


 CodyFire.shared.logHandler = { level, text in print("  CodyFire: " + text) } 

рд╕рд░реНрд╡рд░ рдХрд╛ рдЕрдкреЗрдХреНрд╖рд┐рдд http рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛрдб рдХреИрд╕реЗ рд╕реЗрдЯ рдХрд░реЗрдВ


рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдКрдкрд░ рдХрд╣рд╛ рдерд╛, рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, рдХреЛрдбреАрдлрд╛рдпрд░ рдХреЛ 200 рдУрдХреЗ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рдХреА рдЙрдореНрдореАрдж рд╣реИ , рдФрд░ рдпрджрд┐ рдРрд╕рд╛ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдбреЗрдЯрд╛ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрддрд╛ рд╣реИ рдФрд░ рдСрдирд╕реНрдХрд╛рдЙрдЯ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред

рд▓реЗрдХрд┐рди рдЕрдкреЗрдХреНрд╖рд┐рдд рдХреЛрдб рдХреЛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдПрдиреБрдо рдХреЗ рд░реВрдк рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 201 рдХреЗ рд▓рд┐рдП

 .desiredStatusCode(.created) 

рдпрд╛ рдЖрдк рдХрд╕реНрдЯрдо рдЕрдкреЗрдХреНрд╖рд┐рдд рдХреЛрдб рднреА рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ

 .desiredStatusCode(.custom(777)) 

рдЕрдиреБрд░реЛрдз рд░рджреНрдж рдХрд░реЗрдВ


 .cancel() 

рдФрд░ рдЖрдк рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ .onCancellation рд╣реИрдВрдбрд▓рд░ рдШреЛрд╖рд┐рдд рдХрд░рдХреЗ рдЕрдиреБрд░реЛрдз рд░рджреНрдж рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛

 .onCancellation { //   } 

рдЕрдиреНрдпрдерд╛ рдСрдирд░рд░ рдХреЛ рдЙрдард╛рдпрд╛ рдЬрд╛рдПрдЧрд╛

рдПрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдордп рд╕реАрдорд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛


 .responseTimeout(30) //   30  

рд╣реИрдВрдбрд▓рд░ рдХреЛ рдЯрд╛рдЗрдордЖрдЙрдЯ рдЗрд╡реЗрдВрдЯ рдореЗрдВ рднреА рд▓рдЯрдХрд╛ рджрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ

 . onTimeout { //    } 

рдЕрдиреНрдпрдерд╛ рдСрдирд░рд░ рдХреЛ рдЙрдард╛рдпрд╛ рдЬрд╛рдПрдЧрд╛

рдЗрдВрдЯрд░рдПрдХреНрдЯрд┐рд╡ рдПрдХреНрд╕реНрдЯреНрд░рд╛ рдЯрд╛рдЗрдордЖрдЙрдЯ рд╕реЗрдЯ рдХрд░рдирд╛


рдпрд╣ рдореЗрд░реА рдкрд╕рдВрджреАрджрд╛ рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реИред рдпреВрдПрд╕рдП рдХреЗ рдПрдХ рдЧреНрд░рд╛рд╣рдХ рдиреЗ рдПрдХ рдмрд╛рд░ рдореБрдЭрд╕реЗ рдЙрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкреВрдЫрд╛ рдерд╛, рдХреНрдпреЛрдВрдХрд┐ рдЙрдиреНрд╣реЗрдВ рдпрд╣ рдкрд╕рдВрдж рдирд╣реАрдВ рдерд╛ рдХрд┐ рд▓реЙрдЧрд┐рди рдлрд╝реЙрд░реНрдо рдмрд╣реБрдд рддреЗрдЬрд╝реА рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЙрдирдХреА рд░рд╛рдп рдореЗрдВ рдпрд╣ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рдирд╣реАрдВ рд▓рдЧрддрд╛, рдЬреИрд╕реЗ рдХрд┐ рдпрд╣ рдПрдХ рдирдХрд▓реА рдерд╛, рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдирд╣реАрдВред

рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рд╡рд╣ рдИрдореЗрд▓ / рдкрд╛рд╕рд╡рд░реНрдб рдХреА рдЬрд╛рдВрдЪ рдкрд┐рдЫрд▓реЗ 2 рд╕реЗрдХрдВрдб рдпрд╛ рдЕрдзрд┐рдХ рд╕рдордп рддрдХ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред рдФрд░ рдЕрдЧрд░ рдпрд╣ рдХреЗрд╡рд▓ 0.5 рд╕реЗрдХрдВрдб рддрдХ рд░рд╣рддрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдПрдХ рдФрд░ 1.5 рдлреЗрдВрдХрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рд╣реА рдСрдирд╕реНрдХреНрдпреВ рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВред рдФрд░ рдЕрдЧрд░ рдЗрд╕рдореЗрдВ рдареАрдХ 2 рдпрд╛ 2.5 рд╕реЗрдХрдВрдб рдХрд╛ рд╕рдордп рд▓рдЧрддрд╛ рд╣реИ, рддреЛ рддреБрд░рдВрдд onSuccess рдкрд░ рдХреЙрд▓ рдХрд░реЗрдВред

 .additionalTimeout(2) // 2     

рдХрд╕реНрдЯрдо рджрд┐рдирд╛рдВрдХ рдПрдирдХреЛрдбрд░ / рдбрд┐рдХреЛрдбрд░


CodyFire рдХреА рдЕрдкрдиреА DateCodingStrategy рдПрдирдо рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рддреАрди рдорд╛рди рд╣реИрдВ

- secondsSince1970
- рдорд┐рд▓реАрд╕реЗрдХрдВрдбрд╕рдВрд╕ 1970
- рд╕реНрд╡рд░реВрдкрд┐рдд (_ customDateFormatter: DateFormatter)

DateCodingStrategy рдХреЛ рддреАрди рддрд░реАрдХреЛрдВ рд╕реЗ рдФрд░ рдЕрд▓рдЧ рд╕реЗ рдбрд┐рдХреЛрдбрд┐рдВрдЧ рдФрд░ рдПрдиреНрдХреЛрдбрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ
- рд╡рд┐рд╢реНрд╡ рд╕реНрддрд░ рдкрд░ AppDelegate рдореЗрдВ

 CodyFire.shared.dateEncodingStrategy = .secondsSince1970 let customDateFormatter = DateFormatter() CodyFire.shared.dateDecodingStrategy = .formatted(customDateFormatter) 

- рдПрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП

 APIRequest("some/endpoint") .dateDecodingStrategy(.millisecondsSince1970) .dateEncodingStrategy(.secondsSince1970) 

- рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ рд╕реЗ, рдЖрдкрдХреЛ рдмрд╕ CustomDateEncodingStrategy рдФрд░ / рдпрд╛ CustomDateDecodingStrategy рд╕реЗ рдорд┐рд▓рд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореЙрдбрд▓ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

 struct SomePayload: JSONPayload, CustomDateEncodingStrategy, CustomDateDecodingStrategy { var dateEncodingStrategy: DateCodingStrategy var dateDecodingStrategy: DateCodingStrategy } 

рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдХреИрд╕реЗ рдЬреЛрдбрд╝реЗрдВ


рдкреБрд╕реНрддрдХрд╛рд▓рдп MIT рд▓рд╛рдЗрд╕реЗрдВрд╕ рдХреЗ рддрд╣рдд GitHub рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИред

рдЗрдВрд╕реНрдЯреЙрд▓реЗрд╢рди рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдХреЗрд╡рд▓ CocoaPods рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрдкрд▓рдмреНрдз рд╣реИ
 pod 'CodyFire' 


рдореБрдЭреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдХреЛрдбреАрдлрд╛рдпрд░ рдЕрдиреНрдп рдЖрдИрдУрдПрд╕ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛, рдпрд╣ рдЙрдирдХреЗ рд▓рд┐рдП рд╡рд┐рдХрд╛рд╕ рдХреЛ рд╕рд░рд▓ рдХрд░реЗрдЧрд╛, рдФрд░ рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░ рджреБрдирд┐рдпрд╛ рдХреЛ рдереЛрдбрд╝рд╛ рдмреЗрд╣рддрд░ рдФрд░ рд▓реЛрдЧреЛрдВ рдХреЛ рджрдпрд╛рд▓реБ рдмрдирд╛ рджреЗрдЧрд╛ред

рдпрд╣ рд╕рдм, рдЖрдкрдХреЗ рд╕рдордп рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред

UPD: ReactiveCocoa рдФрд░ RxSwift рдХрд╛ рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛
 pod 'ReactiveCodyFire' # ReactiveCocoa pod 'RxCodyFire' # RxSwift #      'CodyFire',     

ReactiveCoca рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ .signalProducer , рдФрд░ RxSwwobservable рдХреЗ рд▓рд┐рдПред

UPD2: рдЕрдм рдЖрдк рдХрдИ рдЕрдиреБрд░реЛрдз рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ
рдпрджрд┐ рдЖрдкрдХреЗ рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рд╢реНрди рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рддреЛ .and () рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
рдЗрд╕ рдореЛрдб рдореЗрдВ рдЕрдзрд┐рдХрддрдо, рдЖрдк 10 рдЕрдиреБрд░реЛрдз рддрдХ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрдиреНрд╣реЗрдВ рдПрдХ рдХреЗ рдмрд╛рдж рдПрдХ рд╕рдЦреНрддреА рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
 API.employee.all() .and(API.office.all()) .and(API.car.all()) .and(API.event.all()) .and(API.post.all()) .onError { error in print(error.description) }.onSuccess { employees, offices, cars, events, posts in //    !!! } 

onRequestStarted, onNetworkUnavailable, onCancellation, onNotAuthorized, onTimeout рднреА рдЙрдкрд▓рдмреНрдз рд╣реИрдВред
onProgress - рдЕрднреА рднреА рд╡рд┐рдХрд╛рд╕ рдореЗрдВ

рдпрджрд┐ рдЖрдк рдЕрдкрдиреЗ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк .flatten () рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
 [API.employee.all(), API.office.all(), API.car.all()].flatten().onError { print(error.description) }.onSuccess { print("flatten finished!") } 
рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╕ .concurrent (рджреНрд╡рд╛рд░рд╛: 3) рдпрд╣ рддреАрди рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдПрдХ рд╕рд╛рде рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛, рдХрд┐рд╕реА рднреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдЕрд╕рдлрд▓ рдХреНрд╡реЗрд░реА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП .avoidCancelOnError ()
рдкреНрд░рдЧрддрд┐ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, .onProgress рдЬреЛрдбрд╝реЗрдВ

UPD3: рдЕрдм рдЖрдк рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рд╕рд░реНрд╡рд░ рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
рдХрд╣реАрдВ рдЖрд╡рд╢реНрдпрдХ рд╕рд░реНрд╡рд░ рдкрддреЗ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП
 let server1 = ServerURL(base: "https://server1.com", path: "v1") let server2 = ServerURL(base: "https://server2.com", path: "v1") let server3 = ServerURL(base: "https://server3.com") 
рдФрд░ рдЕрдм рдЖрдк рдПрдВрдбрдкреЙрдЗрдВрдЯ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЕрдиреБрд░реЛрдз рдХреЗ рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ рдЙрдирдХрд╛ рд╕рд╣реА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
 APIRequest(server1, "endpoint", payload: payloadObject) APIRequest(server2, "endpoint", payload: payloadObject) APIRequest(server3, "endpoint", payload: payloadObject) 
рдпрд╛ рдЖрдк рдЕрдиреБрд░реЛрдз рдХреЛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╕рд░реНрд╡рд░ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
 APIRequest("endpoint", payload: payloadObject).serverURL(server1) 

Source: https://habr.com/ru/post/hi427937/


All Articles