@@ -9,6 +9,11 @@
# import "KBVipPayHeaderView.h"
# import "KBVipPayHeaderView.h"
# import "KBVipSubscribeCell.h"
# import "KBVipSubscribeCell.h"
# import "KBVipReviewListCell.h"
# import "KBVipReviewListCell.h"
# import "PayVM.h"
# import "KBPayProductModel.h"
# import "FGIAPProductsFilter.h"
# import "FGIAPManager.h"
# import "KBBizCode.h"
static NSString * const kKBVipHeaderId = @ "kKBVipHeaderId" ;
static NSString * const kKBVipHeaderId = @ "kKBVipHeaderId" ;
static NSString * const kKBVipSubscribeCellId = @ "kKBVipSubscribeCellId" ;
static NSString * const kKBVipSubscribeCellId = @ "kKBVipSubscribeCellId" ;
@@ -16,7 +21,7 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
@ interface KBVipPay ( ) < UICollectionViewDataSource , UICollectionViewDelegateFlowLayout >
@ interface KBVipPay ( ) < UICollectionViewDataSource , UICollectionViewDelegateFlowLayout >
@ property ( nonatomic , strong ) UICollectionView * collectionView ; // 主 列 表 ( 竖 向 滚 动 )
@ property ( nonatomic , strong ) UICollectionView * collectionView ; // 主 列 表 ( 竖 向 滚 动 )
@ property ( nonatomic , strong ) NSArray < NSDictionary * > * plans ; // 订 阅 方 案 数 组
@ property ( nonatomic , strong ) NSArray < KBPayProductModel * > * plans ; // 订 阅 方 案 数 组
@ property ( nonatomic , assign ) NSInteger selectedIndex ; // 当 前 选 中 的 方 案 索 引
@ property ( nonatomic , assign ) NSInteger selectedIndex ; // 当 前 选 中 的 方 案 索 引
@ property ( nonatomic , strong ) UIButton * closeButton ; // 当 前 选 中 的 方 案 索 引
@ property ( nonatomic , strong ) UIButton * closeButton ; // 当 前 选 中 的 方 案 索 引
@ property ( nonatomic , strong ) UIImageView * bgImageView ; // 全 屏 背 景 图
@ property ( nonatomic , strong ) UIImageView * bgImageView ; // 全 屏 背 景 图
@@ -27,6 +32,8 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
@ property ( nonatomic , strong ) UIButton * payButton ; // 支 付 按 钮 ( 背 景 图 )
@ property ( nonatomic , strong ) UIButton * payButton ; // 支 付 按 钮 ( 背 景 图 )
@ property ( nonatomic , strong ) UILabel * agreementLabel ; // 协 议 提 示
@ property ( nonatomic , strong ) UILabel * agreementLabel ; // 协 议 提 示
@ property ( nonatomic , strong ) UIButton * agreementButton ; // 《 Embership Agreement 》
@ property ( nonatomic , strong ) UIButton * agreementButton ; // 《 Embership Agreement 》
@ property ( nonatomic , strong ) PayVM * payVM ;
@ property ( nonatomic , strong ) FGIAPProductsFilter * filter ;
@ end
@ end
@@ -46,13 +53,10 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
make . left . top . right . equalTo ( self . view ) ;
make . left . top . right . equalTo ( self . view ) ;
make . height . mas_equalTo ( 224 ) ;
make . height . mas_equalTo ( 224 ) ;
} ] ;
} ] ;
// 初 始 化 数 据 ( 简 单 演 示 )
self . payVM = [ PayVM new ] ;
self . plans = @ [
self . filter = [ [ FGIAPProductsFilter alloc ] init ] ;
@ { @ "title" : @ "Monthly Subscription" , @ "price" : @ "$4.49" , @ "strike" : @ "$4.49" } ,
self . plans = @ [ ] ;
@ { @ "title" : @ "Monthly Subscription" , @ "price" : @ "$4.49" , @ "strike" : @ "$4.49" } ,
self . selectedIndex = NSNotFound ;
@ { @ "title" : @ "Monthly Subscription" , @ "price" : @ "$4.49" , @ "strike" : @ "$4.49" } ,
] ;
self . selectedIndex = 1 ; // 默 认 选 中 第 二 项
// 组 装 主 列 表
// 组 装 主 列 表
[ self . view addSubview : self . collectionView ] ;
[ self . view addSubview : self . collectionView ] ;
@@ -89,18 +93,67 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
// 预 计 算 Header 高 度 ( 由 内 部 约 束 决 定 )
// 预 计 算 Header 高 度 ( 由 内 部 约 束 决 定 )
self . headerHeight = [ self kb_calcHeaderHeightForWidth : KB_SCREEN _WIDTH ] ;
self . headerHeight = [ self kb_calcHeaderHeightForWidth : KB_SCREEN _WIDTH ] ;
[ self . collectionView reloadData ] ;
[ self . collectionView reloadData ] ;
[ self fetchSubscriptionPlans ] ;
}
}
- ( void ) viewDidAppear : ( BOOL ) animated {
- ( void ) viewDidAppear : ( BOOL ) animated {
[ super viewDidAppear : animated ] ;
[ super viewDidAppear : animated ] ;
// 首 次 进 入 , 确 保 订 阅 项 保 持 选 中 态 ( 避 免 首 屏 仅 显 示 Header , 待 滚 动 出 现 时 没 有 选 中 样 式 )
[ self selectCurrentPlanAnimated : NO ] ;
}
# pragma mark - Data
- ( void ) fetchSubscriptionPlans {
__weak typeof ( self ) weakSelf = self ;
[ self . payVM fetchSubscriptionProductsNeedShow : YES completion : ^ ( NSInteger sta , NSString * _Nullable msg , NSArray < KBPayProductModel * > * _Nullable products ) {
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
__strong typeof ( weakSelf ) self = weakSelf ;
if ( ! self ) { return ; }
if ( sta ! = KBBizCodeSuccess || ! [ products isKindOfClass : NSArray . class ] ) {
self . plans = @ [ ] ;
self . selectedIndex = NSNotFound ;
[ self . collectionView reloadData ] ;
NSString * tip = msg . length ? msg : KBLocalized ( @ "Failed to load products" ) ;
if ( tip . length ) { [ KBHUD showInfo : tip ] ; }
return ;
}
self . plans = products ? : @ [ ] ;
self . selectedIndex = self . plans . count > 0 ? 0 : NSNotFound ;
[ self . collectionView reloadData ] ;
[ self selectCurrentPlanAnimated : NO ] ;
} ) ;
} ] ;
}
- ( void ) selectCurrentPlanAnimated : ( BOOL ) animated {
if ( self . selectedIndex = = NSNotFound ) { return ; }
if ( self . selectedIndex < 0 || self . selectedIndex >= self . plans . count ) { return ; }
NSIndexPath * ip = [ NSIndexPath indexPathForItem : self . selectedIndex inSection : 1 ] ;
NSIndexPath * ip = [ NSIndexPath indexPathForItem : self . selectedIndex inSection : 1 ] ;
if ( ! ip ) { return ; }
if ( ! ip ) { return ; }
// 系 统 层 面 也 置 为 选 中
[ self . collectionView selectItemAtIndexPath : ip animated : animated scrollPosition : UICollectionViewScrollPositionNone ] ;
[ self . collectionView selectItemAtIndexPath : ip animated : NO scrollPosition : UICollectionViewScrollPositionNone ] ;
// 若 此 时 cell 不 可 见 , willDisplay 再 兜 底
KBVipSubscribeCell * cell = ( KBVipSubscribeCell * ) [ self . collectionView cellForItemAtIndexPath : ip ] ;
KBVipSubscribeCell * cell = ( KBVipSubscribeCell * ) [ self . collectionView cellForItemAtIndexPath : ip ] ;
if ( cell ) { [ cell applySelected : YES animated : NO ] ; }
if ( [ cell isKindOfClass : KBVipSubscribeCell . class ] ) {
[ cell applySelected : YES animated : animated ] ;
}
}
- ( KBPayProductModel * ) currentSelectedPlan {
if ( self . selectedIndex = = NSNotFound ) { return nil ; }
if ( self . selectedIndex < 0 || self . selectedIndex >= self . plans . count ) { return nil ; }
id plan = self . plans [ self . selectedIndex ] ;
if ( ! [ plan isKindOfClass : KBPayProductModel . class ] ) { return nil ; }
return plan ;
}
- ( NSString * ) displayTitleForPlan : ( KBPayProductModel * ) plan {
if ( ! plan ) { return @ "" ; }
if ( plan . productDescription . length ) { return plan . productDescription ; }
NSString * name = plan . name ? : @ "" ;
NSString * unit = plan . unit ? : @ "" ;
if ( name . length && unit . length ) { return [ NSString stringWithFormat : @ "%@%@" , name , unit ] ; }
if ( name . length ) { return name ; }
if ( unit . length ) { return unit ; }
return KBLocalized ( @ "Subscription" ) ;
}
}
# pragma mark - Header Height Calc
# pragma mark - Header Height Calc
@@ -126,8 +179,41 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
# pragma mark - Bottom Actions
# pragma mark - Bottom Actions
- ( void ) onTapPayButton {
- ( void ) onTapPayButton {
// TODO : 接 入 支 付 , 这 里 仅 做 UI
KBPayProductModel * plan = [ self currentSelectedPlan ] ;
[ KBHUD showInfo : KBLocalized ( @ "Pay clicked" ) ] ;
if ( ! plan ) {
[ KBHUD showInfo : KBLocalized ( @ "Please select a product" ) ] ;
return ;
}
NSString * productId = plan . productId ;
if ( productId . length = = 0 ) {
[ KBHUD showInfo : KBLocalized ( @ "Product unavailable" ) ] ;
return ;
}
[ KBHUD show ] ;
__weak typeof ( self ) weakSelf = self ;
[ self . filter requestProductsWith : [ NSSet setWithObject : productId ] completion : ^ ( NSArray < SKProduct * > * _Nonnull products ) {
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
__strong typeof ( weakSelf ) self = weakSelf ;
if ( ! self ) { return ; }
SKProduct * match = nil ;
for ( SKProduct * product in products ) {
if ( [ product . productIdentifier isEqualToString : productId ] ) {
match = product ;
break ;
}
}
if ( ! match ) {
[ KBHUD dismiss ] ;
[ KBHUD showInfo : KBLocalized ( @ "Unable to load product information" ) ] ;
return ;
}
[ [ FGIAPManager shared ] . iap buyProduct : match onCompletion : ^ ( NSString * _Nonnull message , FGIAPManagerPurchaseRusult result ) {
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
[ KBHUD dismiss ] ;
} ) ;
} ] ;
} ) ;
} ] ;
}
}
- ( void ) agreementButtonAction {
- ( void ) agreementButtonAction {
[ KBHUD showInfo : KBLocalized ( @ "Open agreement" ) ] ;
[ KBHUD showInfo : KBLocalized ( @ "Open agreement" ) ] ;
@@ -149,9 +235,16 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
- ( __kindof UICollectionViewCell * ) collectionView : ( UICollectionView * ) collectionView cellForItemAtIndexPath : ( NSIndexPath * ) indexPath {
- ( __kindof UICollectionViewCell * ) collectionView : ( UICollectionView * ) collectionView cellForItemAtIndexPath : ( NSIndexPath * ) indexPath {
if ( indexPath . section = = 1 ) {
if ( indexPath . section = = 1 ) {
KBVipSubscribeCell * cell = [ collectionView dequeueReusableCellWithReuseIdentifier : kKBVipSubscribeCellId forIndexPath : indexPath ] ;
KBVipSubscribeCell * cell = [ collectionView dequeueReusableCellWithReuseIdentifier : kKBVipSubscribeCellId forIndexPath : indexPath ] ;
NSDictionary * plan = self . plans [ indexPath . item ] ;
if ( indexPath . item < self . plans . count ) {
[ cell configTitle : plan [ @ "title" ] price : plan [ @ "price" ] strike : plan [ @ "strike" ] ] ;
KBPayProductModel * plan = self . plans [ indexPath . item ] ;
NSString * title = [ self displayTitleForPlan : plan ] ;
NSString * price = [ plan priceDisplayText ] ;
[ cell configTitle : title price : price strike : nil ] ;
[ cell applySelected : ( indexPath . item = = self . selectedIndex ) animated : NO ] ;
[ cell applySelected : ( indexPath . item = = self . selectedIndex ) animated : NO ] ;
} else {
[ cell configTitle : @ "" price : @ "" strike : nil ] ;
[ cell applySelected : NO animated : NO ] ;
}
return cell ;
return cell ;
} else {
} else {
KBVipReviewListCell * cell = [ collectionView dequeueReusableCellWithReuseIdentifier : kKBVipReviewListCellId forIndexPath : indexPath ] ;
KBVipReviewListCell * cell = [ collectionView dequeueReusableCellWithReuseIdentifier : kKBVipReviewListCellId forIndexPath : indexPath ] ;
@@ -169,7 +262,7 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
# pragma mark - UICollectionView Delegate
# pragma mark - UICollectionView Delegate
- ( void ) collectionView : ( UICollectionView * ) collectionView didSelectItemAtIndexPath : ( NSIndexPath * ) indexPath {
- ( void ) collectionView : ( UICollectionView * ) collectionView didSelectItemAtIndexPath : ( NSIndexPath * ) indexPath {
if ( indexPath . section ! = 1 ) { return ; }
if ( indexPath . section ! = 1 || indexPath . item >= self . plans . count ) { return ; }
if ( self . selectedIndex = = indexPath . item ) { return ; }
if ( self . selectedIndex = = indexPath . item ) { return ; }
NSInteger old = self . selectedIndex ;
NSInteger old = self . selectedIndex ;
self . selectedIndex = indexPath . item ;
self . selectedIndex = indexPath . item ;
@@ -185,7 +278,7 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
- ( void ) collectionView : ( UICollectionView * ) collectionView willDisplayCell : ( UICollectionViewCell * ) cell forItemAtIndexPath : ( NSIndexPath * ) indexPath {
- ( void ) collectionView : ( UICollectionView * ) collectionView willDisplayCell : ( UICollectionViewCell * ) cell forItemAtIndexPath : ( NSIndexPath * ) indexPath {
// 兜 底 : 当 订 阅 项 第 一 次 出 现 在 屏 幕 上 , 强 制 同 步 选 中 样 式
// 兜 底 : 当 订 阅 项 第 一 次 出 现 在 屏 幕 上 , 强 制 同 步 选 中 样 式
if ( indexPath . section = = 1 && [ cell isKindOfClass : KBVipSubscribeCell . class ] ) {
if ( indexPath . section = = 1 && indexPath . item < self . plans . count && [ cell isKindOfClass : KBVipSubscribeCell . class ] ) {
BOOL sel = ( indexPath . item = = self . selectedIndex ) ;
BOOL sel = ( indexPath . item = = self . selectedIndex ) ;
KBVipSubscribeCell * c = ( KBVipSubscribeCell * ) cell ;
KBVipSubscribeCell * c = ( KBVipSubscribeCell * ) cell ;
if ( sel ) {
if ( sel ) {