Top Banner
Using Protocol to Refactor 邱志強, Green Chiu, iOS Developer.
28

Using Protocol to Refactor

Jan 29, 2018

Download

Engineering

Green Chiu
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
  1. 1. Using Protocol to Refactor , Green Chiu, iOS Developer.
  2. 2. iOS Protocol ?
  3. 3. ?
  4. 4. Delegation ?
  5. 5. ?
  6. 6. Delegation Pattern Apple CocoaTouch SDK UITableView, UICollectionView, UIGestureRecognizer and so on. NSURLSession, StoreKit
  7. 7. NS-Protocols archive, copy, enumerate NSCopying NSCoding NSFastEnumeration
  8. 8. Objective-C/Swift Protocols method
  9. 9. Protocol in Objective-C @protocol SampleProtocol - (void)sampleMethodA; - (void)sampleMethodB; @optional - (void)sampleOptionalMethod; @end
  10. 10. Protocol class method
  11. 11. The End
  12. 12. /
  13. 13. Class LocalPlaylistInfo - (void)fetchPlaylistCoverImageWithSize { if () { UIImage *image = nil; DBMetaReference *ref = ; if (ref.sourceType == ) { DBMetaItem *item = ; } else if (ref.sourceType == ) { MPMediaItem *item = ; image = [item.artwork imageWith ]; } else if (ref.sourceType == LocalDBContextSongSourceTypeStore) { DBMetaItem *item = ; if (!item) { return; } NSString *imageFileURLString = ; void (^imageCallback)(NSString *fileURLString, UIImage *image) = ^(NSString *fileURLString, UIImage *image) { if (image ) { } else if ([NSURL URLWithString:item.photoURL]) { [[KKRadioImageManager sharedImageManager] fetchImageWithURL: requester:nil callback:^(UIImage *receiveImage, NSError *error) { if (receiveImage) { } }]; } };
  14. 14. Class SongInfoViewModel - (void)loadSongInfo:(LocalSongInfo *)inSongInfo { if (inSongInfo.type == LocalDBContextSongSourceTypeStore || ...) { DBMetaItem *item = inSongInfo.rawItem; if (inSongInfo.type == LocalDBContextSongSourceTypeStore) { } else { } self.imageFileURLString = ; void (^imageCallback)(NSString *fileURLString, UIImage *image) = ^void(NSString *fileURLString, UIImage *image){ if (image) { weakSelf.albumCoverImage = cropImage; } else if ([NSURL URLWithString:item.photoURL]) { [[KKRadioImageManager sharedImageManager] fetchImageWithURL: requester:nil callback:^(UIImage *receiveImage, NSError *error) { if (receiveImage) { weakSelf.albumCoverImage = } }]; } }; return; } if (inSongInfo.image) { }
  15. 15. Issues View or Model classes/framework
  16. 16. Design Protocol typedef NS_ENUM(NSInteger, ProvideImageWay) { ProvideImageWayNone = NSNotFound, ProvideImageWayFetchWithURLString = 0, ProvideImageWayGetWithSize, ProvideImageWayGenerateWithCallback }; @protocol LocalItemImageProvider - (ProvideImageWay)getCoverImageWay; - (NSString *)coverURLString; - (UIImage *)coverImageWithSize:(CGSize)inSize; - (void)generateImageWithCallback:(void(^)(UIImage *))inCallback; @end
  17. 17. After implemented - (void)loadSongInfo:(LocalSongInfo *)inSongInfo { switch ([inSongInfo getCoverImageWay]) { case UPProvideImageWayGetWithSize: self.albumCoverImageView.image = [inSongInfo coverImageWithSize:CGSizeMake()]; break; case UPProvideImageWayGenerateWithCallback: { __weak typeof(self) weakSelf = self; [inSongInfo generateImageWithCallback:^(UIImage *image) { weakSelf.albumCoverImageView.image = image; }]; break; } case UPProvideImageWayFetchWithURLString: break; case UPProvideImageWayNone: break; } }
  18. 18. Optimized // UIImageView+LocalItemImageProvider.m - (void)loadImageWithImageProvider:(id)inImageProvider { if (![inImageProvider conformsToProtocol:@protocol(LocalItemImageProvider)]) { return; } switch ([inImageProvider getCoverImageWay]) { case ProvideImageWayGetWithSize: self.image = [inImageProvider coverImageWithSize:CGSizeMake(44, 44)]; break; case ProvideImageWayGenerateWithCallback: { __weak typeof(self) weakSelf = self; [inImageProvider generateImageWithCallback:^(UIImage *image) { weakSelf.image = image; }]; break; } case ProvideImageWayFetchWithURLString: [self fetchImageWithURLString:[inImageProvider coverURLString]]; break; case ProvideImageWayNone: default: break; } }
  19. 19. Finally - (void)loadSongInfo:(UPLocalSongInfo *)inSongInfo { [self.albumCoverImageView loadImageWithImageProvider:inSongInfo]; }
  20. 20. Besides Protocol Mock
  21. 21. Testing // UIImageView+LocalItemImageProvider.m - (void)loadImageWithImageProvider:(id)inImageProvider { if (![inImageProvider conformsToProtocol:@protocol(LocalItemImageProvider)]) { return; } switch ([inImageProvider getCoverImageWay]) { case ProvideImageWayGetWithSize: self.image = [inImageProvider coverImageWithSize:CGSizeMake(44, 44)]; break; case ProvideImageWayGenerateWithCallback: { __weak typeof(self) weakSelf = self; [inImageProvider generateImageWithCallback:^(UIImage *image) { weakSelf.image = image; }]; break; } case ProvideImageWayFetchWithURLString: [self fetchImageWithURLString:[inImageProvider coverURLString]]; break; case ProvideImageWayNone: default: break; } }
  22. 22. Testing @interface TCDummyLocalImageProvider: NSObject - (instancetype)initWithType:(ProvideImageWay)inWay; @end @implementation TCDummyLocalImageProvider { ProvideImageWay way; } - (instancetype)initWithType:(ProvideImageWay)inWay { self = [super init]; if (self) { way = inWay; } return self; } - (ProvideImageWay)getCoverImageWay { return way; } ... @end
  23. 23. Testing - (void)testUIImageLoadImageWithImageProvider { UIImageView *imageView = [[UIImageView alloc] init]; [imageView loadImageWithImageProvider:[NSObject new]]; [imageView loadImageWithImageProvider:[[TCDummyLocalImageProvider alloc] initWithWay:-1000]]; [imageView loadImageWithImageProvider:[[TCDummyLocalImageProvider alloc] initWithWay:ProvideImageWayGetWithSize]]; [imageView loadImageWithImageProvider:[[TCDummyLocalImageProvider alloc] initWithWay:...]]; }
  24. 24. This is Protocol-Oriented Programming
  25. 25. One more thing
  26. 26. We are hiring iOS Developer and others
  27. 27. Thanks