ãã®ã»ãã·ã§ã³ããã³ä»ã®å€ãã®ã»ãã·ã§ã³ïŒ Swift in Practice ã UIKitã¢ããªã®ãããã³ã«ããã³å€æåããã°ã©ãã³ã° ïŒã§ã¯ããããã³ã«ã®äœ¿çšã®è¯ãäŸã瀺ããŠããŸããããããã³ã«æåããã°ã©ãã³ã°ãšã¯æ£åŒã«ã¯å®çŸ©ããŠããŸããã
ãããã³ã«æåããã°ã©ãã³ã°ïŒPOPïŒã«é¢ããå€ãã®èšäºãã€ã³ã¿ãŒãããäžã«ããããããã³ã«ã®äœ¿çšäŸã瀺ãããŠããŸããããã®äžã§ããPOPã®æ確ãªå®çŸ©ã¯èŠã€ãããŸããã§ããã
ãããã³ã«ã®äœ¿çšäŸãåæããã³ãŒãããããã³ã«æåãšåŒã¶ããšãã§ããããã«åŸãã¹ãååãçå®ããããšããŸããã
POPã瀺ãã³ãŒãäŸãèŠãŠã¿ããšã次ã®èšèªããŒã«ãPOPã§éèŠãªåœ¹å²ãæãããŠããããšãããããŸãïŒ protocol ã extensions ã constraint ã
圌ããç§ãã¡ã«äžããæ©äŒãèŠãŠã¿ãŸãããã
ãããã³ã«
ãããã³ã«ã®äœ¿çšã¯ãããã€ãã®ã·ããªãªã«åããããšãã§ããŸãã
ã¿ã€ããšããŠã®ãããã³ã«
OOPããã®ã€ã³ã¿ãŒãã§ã€ã¹ãšã³ã³ãã©ã¯ãããã°ã©ãã³ã°ããã®ã³ã³ãã©ã¯ã㯠ãæŠå¿µã«äŒŒãŠããŸãã ãªããžã§ã¯ãã®æ©èœã説æããŸãã ããããã£ã®ã¿ã€ããé¢æ°ã®çµæã®ã¿ã€ããç°çš®ã³ã¬ã¯ã·ã§ã³ã®èŠçŽ ã®ã¿ã€ããšããŠäœ¿çšã§ããŸãã èšèªã®å¶éã«ãããé¢é£ããã¿ã€ããŸãã¯èªå·±èŠä»¶ãæã€ãããã³ã«ã¯ã¿ã€ããšããŠäœ¿çšã§ããŸããã
ãã¿ãŒã³ã¿ã€ããšããŠã®ãããã³ã«
äžè¬åããã°ã©ãã³ã°ã®æŠå¿µã«äŒŒãŠããŸã ã
ãŸãããªããžã§ã¯ãã®æ©èœã説æãã圹å²ãæãããŸããããåãšããŠã®ãããã³ã«ããšã¯ç°ãªããäžè¬åãããé¢æ°ã®åèŠä»¶ãšããŠäœ¿çšãããŸãã é¢é£ããã¿ã€ããå«ãŸããå ŽåããããŸãã
é¢é£å -æŠå¿µã¢ããªã³ã°åã«é¢é£ããè£å©åïŒ ãŠã£ãããã£ã¢ã®å®çŸ©ïŒããããã³ã«ãã¿ã€ããšããŠäœ¿çšããå Žåãããã³ã¿ã€ãã®å¶éãšããŠããããããã«-äž¡æ¹ã®ã·ããªãªã§ãããã³ã«ã䜿çšããããšãå¿ èŠãªå Žåãããæ確ãªè¡ã¯ãããŸããã ãŠãŒã¹ã±ãŒã¹ã匷調ããŠã¿ãããšãã§ããŸãïŒ
- ã¢ããªã±ãŒã·ã§ã³ã®äžäœå±€ã«æ©èœãæäŸããäŸåé¢ä¿ãšããŠã³ã³ã·ã¥ãŒãã¯ã©ã¹ã«æž¡ãããã¯ã©ã¹-ãããã¯ããµãŒãã¹ããªããžããªãAPIã¯ã©ã€ã¢ã³ãããŠãŒã¶ãŒèšå®ãªã©ã§ãã
ãã®å Žåããããã³ã«ãã¿ã€ããšããŠäœ¿çšããæ¹ã䟿å©ã§ãïŒIOCã³ã³ãããŒã«ç»é²ã§ãã䜿çšããã«äœ¿çšã§ããŸãïŒããã®ãµãŒãã¹ã䜿çšãããã¹ãŠã®é¢æ°ã«ã¿ã€ããã©ã¡ãŒã¿ãŒãè¿œå ããå¿ èŠã¯ãããŸããã
- æ¯èŒãå ç®ãé£çµãªã©ã®æ°åŠçæäœãèšè¿°ãããããã³ã«ã ãã®å Žåãæäœã1ã€ã®ã¿ã€ãïŒSwiftã®IntãšStringã®äž¡æ¹ãEquatableãããã³ã«ã«å¯Ÿå¿ããŸãããè©Šè¡ããå ŽåïŒæ¯èŒæŒç®åã¯ãã©ã¡ãŒã¿ãŒãåãåã§ããããšãèŠæ±ãããããããããåçã§ãããã©ããããã§ãã¯ãããšãã³ã³ãã€ã©ãŒã¯ãšã©ãŒãã¹ããŒããŸãã ãããã£ãŠããã®å Žåããããã³ã«ã¯ã¿ã€ããã³ãã¬ãŒããšããŠäœ¿çšãããŸãã
- é¢é£ä»ããããåãæã€ãããã³ã«ããã©ã€ããŒãããããã£ã«ä¿åããããšãå¿
èŠã«ãªãå ŽåããããŸããããã®å Žåããããã³ã«ãåãšããŠäœ¿çšã§ããŸããã ãã®åé¡ã解決ããã«ã¯ãããŸããŸãªæ¹æ³ããããŸããããšãã°ãé¢é£ããã¿ã€ãã®äœ¿çšãç¹å®ã®ã¿ã€ãã«çœ®ãæããããé¡äŒŒã®ãããã³ã«ãäœæããŸãã åæ¶å»åä¿¡ã®äœ¿çš-ãã®å Žåãé¢é£ããåã¯Any [YourProtocolName]åã®æ±çšãã©ã¡ãŒã¿ãŒã«è»¢éãããŸãã å¥ã®ãªãã·ã§ã³ã¯ãã€ã³ã¹ã¿ã³ã¹èªäœã§ã¯ãªãããã®æ©èœãä¿åããããšã§ãã ãŸãã¯ãããããã£ã«ä¿åãããŠããã¯ããŒãžã£ãŒã§ã€ã³ã¹ã¿ã³ã¹ããã£ããã£ããŸãã
ç¹æ§ãšããŠã®ãããã³ã«
ç¹æ§ïŒã¿ã€ãïŒ -å®è£ ãããæ©èœã®ã»ãããæäŸãããšã³ãã£ãã£ã ã¯ã©ã¹/æ§é /åæåã®ãã«ãã£ã³ã°ãããã¯ã®ã»ãããšããŠæ©èœããŸãã
ç¹æ§ã³ã³ã»ããã®èª¬æã¯ããã«ãããŸã ã
ãã®æŠå¿µã¯ãç¶æ¿ã眮ãæããããã«èšèšãããŠããŸãã OOPã§ã¯ãã¯ã©ã¹ã®åœ¹å²ã®1ã€ã¯åå©çšå¯èœãªã³ãŒãã®åäœã§ãã åå©çšèªäœã¯ç¶æ¿ãéããŠè¡ãããŸãã
åæã«ãã¯ã©ã¹ã¯ã€ã³ã¹ã¿ã³ã¹ã®äœæã«äœ¿çšãããããããã®æ©èœã¯å®å šã§ãªããã°ãªããŸããã ãããã®2ã€ã®ã¯ã©ã¹ã®åœ¹å²ã¯ãã°ãã°ç«¶åããŸãã ããã«ãåã¯ã©ã¹ã«ã¯ã¯ã©ã¹éå±€å ã®ç¹å®ã®å Žæããããã³ãŒãã®åå©çšã®åäœã¯ä»»æã®å Žæã«é©çšã§ããŸãã 解決çãšããŠããã軜ããšã³ãã£ãã£ã䜿çšããããšãææ¡ãããŠããŸã-ã³ãŒãã®åå©çšã®åäœãšããŠã®ç¹æ§ãããã³ã¯ã©ã¹ã¯ãç¹æ§ããç¶æ¿ãããããžãã¯ãåŒã³åºãããã®æ¥ç¶èŠçŽ ã®åœ¹å²ãå²ãåœãŠãããŸãã
Swiftã¯ããããã³ã«ãšãããã³ã«æ¡åŒµãéããŠãã®æŠå¿µãå®è£ ããŸãã ãããã³ã«ã«åºæã®å¿ èŠãªæ©èœããæ¥ç¶ãããã«ã¯ãäœæããã¿ã€ãã«ãã®ãããã³ã«ãžã®éä¿¡ãè¿œå ããå¿ èŠããããŸã-æ©èœãç¶æ¿ããããã®åºæ¬ã¯ã©ã¹ãäœæããå¿ èŠã¯ãããŸããã
ç¹æ§ã«ã¯ã©ã®ãããªç¹æ§ãããããããã³ã«ãšã®é¡äŒŒæ§ããããŸãã
- traitã¯ãåäœãå®è£
ããäžé£ã®ã¡ãœãããæäŸããŸãã -ãããã³ã«æ¡åŒµã䜿çšããŠè¿œå ãããã¡ãœããã
- traitã«ã¯ãåäœãæäŸããããã®ãã©ã¡ãŒã¿ãŒãšããŠæ©èœããäžé£ã®ã¡ãœãããå¿
èŠã§ãã -ãããã³ã«èªäœã«å«ãŸããã¡ãœããïŒãããã³ã«èŠä»¶ïŒ;
- ç¹æ§ã¯ãç¶æ
ãä¿æããå€æ°ãèšå®ããŸããã traitãæäŸããã¡ãœããã¯ãã¯ã©ã¹ã®ãã£ãŒã«ãã«çŽæ¥ã¢ã¯ã»ã¹ããŸããã -æ¡åŒµã¡ãœããã¯ãä¿åãããããããã£ã¿ã€ãã«è¿œå ã§ããŸããã ãããã³ã«ã¯ãããããã£ãäœã§ããã¹ãããšããèŠä»¶ãè¿œå ã§ããŸãã-èšç®ãŸãã¯ä¿åããããããæ¡åŒµã¡ãœããã¯ããŒã¿ã«çŽæ¥ã¢ã¯ã»ã¹ã§ããŸãã-ããããã£ã¢ã¯ã»ãµãä»ããŠå®è£
ãããŸãã
- ã¯ã©ã¹ãšç¹æ§ã¯ãä»ã®ç¹æ§ã§æ§æã§ããŸãã ã¡ãœããã®ç«¶åã¯æ瀺çã«è§£æ±ºããå¿
èŠããããŸãã -ãããã³ã«ã«æºæ ããã¯ã©ã¹ãè¿œå ã§ãããããã³ã«ã¯ä»ã®ãããã³ã«ãžã®ç¶æ¿ããµããŒãããŸãã 競åã¯ãããšãã°ãç¹å®ã®ã¿ã€ãã«ãã£ã¹ãããããšã§è§£æ±ºã§ããŸãã
protocol Protocol1 { } protocol Protocol2 { } protocol ComposedProtocol: Protocol1, Protocol2 { } extension Protocol1 { func doWork() { print("Protocol1 method") } } extension Protocol2 { func doWork() { print("Protocol1 method") } } extension ComposedProtocol { func combinedWork() { (self as Protocol1).doWork() (self as Protocol2).doWork() print("ComposedProtocol method") } }
- ç¹æ§ãè¿œå ããŠããã¯ã©ã¹ã®ã»ãã³ãã£ã¯ã¹ã«ã¯åœ±é¿ããŸãããç¹æ§ããã®ã¡ãœããã䜿çšããããã¯ã©ã¹ã§çŽæ¥å®çŸ©ãããã¡ãœããã䜿çšãããã«éãã¯ãããŸããã -ããã¯ãããã³ã«ã«åœãŠã¯ãŸããŸã-ã³ãŒããèŠããšãã¡ãœãããã©ãã§å®çŸ©ãããŠããããå€æã§ããŸãã-ãããã³ã«æ¡åŒµãŸãã¯ãããã³ã«ã«å¯Ÿå¿ããã¿ã€ã;
- åæç¹æ§ã¯ãç¹æ§ã®ã»ãã³ãã£ã¯ã¹ã«åœ±é¿ãäžããŸãã-è€åç¹æ§ã¯ãåãã¡ãœãããå«ãããã©ãããç¹æ§ãšåçã§ãã -fooïŒïŒã¡ãœããã§Fooãããã³ã«ã䜿çšããbarïŒïŒã¡ãœããã§Barãããã³ã«ãããbazïŒïŒã¡ãœããã§Bazããç¶æ¿ãããŸãããfooïŒïŒãbarïŒïŒãbazïŒïŒã®3ã€ã®ã¡ãœããã§ãããã³ã«ã䜿çšããã®ãšéãã¯ãããŸããã
ã芧ã®ãšããããããã³ã«ã¯Swiftãç»å Žãããã£ãšåã«èª¬æãããç¹æ§ã®æŠå¿µãšå®å šã«äžèŽããŠããŸãã
ããŒã«ãŒãšããŠã®ãããã³ã«
ã¿ã€ãã®ãå±æ§ããšããŠäœ¿çšãããŸãããã®å Žåããããã³ã«ã«ã¯ã¡ãœãããå«ãŸããŠããŸããã äŸã¯ãCoreDataã®NSFetchRequestResultã§ãã 圌ã¯ãNSNumberãNSDictionaryãNSManagedObjectãNSManagedObjectIDãããŒã¯ããŸããã ãã®å Žåã®ãããã³ã«ã¯ãã¯ã©ã¹ã®æ©èœã«ã€ããŠã¯èª¬æããŠããŸããããCoreDataããããã®ã¯ã©ã¹ãã¯ãšãªçµæã®ã¿ã€ããšããŠãµããŒãããŠãããšããäºå®ã説æããŠããŸãã NSFetchRequestResultãããã³ã«ã§ããŒã¯ãããŠããªãã¿ã€ããçµæãšããŠæå®ãããšãã¢ã»ã³ããªæ®µéã§ãšã©ãŒãçºçããŸãã
ãããã³ã«ããŒã«ãŒã®ååšã®ç¢ºèªã¯ãããžãã¯ã®åå²ã«ã䜿çšã§ããŸãã
if object is HighPrioritized { ... }
æ¡åŒµæ©èœ
æ¡åŒµæ©èœã¯ãæ¢åã®ã¿ã€ããŸãã¯ãããã³ã«ã«æ©èœãè¿œå ã§ããèšèªããŒã«ã§ãã
æ¡åŒµæ©èœã䜿çšãããšã次ã®ããšãã§ããŸãã
- ãããã³ã«ã«ã¡ãœãããè¿œå ããŸã-ãã®ã¡ãœããã¯ããã®ãããã³ã«ã«å¯Ÿå¿ããåå
ãšãã®ã³ã³ã·ã¥ãŒããŒã®äž¡æ¹ã§äœ¿çšããããã«ïŒã¹ã³ãŒãå
ã§ïŒå©çšå¯èœã«ãªããŸãã
- ã¯ã©ã¹/æ§é /åæãããã³ã«ã®ã³ã³ãã©ã€ã¢ã³ã¹ãè¿œå ããŸãã åæã«ããããã®ã¿ã€ãã®ã³ãŒãã«ã¢ã¯ã»ã¹ããå¿
èŠã¯ãªãããµãŒãããŒãã£ã®ã©ã€ãã©ãªã«å«ããããšãã§ããŸãã ãã®æ©èœã¯ãé¡åã¢ããªã³ã°ãšåŒã°ããŸãã
ãããã³ã«ãå¥ã®ãããã³ã«ã«é©åãããããšã¯ã§ããŸããã ãããå¯èœã§ãP2ãããã³ã«ã«å¯Ÿå¿ããP1ãããã³ã«ãããå ŽåãP1ãããã³ã«ã«å¯Ÿå¿ãããã¹ãŠã®ã¿ã€ãã¯ãP2ãããã³ã«ã«ãèªåçã«å¯Ÿå¿ããŸãã ãã®åé¡ã®åé¿çãšããŠã次ã®ããªãã¯ã䜿çšã§ããŸãïŒP1ãããã³ã«ã®æ¡åŒµæ©èœãäœæããP2ãããã³ã«ã®ã¡ãœããã®å®è£ ãèšè¿°ããŸãããã®åŸãã¡ãœãããå®è£ ããã«ãP1ã«å¯Ÿå¿ããåã«P2ã®å¯Ÿå¿ãè¿œå ã§ããŸãã ãã®ã¢ã€ãã¢ã¯ãPOPãã¬ãŒã³ããŒã·ã§ã³ -é¡åçæ¡çšã®äŸã§ããå®èšŒãããŠããŸãã
protocol Ordered { func precedes(other: Self) -> Bool } extension Comparable { // , Comparable, : // extension Ordered where Self: Comparable // // extension Comparable where Self: Ordered func precedes(other: Self) -> Bool { return self < other } } extension Int : Ordered {} extension String : Ordered {}
- ãããã³ã«ã¡ãœããã®ããã©ã«ãå®è£
ãèšè¿°ããŸãã ã¿ã€ãã«ãã®ã¡ãœããã®å®è£
ãå«ãŸããå Žåãããã©ã«ãã®ä»£ããã«äœ¿çšãããŸãã
å¶çŽ
åã®å¶éã 以äžããµããŒããããŠããŸãããããã³ã«ã«æºæ ããã¯ã©ã¹ããç¶æ¿ããã¿ã€ããæã£ãŠããŸãã å¶çŽã¯ããžã§ããªãã¯åãæã€ã¡ãœããã®ã»ããã決å®ããããã«äœ¿çšãããŸãã æºè¶³ã§ããªãåã®å¶çŽãåŒæ°ãšããŠæž¡ããšãã³ã³ãã€ã©ã¯ãšã©ãŒãã¹ããŒããŸãã
䜿çšå ŽæïŒ
- äžè¬åãããé¢æ°ã®å®çŸ©ã«ããããã©ã¡ãŒã¿ãŒã®ã¿ã€ãã®å¶éã äŸïŒproduceé¢æ°ã¯ãé¢é£ä»ããããProductã¿ã€ããColaã§ãªããã°ãªããªãFactoryãããã³ã«ã«æºæ ããã¿ã€ãåŒæ°ãåããŸãã
func produce<F: Factory>(factory: F) where F.Product == Cola
å¥ã®äŸïŒåŒæ°ã¯2ã€ã®ãããã³ã«ã«åæã«å¯Ÿå¿ããå¿ èŠããããŸãïŒåç©ãšé£è¡ïŒ
// : func fly<T>(f: T) where T: Flying, T: Animal { ... } func fly<T: Flying & Animal>(f: T) { ... } func fly<T: Animal>(f: T) where T: Flying { ... } func fly<T>(f: T) where T: Flying & Animal { ... }
- ãããã³ã«å®çŸ©ã®é¢é£ã¿ã€ãã®å¶éã äŸ-é£æ³åèå¥åã¯Codableãããã³ã«ã«æºæ ããå¿
èŠããããŸãã
protocol Order { associatedtype Identifier: Codable }
relatedtype relatedtypeãå¶çŽã§ããŸãã
protocol GenericProtocol { associatedtype Value: RawRepresentable where Value.RawValue == Int func getValue() -> Value } // . : protocol GenericProtocol where Value.RawValue == Int { associatedtype Value: RawRepresentable func getValue() -> Value } protocol GenericProtocol where Value: RawRepresentable, Value.RawValue == Int { associatedtype Value func getValue() -> Value }
- æ¡åŒµã¡ãœããã®å¯çšæ§ã«é¢ããå¶éã Animalããã³Factoryã®é¢æ°ã®äŸããæ¡åŒµã¡ãœããã«æžãæããŸãã
extension Animal where Self: Flying { func fly() { ... } } extension Factory where Product == Cola { func produce() { ... } }
- æ¡ä»¶ä»ãé©å äŸïŒé
åã®èŠçŽ ã®åãObjectWithMassãããã³ã«ã«å¯Ÿå¿ããå Žåãé
åèªäœã¯ãã®ãããã³ã«ã«å¯Ÿå¿ãã質éãšããŠãèŠçŽ ã®è³ªéã®åèšãè¿ããŸãã
protocol ObjectWithMass { var mass: Double { get } } extension Array: ObjectWithMass where Element: ObjectWithMass { var mass: Double { return map { $0.mass }.reduce(0, +) } }
é¢é£ã¿ã€ãã®å®æ°ã¯ããããã³ã«èªäœãšããããã³ã«ãæž¡ãããã¡ãœãããããã³ãããã³ã«æ¡åŒµã®äž¡æ¹ã§æå®ã§ãããããå®æ°ãã©ãã«è¿œå ããããšããçåãçããŸãã ããã€ãã®æšå¥šäºé ïŒ
- ãããã³ã«ãã¢ããªã±ãŒã·ã§ã³åºæã§ããã1ã€ã®å®è£ ãæã€å Žåã¯ãé¢é£ããã¿ã€ãã§ã¯ãªãç¹å®ã®ã¿ã€ãã䜿çšããå¯èœæ§ãæ€èšãã䟡å€ããããŸãã
- ãããã³ã«ãã¢ããªã±ãŒã·ã§ã³åºæã§ãããããã€ãã®å®è£
ãããå ŽåïŒãã¹ãçšã®åœç©ãèæ
®ã«å
¥ããŠïŒ-ãã®ãããã³ã«ã䜿çšãããå Žæã§è€è£œããªãããã«ããããã³ã«èªäœã«ããããé
眮ããæ¹ã䟿å©ã§ãã
- ãããã³ã«ãåå©çšããèšç»ãããå Žåããããã³ã«ã«ã¯ãããã®å®æ°ã®ã¿ãå«ããå¿
èŠããããŸãããããã®å®æ°ããªããšããããã³ã«ã®ååšãæå³ãæããããã®äžã«ã¡ã€ã³ããžãã¯ãæ§ç¯ãããŸãã ä»ã®ãã¹ãŠã®å®æ°ã¯ãç¹æ®ãªã±ãŒã¹ã®èª¬æãšèŠãªãããã¡ãœããããã³æ¡åŒµæ©èœã«é
眮ãããå¿
èŠããããŸãã
åå
æé«ã®POPææã¯ããã€ãã»ã¢ãã©ãã ãºãäž»å¬ããããããã³ã«æåããã°ã©ãã³ã°ã®ã¹ãŠã£ãããã»ãã·ã§ã³ã§ãã èŠèŽããããšã匷ããå§ãããŸãã ã»ãšãã©ã®ååã¯ãããããã®äŸã®ãããã§åœ¢æãããŠããŸãã
- ãã¯ã©ã¹ããå§ããªãã§ãã ããã ãããã³ã«ã§éå§ããŸãã "ã ããã¯ãäžèšã®ã»ãã·ã§ã³ããã®ãã€ãã¢ãã©ãã ã¹ã«ãã声æã§ãã 解éããæ¹æ³ã¯2ã€ãããŸãã
- å®è£ ã§ã¯ãªããå¥çŽã®èª¬æïŒãªããžã§ã¯ããæ¶è²»è ã«æäŸããå¿ èŠãããæ©èœã®èª¬æïŒããå§ããŸã
- ã¯ã©ã¹ã§ã¯ãªãããããã³ã«ã§åå©çšå¯èœãªããžãã¯ãèšè¿°ããŸãã ãããã³ã«ãã³ãŒãã®åå©çšã®åäœãšããŠäœ¿çšããã¯ã©ã¹ãäžæã®ããžãã¯ã®å ŽæãšããŠäœ¿çšããŸãã å¥ã®æ¹æ³ã§ããã®ååã説æããããšãã§ããŸã- å€åãããã®ãã«ãã»ã«åããŸã ã
ããã³ãã¬ãŒãã¡ãœããããã¿ãŒã³ã¯ãåªããé¡äŒŒç©ã§ãã 圌ã®ã¢ã€ãã¢ã¯ãäžè¬çãªã¢ã«ãŽãªãºã ãå®è£ ã®è©³çŽ°ããåé¢ããããšã§ãã åºæ¬ã¯ã©ã¹ã«ã¯å ±éã®ã¢ã«ãŽãªãºã ãå«ãŸããåã¯ã©ã¹ã¯ã¢ã«ãŽãªãºã ã®ç¹å®ã®ã¹ããããåå®çŸ©ããŸãã POPã§ã¯ãäžè¬çãªã¢ã«ãŽãªãºã ã¯ãããã³ã«æ¡åŒµã«å«ãŸãããããã³ã«ã¯äœ¿çšãããã¢ã«ãŽãªãºã ã®ã¹ããããšã¿ã€ããããã³ã¯ã©ã¹å ã®ã¹ãããã®å®è£ ã決å®ããŸãã
- æ¡åŒµæ©èœã«ããæ§æã å€ãã®äººããç¶æ¿ãããåæã奜ãããšãããã¬ãŒãºãèããŠããŸãã OOPã§ã¯ããªããžã§ã¯ãã«ç°ãªãæ©èœã»ããïŒå€æ
çãªåäœïŒãå¿
èŠãªå Žåããã®æ©èœãããŒãã«åå²ããã¯ã©ã¹ã®éå±€ãç·šæã§ããŸããåã¯ã©ã¹ã¯ç¥å
ããæ©èœãç¶æ¿ããŠç¬èªã«è¿œå ãããããã€ã³ããŒã§äœ¿çšãããã€ã³ã¹ã¿ã³ã¹ã®éå±€ã«é¢ä¿ã®ãªãã¯ã©ã¹ã«åå²ããŸãæ宀ã æ¡åŒµæ©èœã䜿çšããŠãããã³ã«ã«é©åæ§ãè¿œå ããæ©èœã䜿çšãããšãè£å©ã¯ã©ã¹ãäœæããã«æ§æã䜿çšã§ããŸãã ããã¯ãããŸããŸãªããªã²ãŒãã«äžèŽããviewControllerãè¿œå ãããšãã«ãã䜿çšãããŸãã ã¯ã©ã¹èªäœã«ãããã³ã«é©åæ§ãè¿œå ããããšã®å©ç¹ã¯ãããé©åã«ç·šæãããã³ãŒãã§ãã
extension MyTableViewController: UITableViewDelegate { // UITableViewDelegate } extension MyTableViewController: UITableViewDataSource { // UITableViewDataSource } extension MyTableViewController: UITextFieldDelegate { // UITextFieldDelegate }
- ç¶æ¿ã®ä»£ããã«ãããã³ã«ã䜿çšããŸãã Dave Abrahamsã¯ãããã³ã«ãã¹ãŒããŒã¯ã©ã¹ãšæ¯èŒããŸãããããã¯ããããã³ã«ãè€æ°ã®ç¶æ¿ãèš±å¯ããããã§ãã
ã¯ã©ã¹ã«å€ãã®ããžãã¯ãå«ãŸããŠããå Žåã¯ããã°ã«èšé²ã§ããæ©èœã®å¥ã®ã»ããã«åé¡ãã䟡å€ããããŸãã
ãã¡ãããCocoaã®ãããªãµãŒãããŒãã£ã®ãã¬ãŒã ã¯ãŒã¯ã䜿çšããŠããå Žåãç¶æ¿ã¯é¿ããããŸããã
- é¡åã¢ããªã³ã°ã䜿çšããŸãã
åãã»ãã·ã§ã³ãSwiftã®ãããã³ã«æåããã°ã©ãã³ã°ãã®èå³æ·±ãäŸã§ãã CoreGraphicsã䜿çšããŠã¬ã³ããªã³ã°ããããã®Rendererãããã³ã«ãå®è£ ããã¯ã©ã¹ãäœæãã代ããã«ããã®ãããã³ã«ãžã®æºæ ãæ¡åŒµæ©èœãä»ããŠCGContextã¯ã©ã¹ã«è¿œå ãããŸãã ãããã³ã«ãå®è£ ããæ°ããã¯ã©ã¹ãè¿œå ããåã«ããããã³ã«æºæ ã«é©å¿ã§ããã¿ã€ãïŒã¯ã©ã¹/æ§é /åæåïŒããããã©ãããæ€èšããå¿ èŠããããŸããïŒ
- ãããã³ã«ã§ãªãŒããŒã©ã€ãã§ããã¡ãœãããå«ããŸãïŒ èŠä»¶ã«ããã«ã¹ã¿ãã€ãºãã€ã³ããäœæãããŸã ïŒã
ç¹å®ã®ã¯ã©ã¹ã®ãããã³ã«æ¡åŒµã§å®çŸ©ãããäžè¬çãªã¡ãœãããåå®çŸ©ããå¿ èŠãããå Žåã¯ããã®ã¡ãœããã®çœ²åããããã³ã«èŠä»¶ã«è»¢éããŠãã ããã ä»ã®ã¯ã©ã¹ã¯ç·šéããå¿ èŠã¯ãããŸããã æ¡åŒµæ©èœã®ã¡ãœãããåŒãç¶ã䜿çšããŸãã éãã¯èšèé£ãã«ãããŸã-çŸåšã¯ãæ¡åŒµã¡ãœãããã§ã¯ãªããããã©ã«ãã®å®è£ ã¡ãœãããã§ã ã
POPãšOOPã®éã
æœè±¡å
OOPã§ã¯ãã¯ã©ã¹ã¯æœè±¡ããŒã¿åã®åœ¹å²ãæãããŸãã POPã§ã¯ããããã³ã«ã
Appleã«ãããšãæœè±¡åãšããŠã®ãããã³ã«ã®å©ç¹ïŒã¹ã©ã€ãïŒ ãããè¯ãæœè±¡åã¡ã«ããºã ã ïŒïŒ
- å€åïŒããã³ã¯ã©ã¹ïŒããµããŒã
- éçåé¢ä¿ïŒããã³åçãã£ã¹ãããïŒããµããŒã
- éã¢ããªã·ãã¯
- é¡åã¢ããªã³ã°ããµããŒã
- ã¢ãã«ã«ã€ã³ã¹ã¿ã³ã¹ããŒã¿ã課ããŸãã
- ã¢ãã«ã«åæåã®è² æ ããããŸãã
- å®è£ ãããã®ãæ確ã«ããŸã
翻蚳
- å€åïŒããã³ã¯ã©ã¹ïŒã®ãµããŒã
- éçãªåé¢ä¿ïŒããã³åçãªãã£ã¹ãããïŒã®ãµããŒã
- ãã£ã¹ããªã
- é¡åã¢ããªã³ã°ã®ãµããŒã
- ãªããžã§ã¯ãããŒã¿ã課ããŸããïŒåºæ¬ã¯ã©ã¹ãã£ãŒã«ãïŒ
- åæåã«è² æ ããããªãã§ãã ããïŒåºæ¬ã¯ã©ã¹ïŒ
- å®è£ ãããã®ãæ確ã«ãªããŸã
ã«ãã»ã«å
-ã·ã¹ãã å ã®ããããã£ã§ãã¯ã©ã¹å ã§ããããšé£æºããããŒã¿ãšã¡ãœãããçµã¿åãããããšãã§ããŸãã
ãããã³ã«ã«ã¯ããŒã¿èªäœãå«ããããšã¯ã§ããŸããããã®ããŒã¿ãæäŸããããããã£ã®èŠä»¶ã®ã¿ãå«ããããšãã§ããŸãã OOPã®å Žåãšåæ§ã«ãå¿ èŠãªããŒã¿ã¯ã¯ã©ã¹/æ§é ã«å«ããå¿ èŠããããŸãããé¢æ°ã¯ã¯ã©ã¹ãšæ¡åŒµã®äž¡æ¹ã§å®çŸ©ã§ããŸãã
å€å
POP / swiftã¯ã2çš®é¡ã®ããªã¢ãŒãã£ãºã ããµããŒãããŠããŸãã
- ãµãã¿ã€ãå€åã OOPã§ã䜿çšãããŸãã
func process(service: ServiceType) { ... }
- ãã©ã¡ããªãã¯å€åã äžè¬çãªããã°ã©ãã³ã°ã§äœ¿çšãããŸãã
func process<Service: ServiceType>(service: Service) { ... }
åãå ¥ããããã¿ã€ããšãã®é¢é£ã¿ã€ãã®æ©èœã»ããã¯ãå¶éã«ãã£ãŠæ±ºå®ãããŸãã å¶éãå ããããšã¯ã§ããŸãããããã®å Žåããã©ã¡ãŒã¿ãŒã¯Anyã¿ã€ãã«äŒŒãŠããŸãã
func foo<T>(value: T) { ... }
ãµãã¿ã€ãããªã¢ãŒãã£ãºã ã®å Žåãé¢æ°ã«æž¡ãããç¹å®ã®ã¿ã€ãã¯ããããŸããããã®ã¿ã€ãã®ã¡ãœããã®å®è£ ã¯ãå®è¡æã«æ€åºãããŸãïŒ åçãã£ã¹ããã ïŒã ãã©ã¡ããªãã¯å€çžæ§ã䜿çšããå Žå-ãã©ã¡ãŒã¿ã®åã¯ããããã³ã³ãã€ã«æã«æ¢ç¥ã§ããããã®ã¡ãœããïŒ Static dispatch ïŒã 䜿çšãããåã¯ã¢ã»ã³ããªæ®µéã§æ¢ç¥ã§ãããšããäºå®ã«ãããã³ã³ãã€ã©ã¯ãäž»ã«ã€ã³ã©ã€ã³é¢æ°ã䜿çšããããšã§ãã³ãŒããããæé©åã§ããŸãã
ç¶æ¿
OOPç¶æ¿ã¯ã芪ã¯ã©ã¹ããæ©èœãåçšããããã«äœ¿çšãããŸãã
POPã§ã¯ãæ¡åŒµæ©èœãä»ããŠæ©èœãæäŸãããããã³ã«ã«å¯Ÿå¿ãè¿œå ããããšã«ãããå¿ èŠãªæ©èœãååŸãããŸãã åæã«ãã¯ã©ã¹ã«éå®ãããããããã³ã«ã«ããæ§é ãæ¡åŒµãåæããæ©èœããããŸãã
ãããã³ã«ã¯ä»ã®ãããã³ã«ããç¶æ¿ã§ããŸããããã¯ã芪ãããã³ã«ã®èŠä»¶ãç¬èªã®èŠä»¶ã«è¿œå ããããšãæå³ããŸãã
å®éã«POPã䜿çšããæ¹æ³ãèŠãŠã¿ãŸãããã
äŸ1
æåã®äŸã¯ã WWDC 2015-Session 411 Swift in Practiceã§çºè¡šãããSegueHandlerã®ã¢ããã°ã¬ãŒãçã§ãã
RootViewControllerããããDetailViewControllerããã³AboutViewControllerã®é·ç§»åŠçãè¡ãå¿ èŠããããšããŸãã prepareã®å žåçãªå®è£ ïŒforïŒsender :) ïŒ
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { switch segue.identifier { case "DetailViewController": guard let vc = segue.destination as? DetailViewController else { fatalError("Invalid destination view controller type.") } // configure vc case "AboutViewController": guard let vc = segue.destination as? AboutViewController else { fatalError("Invalid destination view controller type.") } // configure vc default: fatalError("Invalid segue identifier.") } }
idãDetailViewControllerãšAboutViewControllerã§åãååã®ã³ã³ãããŒã©ãŒã¯ã©ã¹ãæã€2ã€ã®é·ç§»ããæãŠãªãããšãããã£ãŠããŸãããäžæãªseque.identifierãã§ãã¯ãšsegue.destinationã®åå€æãè¡ãå¿ èŠããããŸãã
ãã®ã¡ãœããã®ã³ãŒããæ¹åããŠã¿ãŸãããã å¯èœãªé·ç§»ã®èª¬æããå§ããŸããã-enumã¯ããã«æé©ã§ãïŒ
enum SegueDestination { case detail(DetailViewController) case about(AboutViewController) }
ïŒæ³šïŒSegueDestinationã¯RootViewControllerå ã§å®£èšãããŸãïŒ
ç§ãã¡ã®ç®æšã¯ãé·ç§»ãåŠçããããã®æ±çšãã«ããŒã¡ãœãããèšè¿°ããããšã§ãã ãããè¡ãã«ã¯ãé·ç§»ãèšè¿°ããé¢é£ããã¿ã€ãã§SegueHandlerTypeãããã³ã«ãå®çŸ©ããŸãã é¢é£ä»ããããåã®èŠä»¶-ã»ã°ãšIDãšã³ã³ãããŒã©ãŒåã®ç¡å¹ãªçµã¿åããã®å Žåã«nilãè¿ã倱æå¯èœãªåæååãæäŸããå¿ èŠããããŸãã
protocol SegueHandlerType { associatedtype SegueDestination: SegueDestinationType } protocol SegueDestinationType { init?(segueId: String, controller: UIViewController) }
ãããã³ã«ãå®çŸ©ããã移è¡ã€ã³ã¹ã¿ã³ã¹ãè¿ãsegueDestinationïŒforSegue :)ã¡ãœãããè¿œå ããŸãã
extension SegueHandlerType { func segueDestination(forSegue segue: UIStoryboardSegue) -> SegueDestination { guard let id = segue.identifier else { fatalError("segue id should not be nil") } guard let destination = SegueDestination(segueId: id, controller: segue.destination) else { fatalError("Wrong segue Id or destination controller type") } return destination } }
RootViewControllerã«SegueHandlerTypeãå®è£ ãããŸãããïŒãã®äºçŽ°ãªã³ãŒããç®ãåŒãå¯èœæ§ãäœãããã«ãå¥ã®ãã¡ã€ã«ã«å ¥ããŠãã ããïŒïŒ
// file RootViewController+SegueHandler.swift extension RootViewController.SegueDestination: SegueDestinationType { init?(segueId: String, controller: UIViewController) { switch (segueId, controller) { case ("DetailViewController", let vc as DetailViewController): self = .detail(vc) case ("AboutViewController", let vc as AboutViewController): self = .about(vc) default: return nil } } } extension RootViewController: SegueHandlerType { }
SegueHandlerTypeã®relatedtypeãšRootViewControllerã®enumã¯åãååã§ãããããRootViewControllerã®SegueHandlerTypeã®å®è£ ã¯ç©ºã§ããããšã«æ³šæããŠãã ããã ç°ãªãååããããåæãRootViewControllerå ã§å®çŸ©ãããŠããªãå Žåãtypealiasã䜿çšããŠãããã³ã«ã«é¢é£ä»ããããã¿ã€ããæå®ããå¿ èŠããããŸãã
extension RootViewController: SegueHandlerType { typealias SegueDestination = RootControllerSegueDestination }
äŸã®æåŸã®éšå-ããã§æºåããªãã¡ã¯ã¿ãªã³ã°ã§ããŸãïŒforïŒsender :)ïŒ
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { switch segueDestination(forSegue: segue) { case .detail(let vc): // configure vc case .about(let vc): // configure vc } }
ã³ãŒãã¯ãã£ãšãããã§ãããïŒ
ãã¡ãããã³ãŒãã®çµæãšããŠãããã«å€ãããããŸããããã¡ã€ã³ããžãã¯ïŒ "// configure vc"ã³ã¡ã³ãã®åŸãã«é ãããŠããããžãã¯ïŒãšè£å©ã³ãŒããåé¢ããããšãã§ããŸããã é·æ-ã³ãŒããèªã¿ããããªããè£å©SegueHandlerTypeãåå©çšã§ããŸãã
äŸ2
UITableViewã§èŠçŽ ã®ãªã¹ãã衚瀺ããããã®å žåçãªã¿ã¹ã¯ãæ€èšããŠãã ããã
åæããŒã¿ãšããŠã Catã¢ãã«ãšã CatRepositoryãããã³ã«ã«å¯Ÿå¿ããTestCatRepositoryããããŸãã
struct Cat { var name: String var photo: UIImage? } protocol CatRepository { func getCats() -> [Cat] }
ããŒãã«ãšã»ã«ã³ã³ãããŒã©ãŒã¯ã©ã¹ããããžã§ã¯ãã«è¿œå ãããŸãïŒ CatListTableViewController ã CatTableViewCell ã
äžè¬åãªã¹ããããã³ã«ã説æããŠã¿ãŸãããã ä»ã®ããŒãã«ããããžã§ã¯ãã«è¿œå ããèšç»ããããšæ³åããŠãã ãããããã«ã¯ãããã€ãã®ã»ã¯ã·ã§ã³ãå«ãŸããŸãã ãããã³ã«èŠä»¶ïŒ
- ã»ã¯ã·ã§ã³å
ã®èŠçŽ ã®æ°ãèšå®ã§ããã¯ãã§ãã
- ã»ã¯ã·ã§ã³ã€ã³ããã¯ã¹ãšèŠçŽ ã€ã³ããã¯ã¹ã®ã¿ã€ããæå®ã§ããããã«ããå¿
èŠããããŸã-ãããã¯ä»»æã§ã-æ°å€ãåæãã¿ãã«ããããã«èŠä»¶ã課ããŸãã;
- ã»ã«ã¿ã€ã-èŠä»¶ã課ãããšããããTableViewCellã«ããããšãã§ããŸããããŒãã«ã§ç°ãªãã¿ã€ãã®ã»ã«ã䜿çšãããå Žåãç¹å®ã®ã¿ã€ãã®ã»ã«ãååŸããããã«ããè€éãªã¿ã€ãã«ããããšãã§ããŸãïŒç°ãªãã»ã«èå¥åïŒ
- ã»ã«ãæŽæ°ããèŠæ±ãåŠçããæ©èœ-æãç°¡åãªæ¹æ³ã¯ã2ã€ã®ãã©ã¡ãŒã¿ãŒïŒã»ã«ãšãã®ã€ã³ããã¯ã¹ïŒãæã€é¢æ°ã®åœ¢åŒã§ãã³ãã©ãŒãå²ãåœãŠãããšã§ãã
äœæãããèŠä»¶ãèæ ®ããŠããããã³ã«ãèšè¿°ããŸãã
protocol ListViewType: class { associatedtype CellView associatedtype SectionIndex associatedtype ItemIndex func refresh(section: SectionIndex, count: Int) var updateItemCallback: (CellView, ItemIndex) -> () { get set } }
ç«ã«é¢ããæ å ±ã衚瀺ããããã®ã»ã«ã®èŠä»¶ã説æããŸãããã
protocol CatCellType { func setName(_: String) func setImage(_: UIImage?) }
ãã®ãããã³ã«ãžã®éä¿¡ãCatTableViewCellã¯ã©ã¹ã«è¿œå ããŸãã
ã¡ã€ã³ãããã³ã«ã§ããListViewTypeãCatListTableViewControllerã«è¿œå ããå¿ èŠããããŸãã CatTableViewCellã®1ã€ã®ã¿ã€ãã®ã¿ã䜿çšããŠãããããé¢é£ä»ããããã¿ã€ãã®CellViewãšããŠäœ¿çšããŸãã ããŒãã«ã«ã¯ã»ã¯ã·ã§ã³ã1ã€ãããªããèŠçŽ ã®æ°ã¯äºåã«ããããŸãããSectionIndexãšItemIndexãšããŠãããããVoidãšIntã䜿çšããŸãã
CatListTableViewControllerã®å®å šãªå®è£ ïŒ
class CatListTableViewController: UITableViewController, ListViewType { var itemsCount = 0 var updateItemCallback: (CatTableViewCell, Int) -> () = { _, _ in } func refresh(section: Void, count: Int) { itemsCount = count tableView.reloadData() } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return itemsCount } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CatCell", for: indexPath) as! CatTableViewCell updateItemCallback(cell, indexPath.row) return cell } }
çŸåšã®ç®æšã¯ãCatRepositoryãšListViewTypeããªã³ã¯ããããšã§ãã ãã ããã¢ã«ãŽãªãºã ãç¹å®ã®Catã¢ãã«ã«é¢é£ä»ããããããŸããã ãããè¡ãããã«ãã¢ãã«ã¿ã€ããrelatedtypeã§ã¬ã³ããªã³ã°ãããäžè¬åããããããã³ã«ãåºå¥ããŸãã
protocol RepositoryType { associatedtype Model func getItems() -> [Model] } protocol ConfigurableViewType { associatedtype Model func configure(using model: Model) }
æ°ãããããã³ã«ãžã®ã³ã³ãã©ã€ã¢ã³ã¹ãè¿œå ããŸãã
extension CatRepository { func getItems() -> [Cat] { return getCats() } } extension TestCatRepository: RepositoryType { } extension CatCellType where Self: ConfigurableViewType { func configure(using model: Cat) { setName(model.name) setImage(model.photo) } } extension CatTableViewCell: ConfigurableViewType { }
ListViewTypeãªã¹ãã®RepositoryTypeã«ãã£ãŠæäŸããããªããžã§ã¯ãã衚瀺ããã¡ãœãããå®è£ ããæºåããã¹ãŠæŽããŸããã ã¢ã«ãŽãªãºã ã¯è€æ°ã®ã»ã¯ã·ã§ã³ããµããŒãããŸããããã€ã³ããã¯ã¹ãšããŠIntã䜿çšããŸãã æ¡åŒµæ©èœã«å¶éãè¿œå ããŸãã
extension ListViewType where SectionIndex == (), ItemIndex == Int { ... }
CatListTableViewControllerã¯ãããã®å¶éã«æºæ ããŠããŸãã
ãããããããã¯ãã¹ãŠã®å¶éã§ã¯ãããŸãã-ListViewType.CellViewã¯ConfigurableViewTypeã§ãªããã°ãªããããã®ã¢ãã«ã¿ã€ãã¯RepositoryType.Modelã§ãªããã°ãªããŸããïŒ
func setup<Repository: RepositoryType>(repository: Repository) where CellView: ConfigurableViewType, CellView.Model == Repository.Model { ... }
ãããŠãã¯ã©ã¹ã¯ãããã®å¶éãæºãããŠããŸãã
å®å šãªæ¡åŒµã³ãŒãïŒ
extension ListViewType where SectionIndex == (), ItemIndex == Int { func setup<Repository: RepositoryType>(repository: Repository) where CellView: ConfigurableViewType, CellView.Model == Repository.Model { let items = repository.getItems() refresh(section: (), count: items.count) updateItemCallback = { cell, index in let item = items[index] cell.configure(using: item) } } }
ã¡ã€ã³ããžãã¯ã®æºåãã§ããŸãããAppDelegateã§ãã®é¢æ°ã䜿çšããŸãã
let catListTableView = window!.rootViewController as! CatListTableViewController let repository = TestCatRepository() catListTableView.setup(repository: repository)
å®å šãªãµã³ãã«ã³ãŒãã¯ãã¡ãã«ãããŸã ã
ãã®äŸã§ã¯ãããžãã¯ã¯ãå šäœãšããŠæ©èœããå€ãã®å°ããªç¬ç«ããéšåã«åå²ãããŠããŸãã
ããžãã¯ã®ã»ãšãã©ã¯ã¯ã©ã¹ã§ã¯ãªãæ¡åŒµæ©èœã«ãããããäžèŠã©ã®ã¯ã©ã¹ãã©ã®è²¬ä»»ãè² ãã®ãã¯æ確ã§ã¯ãããŸããããããã£ãŠãçåãçããŸãããã®äŸã¯ã©ã®ã¢ãŒããã¯ãã£ã«èµ·å ããã®ã§ããããïŒäœ¿çšãããæ©èœã¯ãListViewTypeæ¡åŒµæ©èœã«ãããŸãããã®ããžãã¯ã¯ããã®ãããã³ã«ã«æºæ ããŠãããããCatListTableViewControllerã¯ã©ã¹ã§äœ¿çšã§ããŸããCatListTableViewControllerã®ã³ã³ã·ã¥ãŒããŒã¯ãããããã®æ©èœãšèŠãªããŸãã
catListTableView.setup(repository: repository)
ãããã£ãŠãCatListTableViewController-MVCã®ã³ã³ãããŒã©ãŒã®åœ¹å²ããããã£ãŠãã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£ã¯MVCã§ãããã³ãŒãã®æ§æã¯å€ãã£ãŠããŸãã
ãããã«
ãããã³ã«æåããã°ã©ãã³ã°ã¯ãæ±çšããã°ã©ãã³ã°ãšç¹æ§ã®æŠå¿µã«äŸåããŠããŸãã
POPã䜿çšãããšãã³ãŒãã®åå©çšæ§ãåäžããæ§é åãããã³ãŒããæ¹åãããã³ãŒãã®éè€ãæžå°ããã¯ã©ã¹ç¶æ¿éå±€ã®è€éããåé¿ãããã³ãŒãã®æ¥ç¶æ§ãåäžããŸãã
ãœãŒã¹ïŒ