Slide 1

Slide 1 text

iOSͰ௨৴ॲཧΛ؆ܿʹॻ͘ 2018/12/25 ΫϦϘονΛٹ͏ձɻ PKPK-Carnage

Slide 2

Slide 2 text

About me • iOSྺ2೥ͪΐͬͱ • খֶੜ͔ΒͣͬͱΞϝίϛ͕޷͖ • Qiita → @PKPK-Carnage • Github → PKPK-Carnage • Twitter → @PKPK-Carnage

Slide 3

Slide 3 text

౦ژίϛίϯʹߦ͖ͬͯ·ͨ͠

Slide 4

Slide 4 text

౦ژίϛίϯʹߦ͖ͬͯ·ͨ͠

Slide 5

Slide 5 text

͜Ε͚ͩΞϝίϛ͕ਓؾʹͳͬͨͷʹɺ Ͳ͏ͯࣗ͠෼͸ҰਓͰίϛίϯʹ͍ΔΜͩɾɾɾ

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Marvel APIͰΞϓϦΛ࡞Ε͹ɺ ΅ͬͪΛճආͰ͖ΔͷͰ͸ʂʁ

Slide 8

Slide 8 text

Marvel APIͬͯͳΜͩʁ • MarvelͷίϛοΫʹؔ͢Δ৘ใΛऔಘͰ͖ΔWebAPI • ৄ͘͠͸Qiitaʹهࣄॻ͖·ͨ͠(એ఻)

Slide 9

Slide 9 text

௨৴ॲཧΛ࡞Δ • Swift4.2Λ࢖༻ • ϑϨʔϜϫʔΫ(Alamofire)Λ࢖༻ • CodableͰjsonΛύʔε͢Δ

Slide 10

Slide 10 text

௨৴ॲཧΛ࡞Δ • Swift4.2Λ࢖༻ • ϑϨʔϜϫʔΫ(Alamofire)Λ࢖༻ • CodableͰjsonΛύʔε͢Δ • ग़དྷΔ͚ͩ؆ܿʹॻ͘ʂ

Slide 11

Slide 11 text

ͱΓ͋͑ͣॻ͍ͯΈΔɻ import Alamofire class APIManager { static func request(urlString: String, parameter: [String: Any], success: @escaping (Data) -> Void, failure: @escaping (Error) -> Void) { // ڞ௨URLΛ݁߹ let url = "https://gateway.marvel.com/v1/public/\(urlString)" // ௨৴Λߦ͏ Alamofire.request(url, parameters: parameter).responseData { response in switch response.result { case .success(let data): success(data) case .failure(let error): failure(error) } } } }

Slide 12

Slide 12 text

ͱΓ͋͑ͣॻ͍ͯΈΔɻ extension APIManager { // ΩϟϥΫλʔͷҰཡΛऔಘ͢ΔAPI static func characterList(parameter: CharacterListRequest, success: @escaping (CharacterListResponse) -> Void, failure: @escaping (Error) -> Void) { self.request(urlString: "characters", parameter: parameter.dict, success: { data in do { let data = try JSONDecoder().decode(CharacterListResponse.self, from: data) success(data) } catch { failure(error) } }, failure: failure) } }

Slide 13

Slide 13 text

ͱΓ͋͑ͣॻ͍ͯΈΔɻ

Slide 14

Slide 14 text

ͱΓ͋͑ͣॻ͍ͯΈΔɻ extension APIManager { // ΩϟϥΫλʔͷҰཡΛऔಘ͢ΔAPI static func characterList(parameter: CharacterListRequest, success: @escaping (CharacterListResponse) -> Void, failure: @escaping (Error) -> Void) { self.request(urlString: “characters", parameter: parameter.dict, success: { data in do { let data = try JSONDecoder().decode(CharacterListResponse.self, from: data) success(data) } catch { failure(error) } }, failure: failure) } }

Slide 15

Slide 15 text

ͱΓ͋͑ͣॻ͍ͯΈΔɻ 15 extension APIManager { // ίϛοΫͷҰཡΛऔಘ͢ΔAPI static func comicList(parameter: ComicListRequest, success: @escaping (ComicListResponse) -> Void, failure: @escaping (Error) -> Void) { self.request(urlString: "comics", parameter: parameter.dict, success: { data in do { let data = try JSONDecoder().decode(ComicListResponse.self, from: data) success(data) } catch { failure(error) } }, failure: failure) } } extension APIManager { // ΠϕϯτͷҰཡΛऔಘ͢ΔAPI static func eventList(parameter: EventListRequest, success: @escaping (EventListResponse) -> Void, failure: @escaping (Error) -> Void) { extension APIManager { // ΩϟϥΫλʔͷҰཡΛऔಘ͢ΔAPI static func characterList(parameter: CharacterListRequest, success: @escaping (CharacterListResponse) -> Void, failure: @escaping (Error) -> Void) { self.request(urlString: “characters", parameter: parameter.dict, success: { data in do { let data = try JSONDecoder().decode(CharacterListResponse.self, from: data) success(data) } catch { failure(error) } }, failure: failure) } }

Slide 16

Slide 16 text

શવ؆ܿʹॻ͚ͯͳ͍

Slide 17

Slide 17 text

֤API͝ͱʹϝιουΛॻ͔ͣʹɺڞ௨Խ͠Α͏

Slide 18

Slide 18 text

enumͱprotocolΛ׆༻͢Δ

Slide 19

Slide 19 text

ProtocolΛ࡞੒͢Δ protocol APIType { var url: String { get } var parameter: [String: Any] { get } } ֤API͝ͱʹඞཁͳϦΫΤετ৘ใΛऔಘ͢ΔͨΊͷProtocolΛ࡞੒͢Δ

Slide 20

Slide 20 text

ҎԼͷೋͭͷAPIͰenumΛ࡞ͬͯΈΔ

Slide 21

Slide 21 text

enumΛ࡞੒͢Δ struct APITypes { private static let baseURL = "http://gateway.marvel.com/v1/public/" enum Character { case list(CharacterListRequest) case comics(CharacterComicListRequest) } }

Slide 22

Slide 22 text

enumΛ࡞੒͢Δ struct APITypes { private static let baseURL = "http://gateway.marvel.com/v1/public/" enum Character: APIType { case list(CharacterListRequest) case comics(CharacterComicListRequest) var url: String { let characterURL = "characters" switch self { case .list: return APITypes.baseURL + characterURL case .comics(let request): return APITypes.baseURL + “\(characterURL)/\(request.id)/comics” } } var parameter: [String : Any] { switch self { case .list(let request): return request.dict case .comics(let request): return request.dict } } } }

Slide 23

Slide 23 text

࠷ॳ͜͏ͩͬͨڞ௨ϦΫΤετͷॲཧ͕ɾɾɾ import Alamofire class APIManager { static func request(urlString: String, parameter: [String: Any], success: @escaping (Data) -> Void, failure: @escaping (Error) -> Void) { // ڞ௨URLΛ݁߹ let url = "https://gateway.marvel.com/v1/public/\(urlString)" // ௨৴Λߦ͏ Alamofire.request(url, parameters: parameter).responseData { response in switch response.result { case .success(let data): success(data) case .failure(let error): failure(error) } } } }

Slide 24

Slide 24 text

͜͏ͳΔ import Alamofire class APIManager { static func request(type: APIType, success: @escaping (Data) -> Void, failure: @escaping (Error) -> Void) { // ௨৴Λߦ͏ Alamofire.request(type.url, parameters: type.parameter).responseData { response in switch response.result { case .success(let data): success(data) case .failure(let error): failure(error) } } } }

Slide 25

Slide 25 text

֤API͝ͱͷϝιου͕ɾɾɾ 25 extension APIManager { // ίϛοΫͷҰཡΛऔಘ͢ΔAPI static func comicList(parameter: ComicListRequest, success: @escaping (ComicListResponse) -> Void, failure: @escaping (Error) -> Void) { self.request(urlString: "comics", parameter: parameter.dict, success: { data in do { let data = try JSONDecoder().decode(ComicListResponse.self, from: data) success(data) } catch { failure(error) } }, failure: failure) } } extension APIManager { // ΠϕϯτͷҰཡΛऔಘ͢ΔAPI static func eventList(parameter: EventListRequest, success: @escaping (EventListResponse) -> Void, extension APIManager { // ΩϟϥΫλʔͷҰཡΛऔಘ͢ΔAPI static func characterList(parameter: CharacterListRequest, success: @escaping (CharacterListResponse) -> Void, failure: @escaping (Error) -> Void) { self.request(urlString: “characters", parameter: parameter.dict, success: { data in do { let data = try JSONDecoder().decode(CharacterListResponse.self, from: data) success(data) } catch { failure(error) } }, failure: failure) } }

Slide 26

Slide 26 text

ඞཁແ͘ͳΔʂ

Slide 27

Slide 27 text

࣮ࡍʹAPIΛୟ͘ͱ͜Μͳײ͡ // ΩϟϥΫλʔͷҰཡΛऔಘ͢Δ func fetchCharacterListData(parameters: CharacterListRequest) { APIManager.request(type: APITypes.Character.list(parameters), success: { data in do { let response = try JSONDecoder().decode(CharacterListResponse.self, from: data) // ௨৴&σίʔυ੒ޭ࣌ͷॲཧ } catch { // σίʔυΤϥʔ࣌ͷॲཧ } }, failure: { error in // ௨৴Τϥʔ࣌ͷॲཧ }) } // ΩϟϥΫλʔ͝ͱͷίϛοΫҰཡΛऔಘ͢Δ func fetchCharacterComicListData(_ parameters: CharacterComicListRequest) { APIManager.request(type: APITypes.Character.comics(parameters), success: { data in do { let response = try JSONDecoder().decode(CharacterComicListResponse.self, from: data) // ௨৴&σίʔυ੒ޭ࣌ͷॲཧ } catch { // σίʔυΤϥʔ࣌ͷॲཧ } }, failure: { error in // ௨৴Τϥʔ࣌ͷॲཧ }) }

Slide 28

Slide 28 text

͋Εɾɾɾʁ // ΩϟϥΫλʔͷҰཡΛऔಘ͢Δ func fetchCharacterListData(parameters: CharacterListRequest) { APIManager.request(type: APITypes.Character.list(parameters), success: { data in do { let response = try JSONDecoder().decode(CharacterListResponse.self, from: data) // ௨৴&σίʔυ੒ޭ࣌ͷॲཧ } catch { // σίʔυΤϥʔ࣌ͷॲཧ } }, failure: { error in // ௨৴Τϥʔ࣌ͷॲཧ }) } // ΩϟϥΫλʔ͝ͱͷίϛοΫҰཡΛऔಘ͢Δ func fetchCharacterComicListData(_ parameters: CharacterComicListRequest) { APIManager.request(type: APITypes.Character.comics(parameters), success: { data in do { let response = try JSONDecoder().decode(CharacterComicListResponse.self, from: data) // ௨৴&σίʔυ੒ޭ࣌ͷॲཧ } catch { // σίʔυΤϥʔ࣌ͷॲཧ } }, failure: { error in // ௨৴Τϥʔ࣌ͷॲཧ }) }

Slide 29

Slide 29 text

ϨεϙϯεͷσίʔυॲཧΛ ຖճॻ͔͞ΕͯΔ

Slide 30

Slide 30 text

֤Ϩεϙϯε͝ͱʹσίʔυॲཧΛॻ͔ͣʹɺڞ௨Խ͠Α͏

Slide 31

Slide 31 text

GenericsΛ׆༻͢Δ

Slide 32

Slide 32 text

GenericsΛద༻͢Δ import Alamofire class APIManager { static func request(type: APIType, success: @escaping (Data) -> Void, failure: @escaping (Error) -> Void) { // ௨৴Λߦ͏ Alamofire.request(type.url, parameters: type.parameter).responseData { response in switch response.result { case .success(let data): success(data) case .failure(let error): failure(error) } } } }

Slide 33

Slide 33 text

GenericsΛద༻͢Δ import Alamofire class APIManager { static func request(type: APIType, success: @escaping (T) -> Void, failure: @escaping (Error) -> Void) { // ௨৴Λߦ͏ Alamofire.request(type.url, parameters: type.parameter).responseData { response in switch response.result { case .success(let data): do { let decodedData = try JSONDecoder().decode(T.self, from: data) success(decodedData) } catch { failure(error) } case .failure(let error): failure(error) } } } }

Slide 34

Slide 34 text

σίʔυ͕ڞ௨Խ͞ΕΔͱɾɾɾ // ΩϟϥΫλʔͷҰཡΛऔಘ͢Δ func fetchCharacterListData(parameters: CharacterListRequest) { APIManager.request(type: APITypes.Character.list(parameters), success: { data in do { let response = try JSONDecoder().decode(CharacterListResponse.self, from: data) // ௨৴&σίʔυ੒ޭ࣌ͷॲཧ } catch { // σίʔυΤϥʔ࣌ͷॲཧ } }, failure: { error in // ௨৴Τϥʔ࣌ͷॲཧ }) } // ΩϟϥΫλʔ͝ͱͷίϛοΫҰཡΛऔಘ͢Δ func fetchCharacterComicListData(_ parameters: CharacterComicListRequest) { APIManager.request(type: APITypes.Character.comics(parameters), success: { data in do { let response = try JSONDecoder().decode(CharacterComicListResponse.self, from: data) // ௨৴&σίʔυ੒ޭ࣌ͷॲཧ } catch { // σίʔυΤϥʔ࣌ͷॲཧ } }, failure: { error in // ௨৴Τϥʔ࣌ͷॲཧ }) }

Slide 35

Slide 35 text

͜͏ͳΔ // ΩϟϥΫλʔͷҰཡΛऔಘ͢Δ func fetchCharacterListData(parameters: CharacterListRequest) { APIManager.request(type: APITypes.Character.list(parameters), success: { data in // ੒ޭ࣌ͷॲཧ(data = CharacterListResponse) }, failure: { error in // ௨৴Τϥʔ΍σίʔυΤϥʔ࣌ͷॲཧ }) } // ΩϟϥΫλʔ͝ͱͷίϛοΫҰཡΛऔಘ͢Δ func fetchCharacterComicListData(_ parameters: CharacterComicListRequest) { APIManager.request(type: APITypes.Character.comics(parameters), success: { data in // ੒ޭ࣌ͷॲཧ(data = CharacterComicListResponse) }, failure: { error in // ௨৴Τϥʔ΍σίʔυΤϥʔ࣌ͷॲཧ }) }

Slide 36

Slide 36 text

Slide 37

Slide 37 text

·ͱΊ • ϦΫΤετͷ੾Γ෼͚͸enumͱprotocolͰ؅ཧͰ͖Δ • Ϩεϙϯεͷσίʔυ͸GenericsͰڞ௨Խग़དྷΔ • ΫϦεϚε·ͰʹMarvelͷΞϓϦΛ࡞Γ্͛Δ͜ͱ͕Ͱ͖ͳ ͔ͬͨͷͰ͜͜Ͱൃද͍ͯ͠Δ

Slide 38

Slide 38 text

͓͠·͍