Photos中常用类(获取展示功能相关)简介

简介

Photos framework是iOS8苹果提供的新的图片框架,能直接获取图片和视频,包括iCloud上面的图库。使用这个框架可以获取assets来展示和回放,编辑图片或者视频内容,或者使用系统相册、时刻、和分享到iCloud的相册来进行相关操作,本文侧重相片的获取与保存。 demo地址在这里

新特性与一些概念

获取实体&改变请求: Photos framework中的三个model类:PHAsset,PHAssetCollection,PHCollectionList,分别对应三个类型的实体:asset(图片和视频),assets集合(相册和时刻),集合列表(相册文件夹或者moment clusters)。这些对象,也成为 相片实体(photo entities),只包含元数据,同时也是read-only属性。

改变观察机制: 使用这个特性能够在其他app、设备更改了图片和视频内容或者相册的时候通知你的app,在实现观察机制前需要用PHPhotoLibrary对象先为你获取到的照片实体注册一个观察者

支持手机中的照片app的特性 使用PHCollectionList类查找获取照片中响应的时刻层级asset,使用PHAsset标记连拍照片,全景照片和高分辨率视频等。当开启iCloud图库后,Photo framework能从iCloud中获取到使用相同apple ID登陆的不同设备中的照片。

加载缓存asset和缩略图 使用PHImageManager请求asset中的特定尺寸的图片或者通过AV Foundation 对象获取video asset。Photos frame会根据设定自动下载,缓存,以便于高效复用。对于大量的assets的快速执行,例如在生成相册中所有图片的缩略图时,使用PHCachingImageManager的子类来实现。

编辑asset内容 PHAsset和PHAsssetChangeRequest定义了一些用于编辑照片或者视频内容的方法,同时允许将编辑后的图片保存到图库中。为了可以让用户可以在前次修改的基础上再次修改,或者是在不同的app上进行多次修改,Photos保存了当前和县区版本的asset,如果单独使用PHAdjustMnentData对象只能获取到最后编辑的照片。如果你的app支持在前面修改基础上多次编辑,你应该允许用户撤回或者修改本次编辑。

framework中的类

PHAdjustmentData

当修改了一个asset后,Photos会将PHAdjustmentData对象和修改过的图片或者视频数据一起保存起来,你可以通过这个对象提供的一些数据来修改已经保存的编辑。

当需要调整data的时候,调用

  • (PHContentEditingInputRequestID)requestContentEditingInputWithOptions:(PHContentEditingInputRequestOptions *)options completionHandler:(void (^)(PHContentEditingInput *contentEditingInput, NSDictionary *info))completionHandler 初始化方法:

/**

  • 用于标记特定的修改数据,使用formatIndentifier和formatVersion指定唯一的adjustment,
  • data存储用于回滚到之前状态的数据,也就是当前图片的修改数据,以便于在这个基础上继续进行修改
  • @param formatIndentifier 用于标记 adjustment data
  • @param formatVersion version number for adjustment data
  • @param data 包含了重新修改需要的数据

*/

  • (instanceType)initWithForamtIndentifier:(NSString *)formatIndentifier formatVersion:(NSString *)formatVersion data:(NSData *)data; PHAssetChangeRequest

在图库中使用PHAssetChangeRequest对象来创建,修改,删除PHAsset对象。

可以使用适当的类方法来实现增加删除修改asset的目的:

/**

  • 删除给定的assets
  • @param assets 包含需要删除的asset数组 */
  • (void)deleteAssets:(id<NSFastEnumeration>)assets;

/**

  • 修改给定的PHAsset对象
  • 在修改之前使用 'canPerformEditOperation:' 方法判断asset是否允许修改
  • 在photo library change block中创建修改请求后,设置正确的修改请求属性。
  • @param asset 待修改的asset */
  • (instancetype)changeRequestForAsset:(PHAsset *)asset; PHFetchOptions

当你使用没方法获取PHAsset(图片和视频),PHCollection(相册类型),PHAssetCollection(相册)的实体(相当于包含多个数据的模型)使用PHFetchOptions对象指定操作,例如获取的实体的排列属性等。

调用PHFetchRequest类方法创建一个包含fetch请求的对象。

这个类包含了两个属性:predicate和sortDescriptors。

NSPredicate *predicate:

specifies which properties to select results by and that also specifies any constraints on selection. 用于指定返回的结果和指定条件

示例:

PHFetchOperation *fetchOptions = [PHFetchOption new]; fetchOperations.predicate = [NSPredicate predicateWithFormat: @"(mediaSubtype & %d) != 0 || (mediaSubtype & %d) != 0", PHAssetMediaSubtypePhotoPanorama,PHAssetMediaSubtypeVideoHightFrameRate];

PHFetchResult *result = [PHAsset fetchAssetWithOptions:fetchOptions]; NSArray <NSSortDescriptor *> *sortDescriptors 用于指定获取的对象的顺序 用一个例子实现以时间顺序倒序(刚拍摄的照片放在前头排列获取图片的功能:

PHFetchOption *option = [PHFetchOption new]; option.sourtDescriptors = @[NSSortDescriptors sortDescriptiorWithKey:@"creationDate" ascending:NO]; PHFetchResult *result = [PHAsset fetchAssetsWithOptions:option]; 其他几个属性:

//用于确定app是否接收到了具体的改变信息。 @property(nonatomic, assign) BOOL wantsIncrementalChangeDetails

/** *限制检索获取得到的photo实体的最小数量,当实体数量十分巨大时,作用显著, *例如,用'PHAsset'的'fetchAssetsWithOptions:'方法获取最近拍摄的照片等。 */ @property(nonatomic, assign, readwrite) NSUInteger fetchLimit

//检索结果是否包含连拍图片,如果是NO,只显示用户选取的那种图片,如果为YES, @property(nonatomic, assign) BOOL includeAllBurstAssets

//顾名思义,是否检索隐藏的图片 @property(nonatomic, assign) BOOL includeHiddenAssets

/** *包含的数据类型: *PHAssetSourceTypeUserLibrary
*PHAssetSourceTypeCloudShared *PHAssetSourceTypeiTunesSynced */ @property(nonatomic, assign) PHAssetSourceType includeAssetSourceTypes PHImageRequestOption

PHImageRequestOption 用于配置从PHImageManager中获取asset的请求。 常用的一些属性和方法有:

/**

  • @discuss 如果是NO,表示为异步操作,从manager中请求图片时,
  • 'reqeustImageForAssets:targetSize:options:resultHandler'方法会立即返回,
  • 建议在后台只在后台线程中执行同步请求 */ @property (nonatomic, assign) BOOL synchronous;

/** *typedef : NSInteger { PHImageRequestOptionsDeliveryModeOpportunistic = 0, PHImageRequestOptionsDeliveryModeHighQualityFormat = 1, PHImageRequestOptionsDeliveryModeFastFormat = 2, } PHImageRequestOptionsDeliveryMode;

*@PHImageRequestOptionsDeliveryModeOpportunistic: 自动返回一个或多个结果,来平衡图片的质量和响应性,它会多次调用 resutltHandler:'requestImageForAssets:targetSize:options:resultHandler'. 它首先会先调用一次'resutltHandler'返回清晰度低的图片作为临时显示图片, 等到能获取到高清晰度的图片时再次调用'resutltHandler'返回高质量图片。

note:如果'synchronous'是NO那么该属性无效

*@PHImageRequestOptionsDeliveryModeHighQualityFormat 只返回高分辨率的图片。具有较高的优先权

*@PHImageRequestOptionsDeliveryModeFastFormat 快速返回结果,可能会牺牲图片质量。 */ @property (nonatomic, assign) PHImageRequestOptionsDeliveryMode deliveryMode;

/**

  • a mode that specifies how to resize the reuqested image */ @property(nonatomic, assign) PHImageRequestOptionsResizeMode resizeMode; 从iCloud中下载照片

/**

  • 能否从iCloud中下载图片, YES,本地也没有保存此图片,从iCloud上下载,用'progressHandler'这个block获取下载进度; NO,同时本地也没有图片,'progressHander'中的info[PHImageReustIsInCloudKey]返回值会表示不能下载 */ @property(nonatomic, assign, getter=isNetworkAccessAllowed) BOOL networkAccessAllowed;

/** 下载进度block,在多条线程中执行操作,刷新UI时需要回到主线程
*/ typedef void (^ PHAssetImageProgressHandler)(double progress, NSError *error, BOOL *stop, NSDictionary *info);

@property(nonatomic, copy) PHAssetImageProgressHandler progressHandler PHFetchResult

PHFetchRequest是有序的photo实体对象的容器,包含通过给定的检索条件返回的asset,相册,一个相册类型中的所有相册列表(例如,smart album类型下的所有相册,它是有序的),在PHAsset,PHCollection,PHAssetcollection,PHCollectionList这几个类中都包含有相应的类方法包含对应信息的PHFetchRequest对象,例如:

PHAsset

/**

  • @param mediaType
  • aaset类型,包含有:
    
  •   PHAssetMediaTypeUnknown = 0,
    
  •   PHAssetMediaTypeImage,
    
  •   PHAssetMediaTypeVideo,
    
  •   PHAssetMediaTypeAudio,
    
  • @param options 检索操作
  • @return 带有符合条件的PHAsset对象集合的PHFetchRequest对象 */ +(PHFetchResult<PHAsset *> *)fetchAssetsWithMeidaType:(PHAssetMediaType)mediaType options:(PHFetchOptions *)options PHCollection (抽象类,不允许直接使用,开发过程中用它的两个子类PHCollectionList和PHAssetCollection替代)

//Retrieves collections from the root of the photo library’s hierarchy of user-created albums and folders. +(PHFetchResult<PHCollection *> *)fetchTopLevelUserCollectionsWithOption:(PHFetchOptions *)options; PHAssetCollection:

/**

  • 获取自定条件的相册

  • @param type 相册类型: PHAssetCollectionTypeAlbum PHAssetCollectionTypeSmartAlbum PHAssetCollectionTypeMoment

  • @param subtype 相对于相册类型更具体些的相片类型,如全景,照片流等

  • @param options 检索条件

  • @return 符合条件的相册 */ +(PHFetchResult<PHAssetCollection *> *)fetchAssetColletcionsWithType:(PHAssetCollectionType)type subtype:(PHAssetCollectionSubtype)subtype options:(PHFetchOptions *)options; PHCollectionList: +(PHFetchResult<PHCollectionList *> *)fetchCollectionListsWithType:(PHCollectionListType)collectionListType subtype:(PHCollectionListSubtype)subtype options:(PHFetchOptions *)options PHFetchRequest虽然包含了符合条件的photo实体的集合,与NSArray不同的是它会动态改变包含的内容,在处理大量的asset的时候效率更高些,实现的效果也好点

常用属性与方法

//是否包含给定的对象

  • (BOOL)containsObject:(ObjectType)anObject

//包含的photo实体个数 @property(readonly) NSUInteger count

//指定类型的asset数量

  • (NSUInteger)countOfAssetsWithMediaType:(PHAssetMediaType)mediaType PHImageManager

PHImageManager有一个单例方法,同时也提供了用于获取全尺寸图片,图片缩略图等方法.

获取图片:

/**

  • 会多次调用'resultHandler',第一次调用,返回的图片清晰度较低,
  • 当高清晰度图片可以获取时,会再次调用,如果高质量的图片在缓存汇中,只调用一次'resultHandler'。
  • 这个方法默认是异步的,当从后台线程调用这个方法时,需要将options的'synchronous'设为YES.
  • @param asset 保存图片信息的asset
  • @param targetSize 返回的图片尺寸
  • @param contentMode 返回的图片显示模式
  • @param options image request option
  • @param resultHandler 返回的内容
  • @return 请求标示,用于取消请求*/
  • (PHImageRequestID)requestImageForAsset:(PHAsset *)asset targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(PHImageRequestOptions *)options resultHandler:(void (^)(UIImage *result, NSDictionary *info))resultHandler;

/**

  • 请求全尺寸的图片,只执行一次'resultHandler',
  • 如果options的'version'被设置为'PHImageRequestOptionsVersionCurrent,'
  • 返回在这个asset上发生的任何编辑后的imageData,如果不是的话,返回最原始版本的图片
  • @param asset 保存图片信息的asset
  • @param options image request option
  • @param resultHandler 返回的内容
  • @return 请求标示,用于取消请求 */
  • (PHImageRequestID)requestImageDataForAsset:(PHAsset *)asset options:(PHImageRequestOptions *)options resultHandler:(void (^)(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info))resultHandler; 取消请求:

  • (void)cancelImageRequest:(PHImageRequestID)requestID PHCachingImageManager

PHCachingImageManager是PHImageManager的子类,如果相册中有大量的图片,而你的需求是要快速的获取这些图片的缩略图和大图数据用于展示,这个时候可以用PHCachingImageManager来实现,它具有缓存机制可以快速获取一个图册的缩略图,或者在后台请求全尺寸图片以便于快速展示。

开始缓存图片:

/**

  • @discuss 当调用这个方法的时候,cacaingManager开始在获取你所需要的数据,
  • 同时在后台生成缩略图,之后可以使用'requestImagesFromAssets:targetSize:contentMode:resultHandler:'
  • 方法从缓存中请求数据。
  • Photos会按照给定的尺寸,显示模式返回图片,缓存中的图片尺寸是固定的
  • @param assets 需要缓存的assets
  • @param targetSize 图片尺寸
  • @param contentMode 显示模式
  • @param options 请求操作 */
  • (void)startCachingImagesForAssets:(NSArray *)assets targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(PHImageRequestOptions *)options; 取消图片缓存:

/**

  • 当使用collectionView展示图片缩略图的时候,如果需要改变尺寸大小的时候,
  • 就需要将缓存中的旧图片删除重新缓存。
  • @param assets 需要缓存的assets
  • @param targetSize 图片尺寸
  • @param contentMode 显示模式
  • @param options 请求操作 */
  • (void)stopCachingImagesForAssets:(NSArray *)assets targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(PHImageRequestOptions *)options; PHPhotoLibrary

PHPhotoLibrary可以看成是一个用户图库,包含了一些的图片和相册,同时包含本地的和iCloud中的资源。当Photos app发生图片的修改、增加、删除等改变时,使用PHPhotoLibrary来做一些刷新UI,保存数据等响应动作,同时也可以注册观察者(使用registerChangeObserver方法),当Photos app内容发生改变的时,会触发代理方法photoLibraryDidChange。

使用PHPhotoLibrary响应图库改变

Photos中的PHAsset,PHAssetCollection等是不可变对象,因此要改变当前这些类型对象的时候就需要使用photo library实现改变。

请求改变数据需要用到PHAssetChangeRequest,PHAssetcCollectionChangeRequest,PHCollectionListChangeRequest。

使用步骤:

1、创建实体

每个change request类都提供了用于创建响应的实体类的方法: creationRequestForAssetCollectionWithTitle:创建了一个asset Collection

如果要添加一个新的asset到collection中,需要用到change request提供的PHObjectPlaceholder对象。在change block结束之后,使用placeholder对象提供的localIdentifier属性获取创建好的asset对象。

2、删除实体

例如:deleCollectionLists用于删除collection list

3、修改实体

changeRqeustForAsset创建了一个可用于修改的asset的change request

下面代码实现往相册中添加新图片的功能:

  • (void)addNewAssetWithImge:(UIImage *)image toAlbum:(PHAssetCollection *)album {

    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{

      PHAssetChangeRequest *assetChange = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
    
      PHAssetCollectionChangeRequest *collectionChange = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:album];
    
      PHObjectPlaceholder *placeholder = [assetChange placeholderForCreatedAsset];
    
      [collectionChange addAssets:@[placeholder]];
    

    } completionHandler:^(BOOL success, NSError * _Nullable error) { NSLog(@"Finished adding asset. %@", (success ? @"Success" : error)); }]; } note:For each call to the performChanges:completionHandler: or performChangesAndWait:error: method, iOS shows an alert asking the user for permission to edit the contents of the photo library. 注册观察者

PHPhotoLibraryChangeObserver在系统图库发生变化的时候就会通知指定的观察者,只要是使用了Photos framework实现的改变,都会触发观察者的方法。 registerChangeObserver:方法指定一名观察者,当系统图库发生改变,会触发观察者的指定方法,这个方法在PHPhotoLibraryChangeObserver协议中:- (void)photoLibraryDidChange:(PHChange *)changeInfo ;

PHCollection

PHCollection是一个抽象类,不允许直接使用它的实例对象,而是使用它的两个子类:PHAssetCollection,PHCollectionList: PHAssetCollection 包含了带有图片或者视频信息PHAsst对象,PHCollectionList可以看做是一个文件夹,里面存放多个相册或者是在年度相册中的所有时刻的照片。

获取图片集合:

//用特定的操作从collection list中获取collection集合

  • (PHFetchResult<PHCollection *>)fetchCollectionsInCollectionList:(PHCollectionList *)collectionList options:(PHFetchOptions *)options

//获取所有用户创建的相册或者文件夹。

  • (PHFetchResult<PHCollection *> *)fetchTopLevelUserCollectionWithOptions:(PHFetchOptions *)options; PHAssetCollection

一个PHAssetCollection代表一个相册,可能包含图片和视频,例如:时间相册,我的照片流,自拍。

在Photos framework中不能直接获取collection中的内容,通过fetchAssetsInAssetCollecton:options:获取到包含PHAsset集合的PHFecthReult对象,之后用fetchResult提供的方法取出图片或者视频。

获取asset collection 的方法有许多种:

/**

  • @param type 相册类型: PHAssetCollectionSubtypeAlbumRegular Photos APP中创建的相册

     PHAssetCollectionSubtypeAlbumSyncedEvent
     从iPhoto中同步的事件相册
    
     PHAssetCollectionSubtypeAlbumSyncedFaces   
     从iPhoto中同步的包含人脸的相册
    
     PHAssetCollectionSubtypeAlbumSyncedAlbum
     从iPhoto同步的普通相册
    
     PHAssetCollectionSubtypeAlbumImported
     从其他设备导入的相册
    
     PHAssetCollectionSubtypeAlbumCloudShared
     分享到iCloud的照片流相册
    
     PHAssetCollectionSubtypeAlbumMyPhotoStream
     用户个人的iCloud照片流
    
     PHAssetCollectionSubtypeSmartAlbumGeneric
     没有特定类型的只能相册
    
     PHAssetCollectionSubtypeSmartAlbumPanoramas
     全景图片相册
    
     PHAssetCollectionSubtypeSmartAlbumVideos
     视频相册
    
     PHAssetCollectionSubtypeSmartAlbumFavorites
     个人收藏
    
     PHAssetCollectionSubtypeSmartAlbumTimelapses
     延时摄影相册
    
     PHAssetCollectionSubtypeSmartAlbumAllHidden
     隐藏的图片相册
    
     PHAssetCollectionSubtypeSmartAlbumRecentlyAdded
     最近添加的图片
    
     PHAssetCollectionSubtypeSmartAlbumBursts
     连拍相册
    
     PHAssetCollectionSubtypeSmartAlbumSlomoVideos
     慢动作视频相册
    
     PHAssetCollectionSubtypeSmartAlbumUserLibrary
     在本地存在的相册(不包含icloud中的相册)
    
     PHAssetCollectionSubtypeSmartAlbumSelfPortraits
     自拍
    
     PHAssetCollectionSubtypeSmartAlbumScreenshots
     截屏
    
     PHAssetCollectionSubtypeAny
     获取所有类型的相册
    
  • @param options 筛选操作

  • @return 包含符合条件的相册的fetch result */

  • (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsWithType:(PHAssetCollectionType)type subtype:(PHAssetCollectionSubtype)subtype options:(nullable PHFetchOptions *)options;

/**

  • 获取符合特定类型同时包含指定asset的相册集合
  • @param asset 给定的sset
  • @param type 指定相册类型
  • @param options 获取操作

*/

  • (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsContainingAsset:(PHAsset *)asset withType:(PHAssetCollectionType)type options:(PHFetchOptions *)options; PHCollectionList

PHCollectionList包含了更高级别的asset集合,可嵌套PHAssetCollection 和自身类型,还支持多重嵌套,例如获取时刻相册和时刻相册中年度照片等。

获取collection list的几种方法:

  • (PHFetchResult<PHCollectionList *>)fetchCollectionListsContainingCollection:(PHCollection *)collection options:(PHFetchOptions *)options;

  • (PHFetchResult<PHCollectionList *> *)fetchCollectionListsContainingCollection:(PHCollection *)collection options:(nullable PHFetchOptions *)options;

  • (PHFetchResult<PHCollectionList *> *)fetchCollectionListsWithLocalIdentifiers:(NSArray<NSString *> *)identifiers options:(nullable PHFetchOptions *)options;

  • (PHFetchResult<PHCollectionList *> *)fetchCollectionListsWithType:(PHCollectionListType)collectionListType subtype:(PHCollectionListSubtype)subtype options:(nullable PHFetchOptions *)options;

  • (PHFetchResult<PHCollectionList *> *)fetchMomentListsWithSubtype:(PHCollectionListSubtype)momentListSubtype containingMoment:(PHAssetCollection *)moment options:(nullable PHFetchOptions *)options;

  • (PHFetchResult<PHCollectionList *> *)fetchMomentListsWithSubtype:(PHCollectionListSubtype)momentListSubtype options:(nullable PHFetchOptions *)options; PHAsset

PHAsset代表一个视频或者图片资源,当需要展示或者修改Photos app中的图片时需要先获取asset,asset是不可改变的并且只保存了所代表的视频或者图片的metadata。

获取PHAsset的几种方法:

//从asset collection中获取符合条件的asset集合

  • (PHFetchResult <PHAsset *> *)fetchAssetsInAssetCollection:(PHAssetCollection *)assetCollection options:(PHFetchOptions *)options

/**

  • 默认返回所有类型的asset,如果要给asset添加更多的类型限定,可以在options的filter predicate中设置。

  • @param mediaType : PHAssetMediaTypeUnknown 未知类型

     PHAssetMediaTypeImage
     静态图片
    
     PHAssetMediaTypeVideo
     视频
    
     PHAssetMediaTypeAudio
     音频
    

注: PHMediaSubtype:

PHAssetMediaSubtypeNone               = 0,

// Photo subtypes
PHAssetMediaSubtypePhotoPanorama      = (1UL << 0),
PHAssetMediaSubtypePhotoHDR           = (1UL << 1),
PHAssetMediaSubtypePhotoScreenshot NS_AVAILABLE_IOS(9_0) = (1UL << 2),
PHAssetMediaSubtypePhotoLive NS_AVAILABLE_IOS(9_1) = (1UL << 3),


// Video subtypes
PHAssetMediaSubtypeVideoStreamed      = (1UL << 16),
PHAssetMediaSubtypeVideoHighFrameRate = (1UL << 17),
PHAssetMediaSubtypeVideoTimelapse     = (1UL << 18),

*/

  • (PHFetchResult <PHAsset *> *_Nullable)fetchAssetsWithMediaType:(PHAssetMediaType)mediaType options:(PHFetchOptions *_Nullable)options;

  • (PHFetchResult *<PHAsset *> *)fetchAssetsWithLocalIndentifiers:(NSArray <NSString *>)identifier options:(PHFetchOptions *)options;

/**

  • 获取key asset,每一个collection都至少有一个key asset,每个不同类型的collection用于定义key asset的方式也不同,有的collection中只有一个key asset,有的含有多个。
  • 例如在相机胶卷中,最近拍摄的图片或者视频就是key asset */
  • (PHFetchResult <PHAsset *>)fetchKeyAssetsInAssetCollection:(PHAssetCollection *)collection options:(PHFetchOptions *)options;

/**

  • 获取所有的符合条件的asset,默认条件下,不包含通过iTunes同步过来的和存储在iCloud中的图片。
  • 更改此条件,配置options的'includeAssetSourceType'属性来实现。 */
  • (PHFetchResult <PHAsset *> *)fetchAssetsWithOptions:(PHFetchOptions *)options;

//获取连拍照片

  • (PHFetchResult <PHAsset *>)fetchAssetWithBurstIdentifier(NSString *)burstIdentifier options:(PHFetchOptions *)options;

转载于:https://my.oschina.net/u/2613046/blog/995712

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值