Slide 1

Slide 1 text

*SJNBTV%FOTBO1MBOOJOHೳొཁ 4DSPMM7JFX6*,JU 4DSPMM %FDFMFSBUJOH

Slide 2

Slide 2 text

iOS15ެ։͞Ε·ͨ͠

Slide 3

Slide 3 text

J04Y͔Βͷڧ੍Ξοϓσʔτ͸ͳ͍ͨΊΞοϓ σʔτ଎౓͸଎͘ͳ͍΋ͷͷɺΞϓϦ։ൃऀଆʹ ͱͬͯ͸ϓϩάϥϛϯά͠΍͘͢ͳΔ࢓૊Έ͕ಋೖ

Slide 4

Slide 4 text

async/await/actorͷಋೖʹΑΓεϨουؒͰͷॲ ཧΛؾʹ͢Δඞཁ͕ݮΓSwiftUI(ͱ͍͏͔iOSωΠ ςΟϒΞϓϦ։ൃ)ͷֶशίετ͕Լ͕Γ·ͨ͠ɻ

Slide 5

Slide 5 text

SwiftUI Λొ৔ͷࠒ(2019)͔ Βਪ͍ͯ͠Δ౰ํͰ͕͢ɺ

Slide 6

Slide 6 text

͜͜Ζ͸SwiftUIΛ཭Ε UIKit ʹ໭͍ͬͯͨɻ

Slide 7

Slide 7 text

Կނ

Slide 8

Slide 8 text

6*,JUͰ΍Γ͜࢒ͨ͜͠ ͱ͕͋Δ͔Βͩ ຊԻ 4XJGU6*Ͱཉ͍͕͠4XJGU6*Ͱ࣮ݱͰ͖ͳ͍͔Β

Slide 9

Slide 9 text

*OGJOJU-PPQ)FBEFS ແݶʹεΫϩʔϧͰ͖Δϔομ w ࠨӈํ޲ʹεΫϩʔϧՄೳ w ϝχϡʔ͕ແݶʹදࣔ͞Ε ͍ͯΔΑ͏ʹϔομ߲໨͕ εΫϩʔϧ w தԝʹ͋Δ߲໨͕બ୒த w ϠΫΦΫΞϓϦ ೥ ݄ݱࡏ ͷϝχϡʔ

Slide 10

Slide 10 text

*OGJOJU-PPQ)FBEFS w ແݶϧʔϓϔομʔ͸ΦʔϓϯιʔεϕʔεͰ͍͔ͭ͘ଘࡏ w 6*$PMMFDUJPO7JFXϕʔε w %BUB4PVSDFEFMFHBUFΛ࢖ͬͯಈతʹΧϥϜੜ੒ w ਺ݸͷϝχϡʔ߲໨Λදࣔ͢Δ͚ͩͰ6*$PMMFDUJPO7JFXΛ࢖͏ඞ ཁ͕͋Δͷ͔ w ΋ͬͱγϯϓϧʹ ͭ·Γ6*4DSPMM7JFX Ͱ࣮ݱͰ͖ͳ͍͔

Slide 11

Slide 11 text

6*4DSPMMʹ͍ͭͯ ߟ͑ͯΈΔ

Slide 12

Slide 12 text

6*4DSPMM7JFX J04ͷ࢖͍ͪ͝͝ͷྑ͞Λܾఆ͚ͮͨ6*ύʔπ w J04 J1IPOF04 ͷࠒ͔Βଘࡏ w Ϣʔβʔͷλονૢ࡞ʹ௥ਵ͢ΔεΫϩʔϧ w ίϯςϯπ຤୺·Ͱ౸ୡͨ͠ࡍͷό΢ϯε w Ԡ༻6*ଟ਺ w 8,8FC7JFXɺ6*5BCMF7JFXɺ6*$PMMFDUJPO7JFX w աڈʹ͸.BQ΋࢖༻

Slide 13

Slide 13 text

6*4DSPMM7JFX J04ͷ࢖͍ͪ͝͝ͷྑ͞Λܾఆ͚ͮͨ6*ύʔπ w ΞϓϦ։ൃͰ΋ෳࡶͳ࢓૊Έ w εΫϩʔϧίϯςϯπͷ෯ߴ͞ͷऔѻ͕೥ʑมԽ w "VUP4J[JOHˠ$POTUSBJOUˠ"ODIPSͱ೥ʑ੔ཧ w ίϯςϯπྖҬͷτϥϒϧ w J04ʙεςʔλεόʔྖҬมߋΛ΋Ζʹड͚Δ w εςʔλεόʔ͔ΒϊονྖҬ΁ͱมԽ w ෳ਺ϓϩύςΟͷ૊Έ߹ΘͤͰڍಈ͕มԽ w %FMFHBUFͰͷදࣔྖҬ੍ޚͷϊ΢ϋ΢ඞཁ

Slide 14

Slide 14 text

6*4DSPMM7JFXͱ೿ੜΫϥε w 6*,JU͸యܕతͳΫϥεϥ ΠϒϥϦ w ೿ੜݩΫϥεͷػೳΛ೿ੜ ݩ্͕ॻ͖͢Δ w ೿ੜ͕܁Γฦ͞ΕΔͱຊདྷ ͷػೳ͕࢖͑Δ͔೺Ѳͮ͠ Β͘ͳΔ ೿ੜݩ ೿ੜઌ

Slide 15

Slide 15 text

6*4DSPMM7JFXͷػೳ্ॻ͖ঢ়گ 6*4DSPMM7JFXͷ೿ੜΫϥεͰԿ͕࢖͑Δ͔ ߟ͑Δඞཁ͋Γ

Slide 16

Slide 16 text

6*4DSPMM7JFXͷػೳ্ॻ͖ঢ়گ 6*4DSPMM7JFXͷ೿ੜΫϥεͰԿ͕࢖͑Δ͔ ߟ͑Δඞཁ͋Γ EFMFHBUF͸࢖༻Մೳ δΣενϟʔҎ֎͸֓Ͷ ར༻Մೳ

Slide 17

Slide 17 text

6*4DSPMM7JFX%FMFHBUF 6*4DSPMM7JFX಺ͰͷΠϕϯτΛัଊ͢ΔEFMFHBUF w 4DSPMMΠϕϯτ w εΫϩʔϧ։࢝ऴྃΠϕϯτ w ར༻ऀ6*ଆͷશͯͷεΫϩʔϧΠϕϯτ͕ൃੜ w ζʔϜ։࢝ऴྃΠϕϯτ w %FDFMFSBUJOH։࢝ऴྃΠϕϯτ w Ϣʔβʔͷૢ࡞ޙʹό΢ϯυಈ࡞ͷ։࢝ऴྃΛ௨஌ w εΫϩʔϧΛτοϓʹҠಈ͢Δ͔ͷΠϕϯτ εςʔλεྖҬͷλ οϓ

Slide 18

Slide 18 text

6*4DSPMM7JFX%FMFHBUF 4DSPMMͱ%FDFMFSBUJOHͷؔ܎ w 4DSPMMΠϕϯτ w Ϣʔβʔ͕λονૢ࡞Ͱ w %FDFMFSBUJOHΠϕϯτ w Ճ଎౓͋Γͷλονૢ࡞ޙʹɺ4DSPMM7JFX͕ຊདྷ͋Δ΂͖Ґஔ ʹίϯςϯπ͕໭Δ·ͰͷΠϕϯτ w %FDFMFSBUJOH͕ऴྃ͢Δ·Ͱը໘্ͷಈ͖͸ࢭ·Βͳ͍

Slide 19

Slide 19 text

͜͜·ͰΛ౿·͑ͯ ແݶϧʔϓΛ࣮ݱ͢Δ

Slide 20

Slide 20 text

αϯϓϧίʔυ

Slide 21

Slide 21 text

IUUQTHJUIVCDPNOPUPSPJE *OGJOJUF)FBEFS%FNP

Slide 22

Slide 22 text

6*4DSPMM7JFXͰແݶεΫϩʔϧΛ࣮ݱᶃ 4DSPMMຖʹҐஔௐ੔ɺ%FDFMFSBUJOHޙʹਖ਼نԽ

Slide 23

Slide 23 text

6*4DSPMM7JFXͰແݶεΫϩʔϧΛ࣮ݱᶄ 4DSPMMຖʹҐஔௐ੔ɺ%FDFMFSBUJOHޙʹਖ਼نԽ

Slide 24

Slide 24 text

6*4DSPMM7JFXͰແݶεΫϩʔϧΛ࣮ݱᶄ 4DSPMMຖʹҐஔௐ੔ɺ%FDFMFSBUJOHޙʹਖ਼نԽ JO fi OJUF-PPQ7JFX্ͷ4UBDL7JFXͷ9࣠Λௐ ੔ͯ͠ݶΓ͋ΔϔομཁૉΛ࠶ར༻͢Δ JO fi OJUF-PPQ7JFX͸4DSPMM7JFX੍͕ޚ͢Δ

Slide 25

Slide 25 text

6*4DSPMM7JFXͰແݶεΫϩʔϧΛ࣮ݱᶅ 4DSPMMຖʹҐஔௐ੔ɺ%FDFMFSBUJOHޙʹਖ਼نԽ 4DSPPM7JFXͷྖҬΛϔομʔͷΧϥϜ ෯ͱ͠ɺDMJQ5P#PVOEΛ֦͛ͯࢠཁૉΛ දࣔɺλονՄೳͳྖҬ΋֦͓͛ͯ͘

Slide 26

Slide 26 text

extension InfiniteLoopHeaderView: UIScrollViewDelegate { … // Decelerating΁ͷରԠ func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { // εΫϩʔϧҐஔͷਖ਼نԽ͕ߦΘΕ͍ͯͳ͍৔߹ guard scrollNormalizedPosition != 0 else { return } // ίϯςϯπͷதԝҐஔΛऔಘ let scrollViewCenter = scrollView.superview!.convert(scrollView.center, to: contentView) // தԝҐஔؚ͕·ΕΔۣܗ৘ใΛݩʹϔομʔཁૉͷΠϯσοΫεΛܭࢉ var targetIndex: Int = -1 for index in 0..<(leftOverrun + elementCount + rightOverrun) { let hitTestRect = CGRect(origin: CGPoint(x: CGFloat(index) * scrollView.bounds.width, y: 0), size: scrollView.bounds.size) if hitTestRect.contains(scrollViewCenter) { targetIndex = index } } // ಘΒΕͨΠϯσοΫεΛݩʹΠϯσοΫε৘ใΛਖ਼نԽ let position = targetIndex - leftOverrun let loopIndex = (elementCount + ( (position) % elementCount)) % elementCount selectedIndex = loopIndex // ͜͜ͰεΫϩʔϧॲཧΛϓϩςΫτ͢Δ(scrollNormalizedPosition͕มߋ͞Εͯ͠·͏ՄೳੑΛආ͚ΔͨΊ) skipDidScroll = true self.scrollView.contentOffset = CGPoint(x: self.scrollView.bounds.width * CGFloat(centerForFiniteLoop() + selectedIndex), y: 0) skipDidScroll = false scrollNormalizedPosition = 0 centerXConstraint.constant = 0 } }

Slide 27

Slide 27 text

extension InfiniteLoopHeaderView: UIScrollViewDelegate { … // εΫϩʔϧ΁ͷରԠ func scrollViewDidScroll(_ scrollView: UIScrollView) { // skipDidScroll͞Ε͍ͯΔ৔߹͸scrollViewDidEndDecelerating Ͱͷ guard skipDidScroll != true else { return } // ScrollViewͷcontentOffsetͱscrollNormalizedPosition͔ΒҐஔΛಘΔ let plainPosition = Int(ceil( (scrollView.contentOffset.x / scrollView.bounds.width) - CGFloat(centerForFiniteLoop()) + CGFloat(scrollNormalizedPosition) ) ) if plainPosition <= leftSafeArea { // ϔομʔࠨͷ҆શྖҬΛ௒͍͑ͯͨ৔߹͸scrollNormalizedPosition ʹҐஔΛ֨ೲ͠contentView ͷҐஔΛͣΒ͢ scrollNormalizedPosition = scrollNormalizedPosition + -plainPosition + (elementCount - visibleColumnNumber) centerXConstraint.constant = CGFloat(-scrollNormalizedPosition) * scrollView.bounds.width } else if plainPosition >= rightSafeArea { // ϔομʔӈͷ҆શྖҬΛ௒͍͑ͯͨ৔߹͸scrollNormalizedPosition ʹҐஔΛ֨ೲ͠contentView ͷҐஔΛͣΒ͢ scrollNormalizedPosition = scrollNormalizedPosition + -plainPosition centerXConstraint.constant = CGFloat(-scrollNormalizedPosition) * scrollView.bounds.width } else { // ͦͷଞͷ৔߹͸௨ৗॲཧɻબ୒ΠϯσοΫεΛมߋ let lIndex = (elementCount + (plainPosition % elementCount)) % elementCount selectedIndex = lIndex } } }

Slide 28

Slide 28 text

·ͱΊ

Slide 29

Slide 29 text

·ͱΊ w4XJGU6*Ͱ࣮ݱͰ͖ͳ͍6*Λ6*,JUͰ࡞Γ·ͨ͠ wΦʔϓϯιʔεطଘͷ΋ͷΑΓγϯϓϧͳ6*ύʔπ Λ໨ࢦ͠·ͨ͠ w6*ύʔπΛ࡞੒ʹ6*4DSPMM7JFXΛ࢖༻͠·ͨ͠ w6*4DSPMM7JFXͷ4DSPMMΠϕϯτ͸Ϣʔβʔૢ࡞ɺՃ ଎౓ʹΑΔό΢ϯυؔ܎ͳ͠ʹൃੜ͠·͢ w6*4DSPMM7JFX͕׬શʹ੩ࢭ͢Δͷ͸%FDFMFSBUJOH ΠϕϯτऴྃޙͰ͢