HXPhotoPickerObjC

照片/视频选择器 - 支持LivePhoto、GIF图片选择、自定义编辑照片/视频、3DTouch预览、浏览网络图片/网络视频 功能 - Imitation weibo photo/image picker - support for LivePhoto, GIF image selection, 3DTouch preview, browse the web image function

APACHE-2.0 License

Stars
37

- Features

  • GIF
  • /
  • 3DTouch
  • LivePhoto iOS9.1
  • iCloud
  • Cell
  • XibMasonry
  • item

- Installation

# Podfile
# 
pod 'HXPhotoPickerObjC', '~> 3.3.4'
  
# SDWebImage
pod 'HXPhotoPickerObjC/SDWebImage', '~> 3.3.4'
  
# YYWebImage
pod 'HXPhotoPickerObjC/YYWebImage', '~> 3.3.4'

# 
pod repo update  rm ~/Library/Caches/CocoaPods/search_index.json
HXPhotoPicker
 "HXPhotoPicker.h"

- Requirements

  • iOS8. ARC. - iOS 8 or later. Requires ARC
  • info.plist
  • Privacy - Photo Library Usage Description Privacy - Camera Usage Description Privacy - Microphone Usage Description
  • Privacy - Location When In Use Usage Description

- Examples

//  
- (HXPhotoManager *)manager {
    if (!_manager) {
        _manager = [[HXPhotoManager alloc] initWithType:HXPhotoManagerSelectedTypePhotoAndVideo];
    }
    return _manager;
}

// 
HXWeakSelf
[self hx_presentSelectPhotoControllerWithManager:self.manager didDone:^(NSArray<HXPhotoModel *> *allList, NSArray<HXPhotoModel *> *photoList, NSArray<HXPhotoModel *> *videoList, BOOL isOriginal, UIViewController *viewController, HXPhotoManager *manager) {
    weakSelf.total.text = [NSString stringWithFormat:@"%ld   ( %ld   %ld )",allList.count, photoList.count, videoList.count];
    weakSelf.original.text = isOriginal ? @"YES" : @"NO";
    NSSLog(@"block - all - %@",allList);
    NSSLog(@"block - photo - %@",photoList);
    NSSLog(@"block - video - %@",videoList);
} cancel:^(UIViewController *viewController, HXPhotoManager *manager) {
    NSSLog(@"block - ");
}];

// 
//  
HXCustomNavigationController *nav = [[HXCustomNavigationController alloc] initWithManager:self.manager delegate:self];
[self presentViewController:nav animated:YES completion:nil];

//  HXCustomNavigationControllerDelegate 
/**


@param photoNavigationViewController self
@param allList ()
@param photoList 
@param videoList 
@param original 
*/
- (void)photoNavigationViewController:(HXCustomNavigationController *)photoNavigationViewController didDoneAllList:(NSArray<HXPhotoModel *> *)allList photos:(NSArray<HXPhotoModel *> *)photoList videos:(NSArray<HXPhotoModel *> *)videoList original:(BOOL)original;

/**


@param photoNavigationViewController self
*/
- (void)photoNavigationViewControllerDidCancel:(HXCustomNavigationController *)photoNavigationViewController;
HXCustomAssetModel *assetModel1 = [HXCustomAssetModel assetWithLocaImageName:@"1" selected:YES];
// selected NO 
HXCustomAssetModel *assetModel2 = [HXCustomAssetModel assetWithLocaImageName:@"2" selected:NO];
HXCustomAssetModel *assetModel3 = [HXCustomAssetModel assetWithNetworkImageURL:[NSURL URLWithString:@"http://tsnrhapp.oss-cn-hangzhou.aliyuncs.com/1466408576222.jpg"] selected:YES];
// selected NO 
HXCustomAssetModel *assetModel4 = [HXCustomAssetModel assetWithNetworkImageURL:[NSURL URLWithString:@"http://tsnrhapp.oss-cn-hangzhou.aliyuncs.com/0034821a-6815-4d64-b0f2-09103d62630d.jpg"] selected:NO];
NSURL *url = [[NSBundle mainBundle] URLForResource:@"QQ_20180301091047" withExtension:@"mp4"];
HXCustomAssetModel *assetModel5 = [HXCustomAssetModel assetWithLocalVideoURL:url selected:YES];

HXPhotoManager *photoManager = [HXPhotoManager managerWithType:HXPhotoManagerSelectedTypePhotoAndVideo];
photoManager.configuration.saveSystemAblum = YES;
photoManager.configuration.photoMaxNum = 0;
photoManager.configuration.videoMaxNum = 0;
photoManager.configuration.maxNum = 10;
photoManager.configuration.selectTogether = YES;
photoManager.configuration.photoCanEdit = NO;
photoManager.configuration.videoCanEdit = NO;

HXWeakSelf
// 
photoManager.configuration.previewRespondsToLongPress = ^(UILongPressGestureRecognizer *longPress, 
                                                          HXPhotoModel *photoModel, 
                                                          HXPhotoManager *manager, 
                                                          HXPhotoPreviewViewController *previewViewController) {
    hx_showAlert(previewViewController, @"", @"", @"", nil, nil, nil);
};
// view
photoManager.configuration.customPreviewFromView = ^UIView *(NSInteger currentIndex) {
    HXPhotoSubViewCell *viewCell = [weakSelf.photoView collectionViewCellWithIndex:currentIndex];
    return viewCell;
};
// image
photoManager.configuration.customPreviewFromImage = ^UIImage *(NSInteger currentIndex) {
    HXPhotoSubViewCell *viewCell = [weakSelf.photoView collectionViewCellWithIndex:currentIndex];
    return viewCell.imageView.image;
};
// view
photoManager.configuration.customPreviewToView = ^UIView *(NSInteger currentIndex) {
    HXPhotoSubViewCell *viewCell = [weakSelf.photoView collectionViewCellWithIndex:currentIndex];
    return viewCell;
};
[photoManager addCustomAssetModel:@[assetModel1, assetModel2, assetModel3, assetModel4, assetModel5]];

[self hx_presentPreviewPhotoControllerWithManager:photoManager
                                     previewStyle:HXPhotoViewPreViewShowStyleDark
                                     currentIndex:0
                                     photoView:nil];


UIViewController+HXExtension.h
/// 
/// @param manager 
/// @param previewStyle 
/// @param currentIndex 
/// @param photoView  - 
- (void)hx_presentPreviewPhotoControllerWithManager:(HXPhotoManager *)manager
                                       previewStyle:(HXPhotoViewPreViewShowStyle)previewStyle
                                       currentIndex:(NSUInteger)currentIndex
                                          photoView:(HXPhotoView * _Nullable)photoView;
// 
HXPhotoModel *photoModel = [HXPhotoModel photoModelWithImage:[UIImage imageNamed:@"1"]];
[self hx_presentPhotoEditViewControllerWithManager:self.manager photoModel:photoModel delegate:nil done:^(HXPhotoModel *beforeModel,
    HXPhotoModel *afterModel, HXPhotoEditViewController *viewController) {
    // beforeModelafterModel
    weakSelf.imageView.image = afterModel.thumbPhoto;
} cancel:^(HXPhotoEditViewController *viewController) {
    // 
}];

// 
[self hx_presentWxPhotoEditViewControllerWithConfiguration:self.manager.configuration.photoEditConfigur photoModel:photoModel delegate:nil finish:^(HXPhotoEdit * _Nonnull photoEdit, HXPhotoModel * _Nonnull photoModel, HX_PhotoEditViewController * _Nonnull viewController) {
    if (photoEdit) {
        // 
        weakSelf.imageView.image = photoEdit.editPreviewImage;
    }else {
        // 
        weakSelf.imageView.image = photoModel.thumbPhoto;
    }
    // 
    weakSelf.photoEdit = photoEdit;
} cancel:^(HX_PhotoEditViewController * _Nonnull viewController) {
    // 
}];

// 
NSURL *url = [[NSBundle mainBundle] URLForResource:@"QQ_20180301091047" withExtension:@"mp4"];
HXPhotoModel *videoModel = [HXPhotoModel photoModelWithVideoURL:url];
[self hx_presentVideoEditViewControllerWithManager:self.manager videoModel:videoModel delegate:nil done:^(HXPhotoModel *beforeModel,
    HXPhotoModel *afterModel, HXVideoEditViewController *viewController) {
    // beforeModelafterModel
    weakSelf.imageView.image = afterModel.thumbPhoto;
} cancel:^(HXVideoEditViewController *viewController) {
    // 
}];
// _manager.configuration.requestImageAfterFinishingSelection YES
// 
// 
//  exportVideoURLForHighestQuality YES
// 
// 
for (HXPhotoModel *model in self.selectList) {
    // 
    // 
    if (model.subType == HXPhotoModelMediaSubTypePhoto) {
        // 
        if (model.photoEdit) {
            // 
            // 
            model.photoEdit.editPreviewImage;
            return;
        }
        // 
        if (model.type == HXPhotoModelMediaTypeCameraPhoto) {
            // 
            //  < ios9.0PHAsset
            //  >= ios9.0 PHAsset
            //  model.asset PHAsset
            // 
            if (model.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeLocal) {
                // 
            
            }else if (model.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeLocalGif) {
                // gif
                
            }else if (model.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeNetWork) {
                // 
            
            }else if (model.cameraPhotoType == HXPhotoModelMediaTypeCameraPhotoTypeNetWorkGif) {
                // gif
                
            }
            // 
            if (model.networkPhotoUrl) {
                // 
                // 
                
            }else {
                // 
                //  model.previewPhoto  model.thumbPhotoimage
                
            }
        }else {
            //  model.asset PHAsset
            //  Gif  LivePhoto 
            if (model.type == HXPhotoModelMediaTypePhoto) {
                // livePhotoGIFLivePhoto
                // NSDataURL
                // GIF model.photoFormat == HXPhotoModelFormatGIF
                
                //  requestImageAfterFinishingSelection = YES  model.previewPhoto  model.thumbPhoto 
                // image
                // size  PHImageManagerMaximumSizesize
                CGSize size;
                if (self.original) {
                    size = PHImageManagerMaximumSize;
                }else {
                    size = CGSizeMake(model.imageSize.width * 0.5, model.imageSize.height * 0.5);
                }
                [model requestPreviewImageWithSize:size startRequestICloud:^(PHImageRequestID iCloudRequestId, HXPhotoModel * _Nullable model) {
                    // iCloud
                } progressHandler:^(double progress, HXPhotoModel * _Nullable model) {
                    // iCloud
                } success:^(UIImage * _Nullable image, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
                    // image
                } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
                    // 
                }];
            }else if (model.type == HXPhotoModelMediaTypePhotoGif) {
                //  requestImageAfterFinishingSelection = YES  model.imageURL
                model.imageURL;
                // imageurldata
                // url
                [model requestImageURLStartRequestICloud:nil progressHandler:nil success:^(NSURL * _Nullable imageURL, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
                    // imageURL 
                } failed:nil];
                
                // data
                [model requestImageDataStartRequestICloud:nil progressHandler:nil success:^(NSData * _Nullable imageData, UIImageOrientation orientation, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
                    // imageData
                } failed:nil];
            }else if (model.type == HXPhotoModelMediaTypeLivePhoto) {
                // LivePhotorequestImageAfterFinishingSelection = YES livephoto
                // livephotolivephoto
                // livephoto
                [model requestLivePhotoAssetsWithSuccess:^(NSURL * _Nullable imageURL, NSURL * _Nullable videoURL, BOOL isNetwork, HXPhotoModel * _Nullable model) {
                    // imageURL - LivePhoto
                    // videoURL - LivePhoto
                    
                } failed:^(NSDictionary * _Nullable info, HXPhotoModel * _Nullable model) {
                    // 
                }];
            }
            //  model.asset PHAsset
            PHAsset *asset = model.asset;
            // 
        }
    }else if (model.subType == HXPhotoModelMediaSubTypeVideo) {
        // 
        if (model.type == HXPhotoModelMediaTypeVideo) {
            // 
            // requestImageAfterFinishingSelection = YES  model.videoURL
            model.videoURL;
            //  AVAsset AVAssetExportSession
            //  AVAsset
            [model requestAVAssetStartRequestICloud:nil progressHandler:nil success:^(AVAsset * _Nullable avAsset, AVAudioMix * _Nullable audioMix, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
                // avAsset
                // avAsset
            } failed:nil];
            
            //  AVAssetExportSession
            [model requestAVAssetExportSessionStartRequestICloud:nil progressHandler:nil success:^(AVAssetExportSession * _Nullable assetExportSession, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
                
            } failed:nil];
            
            // HXPhotoModel
            // presetName 
            [model exportVideoWithPresetName:AVAssetExportPresetMediumQuality startRequestICloud:nil iCloudProgressHandler:nil exportProgressHandler:^(float progress, HXPhotoModel * _Nullable model) {
                // iCloud
            } success:^(NSURL * _Nullable videoURL, HXPhotoModel * _Nullable model) {
                // , videoURL
                
            } failed:nil];
            
            //  model.asset PHAsset
            PHAsset *asset = model.asset;
            // 
        }else {
            // 
            if (model.cameraVideoType == HXPhotoModelMediaTypeCameraVideoTypeLocal) {
                // 
                // model.videoURL 
            }else if (model.cameraVideoType == HXPhotoModelMediaTypeCameraVideoTypeNetWork) {
                // 
                // model.videoURL 
                // model.networkPhotoUrl 
            }
        }
    }
}
HXPhotoModel
/// HXPhotoModel
/// @param photoModel 
- (BOOL)isEqualToPhotoModel:(HXPhotoModel * _Nullable)photoModel;
//  
- (HXPhotoManager *)manager {
    if (!_manager) {
        _manager = [[HXPhotoManager alloc] initWithType:HXPhotoManagerSelectedTypePhotoAndVideo];
    }
    return _manager;
}  
HXPhotoView *photoView = [[HXPhotoView alloc] initWithFrame:CGRectMake((414 - 375) / 2, 100, 375, 400) manager:self.manager];
photoView.delegate = self;
photoView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:photoView];

//  
- (void)photoView:(HXPhotoView *)photoView changeComplete:(NSArray<HXPhotoModel *> *)allList photos:(NSArray<HXPhotoModel *> *)photos videos:(NSArray<HXPhotoModel *> *)videos original:(BOOL)isOriginal;

// view
- (void)photoView:(HXPhotoView *)photoView updateFrame:(CGRect)frame;

// 
- (void)photoView:(HXPhotoView *)photoView deleteNetworkPhoto:(NSString *)networkPhotoUrl;

HXPhotoView.h
...
 HXPhotoManager 
/// 
- (NSArray<HXPhotoModel *> *)getLocalModelsInFile;

/// 
- (BOOL)saveLocalModelsToFile;

/// 
- (BOOL)deleteLocalModelsInFile;

/// manager
/// @param models 
- (void)addLocalModels:(NSArray<HXPhotoModel *> *)models;

/// manager
- (void)addLocalModels;
 HXPhotoManagerHXCustomAssetModel 
/**


@param imageName 
@param selected 
@return HXCustomAssetModel
*/
+ (instancetype)assetWithLocaImageName:(NSString *)imageName selected:(BOOL)selected;

/**
UIImage

@param image 
@param selected 
@return HXCustomAssetModel
*/
+ (instancetype)assetWithLocalImage:(UIImage *)image selected:(BOOL)selected;

/**


@param imageURL 
@param thumbURL 
@param selected 
@return HXCustomAssetModel
*/
+ (instancetype)assetWithNetworkImageURL:(NSURL *)imageURL networkThumbURL:(NSURL *)thumbURL selected:(BOOL)selected;

/**


@param videoURL 
@param selected 
@return HXCustomAssetModel
*/
+ (instancetype)assetWithLocalVideoURL:(NSURL *)videoURL selected:(BOOL)selected;

/// 
/// @param videoURL 
/// @param videoCoverURL 
/// @param videoDuration 
/// @param selected 
+ (instancetype)assetWithNetworkVideoURL:(NSURL *)videoURL videoCoverURL:(NSURL *)videoCoverURL videoDuration:(NSTimeInterval)videoDuration selected:(BOOL)selected;

HXCustomAssetModelHXPhotoManager
/**

/ ,
/
.
.
 type = HXPhotoManagerSelectedTypePhoto  
 type = HXPhotoManagerSelectedTypeVideo  

@param assetArray 
*/
- (void)addCustomAssetModel:(NSArray<HXCustomAssetModel *> *)assetArray;

// 
[self.manager addCustomAssetModel:@[assetModel1, assetModel2, assetModel3, assetModel4, assetModel5, assetModel6]];
// HXPhotoView
[self.photoView refreshView];  

- Issues

1SDWebImage
2YYWebImage
   https://github.com/ibireme/YYKit/issues/573
   https://www.jianshu.com/p/9c117dbe22a8
   SDWebImage
YYKit
HXPhotoConfiguration.h


HXPhotoLanguageTypeSys = 0, // 
HXPhotoLanguageTypeSc,      // 
HXPhotoLanguageTypeTc,      // 
HXPhotoLanguageTypeJa,      // 
HXPhotoLanguageTypeKo,      // 
HXPhotoLanguageTypeEn       // 

/**

 
*/
@property (assign, nonatomic) HXPhotoLanguageType languageType;
HXPhotoModeltype
HXPhotoModelMediaTypePhoto          = 0,    //!< 
HXPhotoModelMediaTypeLivePhoto      = 1,    //!< LivePhoto
HXPhotoModelMediaTypePhotoGif       = 2,    //!< gif
HXPhotoModelMediaTypeCameraPhoto    = 5,    //!< /
typeHXPhotoModelMediaTypeCameraPhotonetworkPhotoUrl
thumbPhoto/previewPhoto
thumbPhoto/previewPhoto
HXPhotoModelimageimageData
1.HXPhotoModelPHAssetAVAssetAVAssetExportSessionAVAsset
2.PHAssetHXPhotoModelVideoURL
HXPhotoModel
/
9.0/PHAsset
HXPhotoModelPHAssettype HXPhotoModelMediaTypePhoto / HXPhotoModelMediaTypeVideo
/ 
HXPhotoModelPHAssettype HXPhotoModelMediaTypeCameraPhoto / HXPhotoModelMediaTypeCameraVideo
block isOriginal  

// 
// 
//  model.thumbPhoto / model.previewPhoto
//   model.thumbPhoto / model.previewPhoto  model.networkPhotoUrl  requestPreviewImageWithSize:progressHandler:success:failed
// photoModel.asset
[photoModel requestImageURLStartRequestICloud:^(PHContentEditingInputRequestID iCloudRequestId, HXPhotoModel *model) { 
    // iCloud,iCloud
    // 
} progressHandler:^(double progress, HXPhotoModel *model) {
    // iCloud
} success:^(NSURL *imageURL, HXPhotoModel *model, NSDictionary *info) {
    // 
    // imageURL
    if ([imageURL.relativePath.pathExtension isEqualToString:@"HEIC"]) {
        //  HEIC 
        CIImage *ciImage = [CIImage imageWithContentsOfURL:imageURL];
        CIContext *context = [CIContext context];
        NSString *key = (__bridge NSString *)kCGImageDestinationLossyCompressionQuality;
        NSData *jpgData = [context JPEGRepresentationOfImage:ciImage colorSpace:ciImage.colorSpace options:@{key : @1}];
        UIImage *image = [UIImage imageWithData:jpgData];
    }else {
        NSData *imageData = [NSData dataWithContentsOfFile:path];
        UIImage *image = [UIImage imageWithData:imageData];  
    }
} failed:^(NSDictionary *info, HXPhotoModel *model) {
    // 
}];
//  size  , size PHAsset 
//  size (width <= 0, height <= 0) / PHImageManagerMaximumSize 
// image
// image
[photoModel requestPreviewImageWithSize:size startRequestICloud:^(PHImageRequestID iCloudRequestId, HXPhotoModel *model) {
    // iCloud,iCloud
    // 
} progressHandler:^(double progress, HXPhotoModel *model) {
    // iCloud
    // ,
} success:^(UIImage *image, HXPhotoModel *model, NSDictionary *info) {
    // 
} failed:^(NSDictionary *info, HXPhotoModel *model) {
    // 
}];

//  imageData data
// 
[photoModel requestImageDataStartRequestICloud:^(PHImageRequestID iCloudRequestId, HXPhotoModel *model) {
    // iCloudimageData
} progressHandler:^(double progress, HXPhotoModel *model) {
    // iCloud
} success:^(NSData *imageData, UIImageOrientation orientation, HXPhotoModel *model, NSDictionary *info) {
    // 
    if ([HXPhotoTools assetIsHEIF:model.asset]) {
        //  HEIC 
        CIImage *ciImage = [CIImage imageWithData:imageData];
        CIContext *context = [CIContext context];
        NSData *jpgData = [context JPEGRepresentationOfImage:ciImage colorSpace:ciImage.colorSpace options:@{}];
        // jpgData imageData
    } 
} failed:^(NSDictionary *info, HXPhotoModel *model) {
    // 
}];
HXPhotoView 
- (void)photoView:(HXPhotoView *)photoView updateFrame:(CGRect)frame 
frame.size.height  HXPhotoView 
demo11

- Update History

- v3.3.4-ObjC
- v3.3.2-iOS16iPhone14Pro/ProMaxiOS9.3.5 fileSize
- v3.3.1-``cell,
- v3.3.0-HXPhotoModel
- v3.2.9-iOS15
- v3.2.7-iOS15
- v3.2.6-""iPhone se  12.2 
- v3.2.5-iOS15
- v3.2.4-
- v3.2.3-iOS 14 
- v3.2.2-podHXPhotoViewitemSize pod 'HXPhotoPickerObjC/CustomItem'
- v3.2.1-gifURL
- v3.2.0-
- v3.1.9-
- v3.1.8-
- v3.1.7-HXPhotoModel
- v3.1.6-requestImageAfterFinishingSelectionYES
- v3.1.5-
- v3.1.4-fix previewPhotonil
- v3.1.3-darkiOS14iCloud/PHAsset
- v3.1.2-iPhone12PHAssetCollectionPHAsset
- v3.1.1-darkiOS14
- v3.1.0-iOS14iOS11
- v3.0.8-
- v3.0.7-/
- v3.0.6-...
- v3.0.5-LivePhotoLivePhoto
- v3.0.4-
- v3.0.3-podxibgif
- v3.0.2-ios14titleView
- v3.0.0-
...
- v2.4.5-pod SDWebImage/YYWebImage 
- v2.4.4-bugHXPhotoView...Demo15
- v2.4.3-Demo14HXPhotoViewItem
- v2.4.2-
- v2.4.1-/podAFNetworking
- v2.4.0-demo8/
- v2.3.8-HXPhotoViewMasonryDemoXibMasonry
- v2.3.7-/
- v2.3.6-HXPhotoModelfileURL
- v2.3.5-requestImageAfterFinishingSelection YESHXPhotoViewActionSheetviewios13...
- v2.3.4-ios13requestImageAfterFinishingSelectionblock
- v2.3.3-podyy
- v2.3.2-ios13
- v2.3.1-podsdyy
- v2.3.0-SDWebImage v5.0.0 
- v2.2.9-UI
- v2.2.7-NSArray+HXExtension
- v2.2.6-ipadios8Demo
- v2.2.5-
- 2019-1-18 iCloudcellDateDate
- 2019-1-12 HEIC
- 2019-1-9  
- 2019-1-7  ios9PHAsset
- v2.2.3-Demo9 cell3DTouchDemo13 /
- v2.2.2-iphone XS - XSMax - XRYYWebImageYYWebImageSDYYYY
- v2.2.1-HXPhotoView
- v2.2.0-xibDemo11//Demo12
- v2.1.9-Demo2
- v2.1.8-
- v2.1.7- 
- v2.1.5-cell
- v2.1.4-
- 2017-11-21iCloud
- v2.1.2-
- 2017-11-14
- 2017-11-06
- v2.1.1-(,)
- v2.1.0-ios11iphone X / 3DTouchgif / iCloud
- v2.0.9-tempdemo
- v2.0.8-
- v2.0.7-
- v2.0.6-ios8
- v2.0.5-
- ...
- 2017-08-12HXPhotoTools
- 2017-08-1064
- 2017-08-08/
- 2017-07-26cell3DTouch/Demo
- 2017-07-05,
- 2017-07-01
- 2017-06-26
- ...
- 2017-03-0790
- 2017-03-06

- Plan

  • HXPhotoView

  • ...

- Author

Package Rankings
Top 22.81% on Cocoapods.org
Related Projects