iOSDC 2023 のパンフレット原稿です。
Zenn により詳しい記事を書いているので、あわせてご覧ください。🤗 https://zenn.dev/kamimi01/scraps/ddad5212081b1a
͡ΊΑ͏ʂ4XJGU0QFO"1*(FOFSBUPSʹΑΔεΩʔϚۦಈ։ൃɿಋೖखॱͱ׆༻ͷίπ88%$Ͱ4XJGUಛԽͷ(FOFSBUPSɺ4XJGU0QFO"1*(FOFSBUPS͕ൃද͞Ε·ͨ͠ɻ4XJGU1BDLBHFQMVHJOͱͯ͠ఏڙ͞Εͨ͜ͱͰίʔυͷੜ͔Βར༻Λɺ9DPEFΛΕΔ͜ͱͳ͘εϜʔζʹߦ͑·͢ɻຊߘͰ4XJGU0QFO"1*(FOFSBUPSͷಋೖखॱ׆༻ͷίπΛ࣮ࡍͷίʔυΛަ͑ͯ͝հ͠·͢ɻ0QFO"1*ʹ͍ͭͯ 0QFO"1*4QFDJfiDBUJPOʢ0"4ʣɺ)551"1*ͷΠϯλʔϑΣʔεఆٛͰ͢ɻαʔόʔαΠυͱͷ༷ͷೝࣝ߹Θͤʹ͍ͬͯ͜ͰɺυΩϡϝϯτίʔυੜͳͲΤίγεςϜॆ࣮͍ͯ͠·͢ɻ:".-+40/ܗࣜͰ"1*ͷ༷Λهࡌ͢Δ͜ͱ͕Ͱ͖·͢ɻ4XJGU0QFO"1*(FOFSBUPSͱ 88%$Ͱ4XJGUಛԽͷ(FOFSBUPSɺ4XJGU0QFO"1*(FOFSBUPS͕ൃද͞Ε·ͨ͠ɻ4XJGU1BDLBHFQMVHJOͱͯ͠ఏڙ͞Εͨ͜ͱͰίʔυͷੜ͔Βར༻Λɺ9DPEFΛΕΔ͜ͱͳ͘εϜʔζʹߦ͏͜ͱ͕Ͱ͖·͢ɻ4XJGU1BDLBHFQMVHJOɺࡢͷ88%$Ͱൃද͞Εͨ4XJGU1BDLBHF·ͨ9DPEF্Ͱಈ͘4XJGUεΫϦϓτͰ͢ɻࠓ·ͰΞϓϦଆͰ#VJME1IBTFTͰ3VO4DSJQUΛ࣮ߦ͢Δ͜ͱ͕Ͱ͖·͕ͨ͠ɺ4XJGU1BDLBHFͰϏϧυલϏϧυதʹ࣮ߦ͢ΔॲཧΛఆٛͰ͖·ͤΜͰͨ͠ɻQMVHJOͷηογϣϯͰϢʔεέʔεͱͯ͠ɺίʔυੜϦϦʔε࡞ۀͷࣗಈԽͳͲ͕հ͞Ε͍ͯ·ͨ͠ɻࠓճͷ4XJGU0QFO"1*(FOFSBUPSͷొͰɺࡢͷൃද͜ͷͨΊͩͬͨͷ͔ͱ͕ઢʹͳΔײ֮ΛຯΘ͍·ͨ͠ɻ4XJGU1BDLBHF(FOFSBUPS0QFO"1*5PPMT͕ఏڙ͍ͯ͠Δ0QFO"1*(FOFSBUPSͳͲଞͷࣗಈੜπʔϧͱൺֱ͢Δͱಋೖར༻ͷख͕ܰ͞ϝϦοτͰ͢ɻ࣮ࡍʹͬͯΈΔ ࠓճΫϥΠΞϯτίʔυͷੜɺͭ·ΓJ04ΞϓϦͰ༻͞ΕΔ4XJGUίʔυͷੜΛߦ͍·͢ɻαʔόʔαΠυͰ༻͢Δ4XJGUίʔυͷੜՄೳͰ͕͢ɺࢴ໘ͷ߹্ׂѪ͠·͢ɻಋೖฤ kamimi / ͔ΈΈ(גࣜձࣾϠϓϦ)Twitterɿ@kamimi_01GitHubɿ@kamimi01
View Slide
1BDLBHF%FQFOEFODJFTʹ̏ͭͷґଘؔΛՃ͢Δͭ4XJGU1BDLBHF(FOFSBUPSຊମͰ͢ɻ࣮ࡍʹίʔυΛੜ͢ΔͨΊͷϩδοΫ͕࣮͞Ε͍ͯ·͢ɻIUUQTHJUIVCDPNBQQMFTXJGUPQFOBQJHFOFSBUPSͭ4XJGU0QFO"1*3VOUJNFͰ͢ɻੜ͞Εͨίʔυ͔Β༻͞ΕΔڞ௨ͷܕநԽΛఏڙ͍ͯ͠·͢ɻIUUQTHJUIVCDPNBQQMFTXJGUPQFOBQJSVOUJNFͭ4XJGU0QFO"1*63-4FTTJPOͰ͢ɻੜ͞Εͨίʔυಛఆͷ)551ΫϥΠΞϯτϥΠϒϥϦʹґଘ͍ͯ͠ͳ͍ͷͰɺඥ͚͍ͨϥΠϒϥϦΛબ͢Δ͜ͱ͕Ͱ͖·͢ɻࠓճJ04ΞϓϦͷΫϥΠΞϯτίʔυΛੜ͢ΔͷͰ͜ΕΛબͼ·͢ɻIUUQTHJUIVCDPNBQQMFTXJGUPQFOBQJVSMTFTTJPO#VJME1IBTFTʹॲཧΛՃ͢Δ࣍ʹ#VJME1IBTFTͷ3VO#VJME5PPM1MVHJOTʹɺ0QFO"1*(FOFSBUPSΛՃ͠·͢ɻ͜ΕͰίʔυͷੜ͕ίϯύΠϧͷલʹߦΘΕ·͢ɻ0QFO"1*ͷυΩϡϝϯτ̎ͭΛՃ͢Δ࣍ʹίʔυੜͷͨΊͷॏཁͳ̎ͭͷυΩϡϝϯτΛϓϩδΣΫτʹՃ͠·͢ɻͭɺ:".-·ͨ+40/ܗࣜͷ0QFO"1*υΩϡϝϯτͰ͢ɻͭɺPQFOBQJHFOFSBUPSDPOfiHZBNMͰ͢ɻ͜ΕʹҎԼͷΑ͏ʹੜ͢ΔίʔυͷछྨΛఆٛ͠·͢ɻQMVHJOΛ৴པ͢ΔॳΊͯQMVHJOΛ༻͢Δͱ͖ɺ9DPEF্ͰҎԼͷը໘͕දࣔ͞ΕΔͷͰʮ5SVTU&OBCMF"MMʯΛબ͠·͢ɻϏϧυ͢Δ͜͜·Ͱྃͨ͠ΒϏϧυ͠·͢ɻϏϧυϩάΛ֬ೝ͢Δͱɺ(FOFSBUPS͕ͲͷΑ͏ͳઃఆͰίʔυੜ·Ͱߦ͓͏ͱ͍ͯ͠Δ͔͕Θ͔Γ·͢ɻ0QFO"1*υΩϡϝϯτͷఆ͕ٛਖ਼͘͠ͳ͍߹ඞཁͳϑΝΠϧ͕ଘࡏ͠ͳ͍ͱ͍ͬͨ͜ͱ͕ݪҼͰϏϧυΤϥʔʹͳͬͨ߹ɺϩάΛ֬ೝ͢Δ͜ͱͰσόοά͕ḿΓ·͢ɻgenerate:- types- client
·ͨίʔυ%FSJWFE%BUBʹੜ͞ΕΔͨΊɺHJUJHOPSFʹؚΊΔͳͲ͢Δඞཁ͋Γ·ͤΜɻ͜ΕͰಋೖྃͰ͢ʂQMVHJOͰఏڙ͞Ε͍ͯΔ͜ͱʹΑΓɺ9DPEFΛΕΔ͜ͱͳ͘εϜʔζʹಋೖͰ͖·ͨ͠ɻίʔυར༻ฤ ·ͣඞཁͳϞδϡʔϧΛΠϯϙʔτ͠·͢ɻ࣍ʹੜ͞Εͨίʔυ͕ఏڙ͢Δ$MJFOUͱ͍͏ܕΛੜ͠·͢ɻ͜͜ͰҾʹαʔόʔͷ63-ͱ࣮ࡍʹωοτϫʔΫΛ༻ͯ͠)551ૢ࡞Λߦ͏)551ϥΠϒϥϦΛ͠·͢ɻ$MJFOU"1*1SPUPDPMʹ४ڌ͓ͯ͠Γɺ͜ͷͭҎ֎ʹड͚औΕΔҾ͕͋Γ·͢ɻଞͷҾʹ͍ͭͯޙड़͠·͢ɻࣗಈੜʹΑͬͯ0QFO"1*υΩϡϝϯτͷQBUITͰఆٛͨ͠ϝιουʢ͜͜ͰUFYU$PNQMFUJPOTϝιουʣ͕ੜ͞Ε͍ͯΔͷͰɺͦΕΛݺͼग़͠·͢ɻࠓճݺͼ͍ͨ"1*1045ϝιουͰϦΫΤετϘςΟ͕ଘࡏ͢ΔͷͰҾʹ͍ͯ͠·͢ɻ͜͜Ͱলུ͠·͕͢ɺྫ֎Λ͛Δ͜ͱ͕͋ΔͷͰ࣮ࡍEPDBUDIจΛ༻͢ΔͳͲ͍ͯͩ͘͠͞ɻ࣍ʹϨεϙϯεͷॲཧͰ͢ɻϨεϙϯεɺFOVNͰ࣮͞Ε͍ͯ·͢ɻTXJUDIจͰέʔε͝ͱʹॲཧΛ͍͖ͯ͠·͢ɻ࣮͜ΕͰྃͰ͢ʂҾ͔͔ͬͬͨϙΠϯτ 4XJGU0QFO"1*(FOFSBUPSʹҙ͖͢ϙΠϯτ͕ෳ͋Γ·͢ɻ࣮ࡍʹ໘ͨͭ͠Λհ͠·͢ɻ ϙΠϯτ0QFO"1*υΩϡϝϯτͷॻ͖͔ͨίʔυͷࣗಈੜʹ͓͍ͯ0QFO"1*υΩϡϝϯτΛਖ਼͘͠ॻ͘͜ͱඇৗʹॏཁͰ͢ɻ4XJGU0QFO"1*(FOFSBUPSͷݪଇʹʮ'BJUIGVMMZSFQSFTFOUUIF0QFO"1*EPDVNFOUʯͭ·Γʮ0QFO"1*υΩϡϝϯτΛ࣮ʹදݱ͢Δʯ͕ڍ͛ΒΕ͍ͯ·͢ɻͨͩ0QFO"1*ͷυΩϡϝϯτඞਢͷ߲͕ଟଘࡏ͍ͯͨ͠Γɺ(FOFSBUPSಛ༗ͷॻ͖ํͷίπ͕͋ΔͳͲิॿͳ͠Ͱॻ͘͜ͱ͍͠ͱࢥ͍·͢ɻͦ͜Ͱ͜͜ͰͳΔ͘// লུswitch response {case let .ok(okResponse):switch okResponse.body {case .json(let json):print(json)}case let .unauthorized(error):print("unauthorized: \(error)")case let .badRequest(json):print("bad request:", json)case .undocumented(statusCode: letstatusCode, let payload):print("undocumented: \(statusCode)\n \(payload)")}self.client = Client(ɹɹɹɹserverURL: try!Servers.server1(),ɹɹɹɹtransport: URLSessionTransport())let response = try awaitclient.textCompletions(body: body)import OpenAPIRuntimeimport OpenAPIURLSession
ਖ਼͍͠υΩϡϝϯτΛఆٛ͢ΔͨΊͷΛհ͠·͢ɻ 74$PEFͰ֦ுػೳΛ׆༻͠ͳ͕Βॻ͘࠷ॳͷҰาͱͯ͠9DPEFΛΘͣɺ0QFO"1*ͷυΩϡϝϯτΛॻ͘ڥ͕͍͑͢*%&Ͱॻ͘͜ͱΛ͓קΊ͠·͢ɻࢲ74$PEFͰॻ͘͜ͱ͕΄ͱΜͲͰ͢ɻ:".-ͷ߹ɺ9DPEFΑΓγϯλοΫεϋΠϥΠτ͕ޮ͖·͢ɻ·ͨ74$PEFͰ0QFO"1*ͷυΩϡϝϯτΛॻͨ͘Ίʹศརͳ֦ுػೳ͕͍͔ͭ͋͘Γ·͢ɻ͓͢͢ΊҎԼͰ͢ɻɾ4XBHHFS7JFXFSɾPQFOBQJMJOUɾ0QFO"1* 4XBHHFS&EJUPSɾ0QFO"QJ4OJQQFUT 4QFDUSBMͷΑ͏ͳ$-*πʔϧΛ༻͢Δผͷํ๏ͱͯ͠ɺ4QFDUSBMͱ͍͏OQNϞδϡʔϧΛ͏͜ͱͰ͖·͢ɻҎԼͷίϚϯυΛ࣮ߦ͢Δ͜ͱͰɺυΩϡϝϯτͷόϦσʔγϣϯΛͯ͘͠Ε·͢ɻ 0QFO"1*,JUΛ͍ɺ4XJGUͰόϦσʔτ͢Δ4XJGUͰόϦσʔτΛߦ͏ͱ͍͏ํ๏͋Γ·͢ɻ0QFO"1*,JUͱ͍͏ϥΠϒϥϦΛͬͯ0QFO"1*υΩϡϝϯτͷόϦσʔγϣϯΛ͢Δ͜ͱ͕ՄೳͰ͢ɻ͜ͷϥΠϒϥϦ4XJGU0QFO"1*(FOFSBUPS෦Ͱ༻͍ͯ͠ΔϥΠϒϥϦͰ͢ɻϝΠϯͷػೳ0QFO"1*υΩϡϝϯτͷΤϯίʔυɺσίʔυΛߦ͏͜ͱͰ͕͢ɺόϦσʔγϣϯՄೳͰ͢ɻಛ4XJGUͰόϦσʔγϣϯΛ࣮͢Δ͜ͱ͕Ͱ͖Δ͜ͱͰ͢ɻࢴ໘ͷ߹্ৄ͘͠આ໌Ͱ͖·ͤΜ͕ɺผهࣄͰ࣮ʹ͍ͭͯղઆ͍ͯ͠·͢ͷͰɺຊߘ·ͱΊͷ23ίʔυ͔Βͥͻ֬͝ೝ͍ͩ͘͞ɻϙΠϯτࣗಈੜ͕ະରԠͷ߹ͷ࣮4XJGU0QFO"1*(FOFSBUPSͱͯศརͰ͕͢ɺ·ͩαϙʔτ͍ͯ͠ͳ͍͜ͱଟ͋͘Γ·͢ɻ͜͜Ͱͦͷ͏ͪͷҰͭͱͦͷରԠํ๏ͷ࣮ྫΛհ͠·͢ɻ0QFO"1*ͷఆٛʹTFDVUJSZ4DIFNFTͱ͍͏"1*ͷೝূʢ#BTJDೝূɺ0"VUIͳͲʣΛఆٛ͢Δ߲͕ଘࡏ͠·͕͢ɺ4XJGU0QFO"1*(FOFSBUPS·ͩରԠ͓ͯ͠ΒͣͦΕΒͷίʔυࣗಈੜ͞Ε·ͤΜɻͰࣗಈੜίʔυͷ༻ఘΊͳ͚Ε͍͚ͳ͍ͷ͔ͱ͍͏ͱͦΜͳ͜ͱͳ͘ɺ͍ʹରԠํ๏͕͋Γ·͢ɻͦΕ͕ϛυϧΣΞΛ༻͢Δํ๏Ͱ͢ɻ$MJFOU.JEEMFXBSFͱ͍͏ϓϩτίϧʹ४ڌͯ͠JOUFSDFQUϝιουΛ࣮͢Δ͜ͱͰ)551ϦΫΤετʹ్தͰׂΓࠐΈɺॲཧΛೖ͢Δ͜ͱ͕Ͱ͖·͢ɻnpx spectral lint openapi.yaml
ҎԼͷΑ͏ʹ࣮͠·͢ɻͦͯ͠$MJFOUΛॳظԽ͢Δͱ͖ʹΦϓγϣφϧͷҾͰ͋ΔNJEEMFXBSFTʹ͠·͢ɻྻΛड͚औΔͷͰɺෳͷϛυϧΣΞΛ࣮ͯ͢͜͠ͱ͕Ͱ͖·͢ɻ͜ͷΑ͏ʹࣗಈੜʹରԠ͍ͯ͠ͳ͍έʔε͕͋ͬͯɺ4XJGU0QFO"1*(FOFSBUPSͷϧʔϧʹԊ࣮ͬͨΛೖ͢Δ͜ͱͰɺࣗಈੜίʔυΛ͍ͳ͕Β(FOFSBUPSͷະରԠ෦ΛΧόʔ͢Δ͜ͱ͕Ͱ͖·͢ɻimport Foundationimport OpenAPIRuntimefinal class AuthMiddleware: ClientMiddleware {func intercept(_ request: OpenAPIRuntime.Request,baseURL: URL, operationID: String,next: (OpenAPIRuntime.Request, URL)async throws -> OpenAPIRuntime.Response) async throws -> OpenAPIRuntime.Response {var request = requestrequest.headerFields.append(.init(name: "Authorization", value:"Basic "))return try await next(request, baseURL)}}self.client = Client(serverURL: try! Servers.server1(),transport: URLSessionTransport(),middlewares: [AuthMiddleware()])
·ͱΊ͜͜·Ͱ͓ಡΈ͍͖ͨͩ͋Γ͕ͱ͏͍͟͝·͢ʂ 4XJGU1BDLBHFQMVHJOͷϏϧυπʔϧϓϥάΠϯͱͯ͠༻Մೳͳ͜ͱͰɺ4XJGU0QFO"1*(FOFSBUPSͷಋೖඇৗʹ؆୯Ͱͨ͠ɻ͍׳Ε͍ͯΔ9DPEF͔ΒΕͣʹಋೖɾར༻͕ՄೳͳͷJ04ΤϯδχΞʹͱͬͯخ͍͜͠ͱͩͱࢥ͍·͢ɻ;FOOʹຊߘͷݪߘΑΓৄࡉͳղઆهࣄɺࢀߟจݙͷϦϯΫΛ·ͱΊ͍ͯ·͢ɻ͜͜Ͱઆ໌͖͠Εͳ͔ͬͨ$MJFOU.JEEMFXBSFΛ༻ͨ͠ผͷϢʔεέʔε0QFO"1*,JUͷόϦσʔγϣϯϝιουͷ͍ํͳͲΛղઆ͍ͯ͠·͢ɻͥͻ͝ཡ͍ͩ͘͞ɻίϝϯτײ͓͍ͪͯ͠·͢ɻ ͜ΕΛػʹ4XJGU0QFO"1*(FOFSBUPSʹڵຯΛ࣋ͬͯͩ͘͞Δํ͕૿͑Ε͍Ͱ͢ɻஶऀʹ͍ͭͯstruct Kamimi {var organization: String = "Yappli, Inc."let twitter: String = "kamimi_01"let github: String = "kamimi01"var approvedProposals = ["͡ΊΑ͏ʂSwift OpenAPI GeneratorʹΑΔεΩʔϚۦಈ։ൃɿಋೖखॱͱ׆༻ͷίπ","جૅ͔Βཧղ͢Δʂདྷय़·ͰʹରԠ͖͢ϓϥΠόγʔͷมߋ"]}