ダックタイピングとidでUserDefaultsをモック化する

7a78f23eef1b0e883ef44c229a54f0bb?s=47 417.72KI
September 05, 2019

 ダックタイピングとidでUserDefaultsをモック化する

7a78f23eef1b0e883ef44c229a54f0bb?s=128

417.72KI

September 05, 2019
Tweet

Transcript

  1. 2.

    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
  2. 6.

    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 {}
  3. 7.

    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 } ɾ ɾ ɾ }
  4. 8.

    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
  5. 9.

    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
  6. 18.

    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]; }
  7. 21.

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

    } walkAndQuack([Duck new]); walkAndQuack([Dog new]); *ODPNQBUJCMFQPJOUFSUZQFTQBTTJOH%PH  UPQBSBNFUFSPGUZQF%VDL  ܯࠂ͕ग़Δ͚ͩͰϏϧυ͸௨Δ
  8. 25.

    @protocol UITableViewDataSource<NSObject> @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ͱμοΫλΠϐϯά ࣮૷Λڧ੍͠ͳ͍ϝιου܈
  9. 26.

    @implementation UITableView ɾ ɾ ɾ - (NSInteger)numberOfSections { if ([self.dataSource

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

    %FMFHBUFͱμοΫλΠϐϯά @interface HogeViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> @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 ϓϩτίϧએݴ σϦήʔτϝιου
  11. 28.

    %FMFHBUFͱμοΫλΠϐϯά @interface HogeViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> @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͸
  12. 29.

    %FMFHBUFͱμοΫλΠϐϯά @interface HogeViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> @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͕࣮૷͞ΕͯΛฦ͢Α͏ʹ
  13. 30.

    @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$POUSPMMFS DPOTU@@TUSPOH ϓϩτίϧએݴΛফͯ͠Έͨ৔߹ ܯࠂ͕ग़Δ͚ͩͰϏϧυ͸௨Δ Ϋϥογϡ΋ͤͣ5BCMF7JFXͱͯ͠ػೳ͢Δ
  14. 31.
  15. 33.

    NSArray *array = @[ @{@"hoge":@"fuga"}, ]; for (NSObject *obj in

    array) { NSLog([obj objectForKey:@"hoge"]); } JEܕͷԸܙ /PWJTJCMF!JOUFSGBDFGPS/40CKFDUEFDMBSFTUIFTFMFDUPSPCKFDU'PS,FZ
  16. 34.

    NSArray *array = @[ @{@"hoge":@"fuga"}, ]; for (NSObject *obj in

    array) { NSLog([(NSDictionary *)obj objectForKey:@"hoge"]); } JEܕͷԸܙ Ωϟετ͢Δ͜ͱͰݺͼग़ͤΔΑ͏ʹ
  17. 35.

    NSArray *array = @[ @{@"hoge":@"fuga"}, ]; for (id obj in

    array) { NSLog([obj objectForKey:@"hoge"]); } JEܕͷԸܙ Ωϟετͤͣʹ/4%JDUJPOBSZͱͯ͠ѻ͏͜ͱ͕Ͱ͖Δ
  18. 36.

    NSArray *array = @[ @{@"hoge":@"fuga"}, ]; for (NSDictionary *obj in

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

    NSArray *array = @[ @{@"hoge":@"fuga"}, @"hogehoge" ]; for (NSDictionary *obj

    in array) { NSLog([obj objectForKey:@"hoge"]); } JEܕͷԸܙ GVHB
  20. 38.

    NSArray *array = @[ @{@"hoge":@"fuga"}, @"hogehoge" ]; for (NSDictionary *obj

    in array) { NSLog([obj objectForKey:@"hoge"]); } JEܕͷԸܙ VOSFDPHOJ[FETFMFDUPSTFOUUPJOTUBODF
  21. 39.

    NSArray <NSDictionary <NSString *, id> *> *array = @[ @{@"hoge":@"fuga"},

    @"hogehoge" ]; for (NSDictionary <NSString *, id> *obj in array) { NSLog([obj objectForKey:@"hoge"]); } -JHIUXFJHIU(FOFSJDT 0CKFDUPGUZQF/44USJOH JTOPUDPNQBUJCMFXJUIBSSBZ FMFNFOUUZQF/4%JDUJPOBSZ/44USJOH JE 
  22. 44.
  23. 48.

    ࢀߟจݙ w μοΫɾλΠϐϯά 8JLJQFEJB 
 IUUQTKBXJLJQFEJBPSHXJLJ &&&"'&##& #'&"&&#& # 

    w JEܕͱ͸ಈత݁߹ͷ֓೦
 IUUQTKQSPHSBNFSDPNPCKFDUJWFD  w ·ͭ΋ͱ௚఻ɹϓϩάϥϛϯάͷΦΩςୈճʢʣ
 IUUQTUFDIOJLLFJCQDPKQJUBSUJDMF$0-6./