Using Protocol to Refactor
28
Using Protocol to Refactor 邱志強, Green Chiu, iOS Developer.
-
Upload
green-chiu -
Category
Engineering
-
view
80 -
download
2
Transcript of Using Protocol to Refactor
- 1. Using Protocol to Refactor , Green Chiu, iOS Developer.
- 2. iOS Protocol ?
- 3. ?
- 4. Delegation ?
- 5. ?
- 6. Delegation Pattern Apple CocoaTouch SDK UITableView, UICollectionView, UIGestureRecognizer and so on. NSURLSession, StoreKit
- 7. NS-Protocols archive, copy, enumerate NSCopying NSCoding NSFastEnumeration
- 8. Objective-C/Swift Protocols method
- 9. Protocol in Objective-C @protocol SampleProtocol - (void)sampleMethodA; - (void)sampleMethodB; @optional - (void)sampleOptionalMethod; @end
- 10. Protocol class method
- 11. The End
- 12. /
- 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. 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. Issues View or Model classes/framework
- 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. 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. 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. Finally - (void)loadSongInfo:(UPLocalSongInfo *)inSongInfo { [self.albumCoverImageView loadImageWithImageProvider:inSongInfo]; }
- 20. Besides Protocol Mock
- 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. 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. 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. This is Protocol-Oriented Programming
- 25. One more thing
- 26. We are hiring iOS Developer and others
- 27. Thanks