Slide 1

Slide 1 text

μοΫλΠϐϯάͱJEͰ 6TFS%FGBVMUTΛϞοΫԽ͢Δ J04%$+BQBOEBZ5SBDL&

Slide 2

Slide 2 text

struct Me { let name = "Takuhiro Muta" let aka = "417.72KI" let twitter = "417_72ki" let qiita = "417_72ki" let gitHub = "417-72KI" let products = [ "BuildConfig.swift", "MockUserDefaults", ] let workAt = [ "Rhizome Inc.": "2014/04~2018/01", "iRidge Inc.": "2018/02~2019/08", "WealthNavi Inc.": "2019/09~", ] } TFMGEFTDSJQUJPO

Slide 3

Slide 3 text

"HFOEB w ςετͱ6TFS%FGBVMUT w μοΫλΠϐϯά w JEܕ w .PDL6TFS%FGBVMUT

Slide 4

Slide 4 text

ςετͱ6TFS%FGBVMUT

Slide 5

Slide 5 text

ςετͱ6TFS%FGBVMUT w 6OJU5FTUΛߟ͑Δ্Ͱ6TFS%FGBVMUTͷѻ͍͸ॏཁ w 6TFS%FGBVMUTΛ5FTUBCMFʹ͍ͨ͠ w QSPUPDPMΛט·ͤΔ w TVJUF/BNFΛ࢖͏

Slide 6

Slide 6 text

QSPUPDPMΛט·ͤΔ protocol UserDefaultsProtocol: class { func object(forKey defaultName: String) -> Any? func set(_ value: Any?, forKey defaultName: String) func string(forKey defaultName: String) -> String? ɾ ɾ ɾ } extension UserDefaults: UserDefaultsProtocol {}

Slide 7

Slide 7 text

QSPUPDPMΛט·ͤΔ class MockUserDefaults { private var mockDictionary: [String: Any] = [:] } extension MockUserDefaults: UserDefaultsProtocol { func object(forKey defaultName: String) -> Any? { return mockDictionary[defaultName] } func set(_ value: Any?, forKey defaultName: String) { mockDictionary[defaultName] = value } ɾ ɾ ɾ }

Slide 8

Slide 8 text

QSPUPDPMΛט·ͤΔ protocol UseCase { var userDefaults: UserDefaultsProtocol { get } func doSomething() } extension UseCase { func doSomething() { userDefaults.set("bar", forKey: "foo") } } class MixInUseCase: UseCase { let userDefaults: UserDefaultsProtocol = UserDefaults.standard } class TestUseCase: UseCase { let userDefaults: UserDefaultsProtocol = MockUserDefaults() } "QQ 5FTU

Slide 9

Slide 9 text

TVJUF/BNFΛ࢖͏ protocol UseCase { var userDefaults: UserDefaults { get } func doSomething() } extension UseCase { func doSomething() { userDefaults.set("bar", forKey: "foo") } } class MixInUseCase: UseCase { let userDefaults: UserDefaults = .standard } class TestUseCase: UseCase { let userDefaults: UserDefaults = .init(suiteName: "Mock")! } "QQ 5FTU

Slide 10

Slide 10 text

ςετͱ6TFS%FGBVMUT w 6TFS%FGBVMUTΛ5FTUBCMFʹ͍ͨ͠ w QSPUPDPMΛט·ͤΔ w طʹ6TFS%FGBVMUTΛϓϩύςΟͱͯ͠࢖༻͍ͯ͠Δ ৔߹ɺطଘίʔυʹखΛೖΕΔඞཁ͕͋Δ w TVJUF/BNFΛ࢖͏ w /4)PNF%JSFDUPSZ -JCSBSZ1SFGFSFODFT TVJUF/BNF QMJTU͕࡞੒͞ΕΔ w ςετͰӬଓྖҬΛ͍͡Γͨ͘͸ͳ͍

Slide 11

Slide 11 text

ςετͱ6TFS%FGBVMUT w 6TFS%FGBVMUTΛ5FTUBCMFʹ͍ͨ͠ w QSPUPDPMΛט·ͤΔ w TVJUF/BNFΛ࢖͏ w μοΫλΠϐϯάΛ࢖ͬͨࠇຐज़

Slide 12

Slide 12 text

μοΫλΠϐϯά

Slide 13

Slide 13 text

μοΫλΠϐϯά w ܕ෇͚ʹؔ͢Δߟ͑ํͷҰͭ w ಈతܕ෇͚ݴޠͰ࢖ΘΕΔ FH3VCZ 1ZUIPO w ΦϒδΣΫτࣗମ͕ϝιου΍ϓϩύςΟΛ͔࣋ͭͰ൑ఆ OPUܕ r%BWF5IPNBT l*GJUXBMLTMJLFBEVDLBOERVBDLTMJLFBEVDL JUNVTUCFBEVDLz

Slide 14

Slide 14 text

Ұൠతͳ੩తܕ෇͚ ී௨ʹΫϥεࢦఆ ݘʹରͯ͠ ૸Εʂ ϫϯʂ

Slide 15

Slide 15 text

Ұൠతͳ੩తܕ෇͚ JOUFSGBDFʹΑΔந৅Խ ಈ෺ʹରͯ͠ ૸Εʂ ϫϯʂ

Slide 16

Slide 16 text

μοΫλΠϐϯάʹΑΔ ಈతܕ෇͚ Կ͔͸஌ΒΜ͕ͱΓ͋͑ͣ ૸Εʂ Կ͔͸෼͔Βͳ͍͚Ͳ ૸ΕͬͯݴΘΕͨΒ ૸Δ͸ͣ

Slide 17

Slide 17 text

ϫϯʂ μοΫλΠϐϯάʹΑΔ ಈతܕ෇͚ Կ͔͸஌ΒΜ͕ͱΓ͋͑ͣ ૸Εʂ

Slide 18

Slide 18 text

0CKFDUJWF$ʹ͓͚Δ μοΫλΠϐϯά @interface Duck: NSObject - (void)walk; - (void)quack; @end @implementation Duck - (void)walk { NSLog(@"Duck walking"); } - (void)quack { NSLog(@"Quack!!"); } @end @interface Dog: NSObject - (void)walk; - (void)bark; @end @implementation Dog - (void)walk { NSLog(@"Dog walking"); } - (void)bark { NSLog(@"Bark!!"); } @end void walkAndQuack(id duck) { [duck walk]; [duck quack]; }

Slide 19

Slide 19 text

0CKFDUJWF$ʹ͓͚Δ μοΫλΠϐϯά walkAndQuack([Duck new]); // Duck walking // Quack!! walkAndQuack([Dog new]); // Dog walking // unrecognized selector sent to instance

Slide 20

Slide 20 text

0CKFDUJWF$ʹ͓͚Δ μοΫλΠϐϯά void walkAndQuack(id duck) { [duck walk]; [duck quack]; } walkAndQuack([Duck new]); walkAndQuack([Dog new]);

Slide 21

Slide 21 text

0CKFDUJWF$ʹ͓͚Δ μοΫλΠϐϯά void walkAndQuack(Duck *duck) { [duck walk]; [duck quack]; } walkAndQuack([Duck new]); walkAndQuack([Dog new]); *ODPNQBUJCMFQPJOUFSUZQFTQBTTJOH%PH UPQBSBNFUFSPGUZQF%VDL ܯࠂ͕ग़Δ͚ͩͰϏϧυ͸௨Δ

Slide 22

Slide 22 text

0CKFDUJWF$ͷܕγεςϜ w ऑ͍੩తܕ෇͚ w ࣮ߦ࣌ʹܕͷνΣοΫΛ͠ͳ͍ w ܕ͕Ұக͠ͳ͍ΦϒδΣΫτΛ୅ೖͯ͠΋
 ίϯύΠϧΤϥʔʹͳΒͳ͍ ܯࠂͷΈ w ϝιουΛݺͿࡍʹ໰୊͕͋ΔͱΫϥογϡ͢Δ w +BWB΍4XJGU͸ڧ͍੩తܕ෇͚

Slide 23

Slide 23 text

ڧ͍ܕ෇͚ͱऑ͍ܕ෇͚ 4USJOH < ߴࡔึ೫Ռ Ҁ੉ֆཬ > ऑ͍ܕ෇͚ ڧ͍ܕ෇͚

Slide 24

Slide 24 text

ऑ͍ܕ෇͚ w ࣮ߦ࣌ʹܕͷνΣοΫΛ͠ͳ͍ w ܕͷνΣοΫΛͤͣʹϝιουΛ࣮ߦ͢Δ w ֨ೲ͞Ε͍ͯΔΦϒδΣΫτ͕ͦͷϝιουΛ࣮ߦͰ ͖Ε͹0, %FMFHBUF

Slide 25

Slide 25 text

@protocol UITableViewDataSource @required - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; @optional - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; - (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; ɾ ɾ ɾ %FMFHBUFͱμοΫλΠϐϯά ࣮૷Λڧ੍͠ͳ͍ϝιου܈

Slide 26

Slide 26 text

@implementation UITableView ɾ ɾ ɾ - (NSInteger)numberOfSections { if ([self.dataSource respondsToSelector:@selector(numberOfSectionsInTableView:)]) { return [self.dataSource numberOfSectionsInTableView:self]; } else { return 1; } } ɾ ɾ ɾ @end %FMFHBUFͱμοΫλΠϐϯά ϝιου͕࣮૷͞Ε͍ͯΔ͔νΣοΫ

Slide 27

Slide 27 text

%FMFHBUFͱμοΫλΠϐϯά @interface HogeViewController : UIViewController @property (nonatomic, weak) IBOutlet UITableView *tableView; @end @implementation HogeViewController - (void)viewDidLoad { [super viewDidLoad]; self.tableView.dataSource = self; self.tableView.delegate = self; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { ɾɾɾ } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { ɾɾɾ } @end ϓϩτίϧએݴ σϦήʔτϝιου

Slide 28

Slide 28 text

%FMFHBUFͱμοΫλΠϐϯά @interface HogeViewController : UIViewController @property (nonatomic, weak) IBOutlet UITableView *tableView; @end @implementation HogeViewController - (void)viewDidLoad { [super viewDidLoad]; self.tableView.dataSource = self; self.tableView.delegate = self; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { ɾɾɾ } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { ɾɾɾ } @end OVNCFS0G4FDUJPOT*O5BCMF7JFX͕࣮૷͞Ε͍ͯͳ͍ͷͰTFDUJPO͸

Slide 29

Slide 29 text

%FMFHBUFͱμοΫλΠϐϯά @interface HogeViewController : UIViewController @property (nonatomic, weak) IBOutlet UITableView *tableView; @end @implementation HogeViewController - (void)viewDidLoad { [super viewDidLoad]; self.tableView.dataSource = self; self.tableView.delegate = self; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 2 } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { ɾɾɾ } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { ɾɾɾ } @end OVNCFS0G4FDUJPOT*O5BCMF7JFX͕࣮૷͞ΕͯΛฦ͢Α͏ʹ

Slide 30

Slide 30 text

@interface HogeViewController : UIViewController @property (nonatomic, weak) IBOutlet UITableView *tableView; @end @implementation HogeViewController - (void)viewDidLoad { [super viewDidLoad]; self.tableView.dataSource = self; self.tableView.delegate = self; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 2 } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { ɾɾɾ } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { ɾɾɾ } @end %FMFHBUFͱμοΫλΠϐϯά "TTJHOJOHUPJE6*5BCMF7JFX%BUB4PVSDF@/VMMBCMFGSPN JODPNQBUJCMFUZQF)PHF7JFX$POUSPMMFSDPOTU@@TUSPOH ϓϩτίϧએݴΛফͯ͠Έͨ৔߹ ܯࠂ͕ग़Δ͚ͩͰϏϧυ͸௨Δ Ϋϥογϡ΋ͤͣ5BCMF7JFXͱͯ͠ػೳ͢Δ

Slide 31

Slide 31 text

JEܕ

Slide 32

Slide 32 text

JEܕ w 0CKFDUJWF$ಠࣗͷ൚༻σʔλܕ w +BWBͰݴ͏0CKFDUɺ4XJGUͰݴ͏"OZ w ΦϒδΣΫτͷϙΠϯλΛอ࣋ w Ωϟετ͢Δ͜ͱͳ͘୅ೖ΍ϝιουݺͼग़͕͠Մೳ w ܕ҆શੑΛࣺͯͯॊೈੑʹεςʔλεΛৼͬͯΔ

Slide 33

Slide 33 text

NSArray *array = @[ @{@"hoge":@"fuga"}, ]; for (NSObject *obj in array) { NSLog([obj objectForKey:@"hoge"]); } JEܕͷԸܙ /PWJTJCMF!JOUFSGBDFGPS/40CKFDUEFDMBSFTUIFTFMFDUPSPCKFDU'PS,FZ

Slide 34

Slide 34 text

NSArray *array = @[ @{@"hoge":@"fuga"}, ]; for (NSObject *obj in array) { NSLog([(NSDictionary *)obj objectForKey:@"hoge"]); } JEܕͷԸܙ Ωϟετ͢Δ͜ͱͰݺͼग़ͤΔΑ͏ʹ

Slide 35

Slide 35 text

NSArray *array = @[ @{@"hoge":@"fuga"}, ]; for (id obj in array) { NSLog([obj objectForKey:@"hoge"]); } JEܕͷԸܙ Ωϟετͤͣʹ/4%JDUJPOBSZͱͯ͠ѻ͏͜ͱ͕Ͱ͖Δ

Slide 36

Slide 36 text

NSArray *array = @[ @{@"hoge":@"fuga"}, ]; for (NSDictionary *obj in array) { NSLog([obj objectForKey:@"hoge"]); } JEܕͷԸܙ /4%JDUJPOBSZͱͯ͠औΓग़ͤΔ ॊೈੑͷߴ͍ίʔσΟϯά͕Մೳʹ

Slide 37

Slide 37 text

NSArray *array = @[ @{@"hoge":@"fuga"}, @"hogehoge" ]; for (NSDictionary *obj in array) { NSLog([obj objectForKey:@"hoge"]); } JEܕͷԸܙ GVHB

Slide 38

Slide 38 text

NSArray *array = @[ @{@"hoge":@"fuga"}, @"hogehoge" ]; for (NSDictionary *obj in array) { NSLog([obj objectForKey:@"hoge"]); } JEܕͷԸܙ VOSFDPHOJ[FETFMFDUPSTFOUUPJOTUBODF

Slide 39

Slide 39 text

NSArray *> *array = @[ @{@"hoge":@"fuga"}, @"hogehoge" ]; for (NSDictionary *obj in array) { NSLog([obj objectForKey:@"hoge"]); } -JHIUXFJHIU(FOFSJDT 0CKFDUPGUZQF/44USJOHJTOPUDPNQBUJCMFXJUIBSSBZ FMFNFOUUZQF/4%JDUJPOBSZ/44USJOH JE

Slide 40

Slide 40 text

6TFS%FGBVMUTͱμοΫλΠϐϯά

Slide 41

Slide 41 text

w ऑ͍੩తܕ෇͚ w ࣮ߦ࣌ʹܕͷνΣοΫΛ͠ͳ͍ w ܕͷνΣοΫΛͤͣʹϝιουΛ࣮ߦ͢Δ w ֨ೲ͞Ε͍ͯΔΦϒδΣΫτ͕ͦͷϝιουΛ࣮ߦͰ͖Ε͹0, 6TFS%FGBVMUTͱμοΫλΠϐϯά /46TFS%FGBVMUT͕͍࣋ͬͯΔ ϝιουΛͦͬ͘ΓਅࣅͨΫϥεΛ࡞ِͬͯ૷ͯ͋͛͠Δ

Slide 42

Slide 42 text

.PDL6TFS%FGBVMUT

Slide 43

Slide 43 text

.PDL6TFS%FGBVMUT IUUQTHJUIVCDPN,*.PDL6TFS%FGBVMUT

Slide 44

Slide 44 text

%FNP

Slide 45

Slide 45 text

஫ҙ w μοΫλΠϐϯάࣗମ͸͋͘·Ͱख๏ ߟ͑ํ Ͱ͋Γɺ
 ภʹࠇຐज़ͩͱ͸ݴ͍੾Εͳ͍ w ࣮ࡍɺ1ZUIPO΍1)1ͳͲͷಈతܕ෇͚ܥݴޠͰ͸͜ͷ ߟ͑ํʹج͍ͮͨϓϩάϥϛϯά͕ߦΘΕΔ w ࢍ൱͸͋Δ͕ɺ͜ΕͰϙϦϞʔϑΟζϜΛ࣮ݱ͍ͯ͠Δ ͱ͍͏આ΋͋Δ

Slide 46

Slide 46 text

·ͱΊ w 0CKFDUJWF$͸ऑ͍ܕ෇͚ͳͷͰશؔ͘܎ແ͍ΫϥεͷΦ ϒδΣΫτΛ୅ೖͰ͖Δ w μοΫλΠϐϯάʹΑͬͯ/46TFS%FGBVMUTͱಉ͡ϝ ιουΛએݴͨ͠ผͷΫϥεΛએݴِͯ͠૷͕Մೳʹ w JEܕΛ࢖͏͜ͱͰΩϟετ΋ෆཁ

Slide 47

Slide 47 text

5IBOLZPV IUUQTHJUIVCDPN,*.PDL6TFS%FGBVMUT

Slide 48

Slide 48 text

ࢀߟจݙ w μοΫɾλΠϐϯά 8JLJQFEJB 
 IUUQTKBXJLJQFEJBPSHXJLJ &&&"'&##& #'&"&&#& # w JEܕͱ͸ಈత݁߹ͷ֓೦
 IUUQTKQSPHSBNFSDPNPCKFDUJWFD w ·ͭ΋ͱ௚఻ɹϓϩάϥϛϯάͷΦΩςୈճʢʣ
 IUUQTUFDIOJLLFJCQDPKQJUBSUJDMF$0-6./

Slide 49

Slide 49 text

ʲॏཁͳ஫ҙࣄ߲ʳ ɾຊࢿྉ͸ɺஅఆత൑அΛఏڙ͢Δ΋ͷͰ͸ͳ͘ɺ৘ใΛఏڙ͢Δ͜ͱͷΈΛ໨తͱ͓ͯ͠Γɺ͍͔ͳΔछྨ ͷ঎඼΋ק༠͢Δ΋ͷͰ͸͋Γ·ͤΜɻ࠷ऴతͳܾఆ͸ɺ͓٬༷ࣗ਎Ͱ൑அ͢Δ΋ͷͱ͠ɺ౰ࣾ͸͜ΕʹҰ੾ ؔ༩ͤͣɺ·ͨɺҰ੾ͷ੹೚Λෛ͍·ͤΜɻ ɾຊࢿྉʹ͸কདྷͷग़དྷࣄʹؔ͢Δ༧૝ؚ͕·Ε͍ͯΔ৔߹͕͋Γ·͕͢ɺͦΕΒ͸༧૝Ͱ͋Γɺ·ͨɺຊࢿ ྉͷ಺༰ͷਖ਼֬ੑɺ৴པੑɺ׬શੑɺద࣌ੑ౳ΛҰ੾อূ͢Δ΋ͷͰ͸͋Γ·ͤΜɻຊࢿྉʹج͍ͮͯඃͬͨ ͍͔ͳΔଛ֐ʹ͍ͭͯ΋ɺ౰ࣾ͸Ұ੾ͷ੹೚Λෛ͍·ͤΜɻ·ͨɺ౰ࣾ͸ɺ৽͍͠৘ใ΍কདྷͷग़དྷࣄͦͷଞ ͷ৘ใʹ͍ͭͯɺߋ৽ຢ͸గਖ਼͢Δٛ຿Λෛ͍·ͤΜɻ ɾຊࢿྉΛར༻͢Δ͜ͱʹΑΓ͓٬༷ʹੜͨ͡௚઀తଛ֐ɺؒ઀తଛ֐ɺ೿ੜతଛ֐ͦͷଞ͍͔ͳΔଛ֐ʹͭ ͍ͯ΋ɺ౰ࣾ͸Ұ੾ͷ੹೚Λෛ͍·ͤΜɻ ঎߸౳ɿ΢ΣϧεφϏגࣜձࣾۚ༥঎඼औҾۀऀؔ౦ࡒ຿ہ௕ʢۚ঎ʣୈ߸ Ճೖڠձɿ೔ຊূ݊ۀڠձҰൠࣾஂ๏ਓ೔ຊ౤ࢿސ໰ۀڠձ