Fetching SKProduct Price into UICollectionView Cell Label

109 Views Asked by At

I'm facing a issue where when I fetch SKProduct locale price on to the label.text of my UICollectionView, Its displaying correctly, however the prices jump around in different labels depending on how fast the page is being loaded.

TopUpViewController (UICollectionView) -> TopUpMoneyCell (MoneyLabel)

Any idea how to solve this? Currently I'm calling SKProduct in TopUpMoneyCell. I have a array of 4 in app product to be called, each with different value.

Should I call it from TopUpViewController instead? If so, how should I pull the data I got from TopUpViewController to TopUpMoneyCell?

Edit 1: Added UI Mockup, once again thanks for commenting.

View of UI Mockup

3

There are 3 best solutions below

0
JG_ On BEST ANSWER

Okay I managed to solve my issue. Would appreciate if anyone could help to simplify my code :) Below is an extract of the code.

#import "TopUpMoneyCell.h"
#import "TopUpMoneyModel.h"
#import <StoreKit/StoreKit.h>

@interface TopUpMoneyCell() <SKProductsRequestDelegate>
@property (nonatomic,strong) NSString *purchID;
@property (nonatomic,strong) NSArray *products;
@property (nonatomic,strong) NSArray *productID;
@property (nonnull,strong) IAPCompletionHandle handle;
@property (strong,nonatomic) SKProductsRequest *request;
@property (strong,nonatomic) SKProduct *firstProduct;
@property (strong,nonatomic) SKProduct *secondProduct;
@property (strong,nonatomic) SKProduct *thirdProduct;
@property (strong,nonatomic) SKProduct *fourthProduct;
@property (strong,nonatomic) NSString *firstProductPrice;
@property (strong,nonatomic) NSString *secondProductPrice;
@property (strong,nonatomic) NSString *thirdProductPrice;
@property (strong,nonatomic) NSString *fourthProductPrice;
@property (nonatomic, weak) UILabel *firstPriceLabel;
@property (nonatomic, weak) UILabel *secondPriceLabel;
@property (nonatomic, weak) UILabel *thirdPriceLabel;
@property (nonatomic, weak) UILabel *fourthPriceLabel;
@end

@implementation AQTopUpMoneyCell

- (UILabel *)priceLabel {
    if (!_priceLabel) {
        UILabel *label = [[UILabel alloc] init];
        _priceLabel = label;
        label.textAlignment = NSTextAlignmentCenter;
        label.text = @"";
    }
    return _priceLabel;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self productsInfoRequest];
        [self cnyLabel];
    }
    return self;
}

- (void)productsInfoRequest {
                _productID = [NSArray arrayWithObjects:@"100",@"200",@"300",@"400", nil];
               SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithArray:_productID]];
                request.delegate = self;
                [request start];
    }

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
    {
        NSSortDescriptor *mySortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"price" ascending:NO];
        NSMutableArray *_productsAvailable = [[NSMutableArray alloc] initWithArray:response.products];
        [_productsAvailable sortUsingDescriptors:[NSArray arrayWithObject:mySortDescriptor]];

        self.firstProduct = response.products[0];
        self.secondProduct = response.products[1];
        self.thirdProduct = response.products[2];
        self.fourthProduct = response.products[3];

        NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
        [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
        [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
        [numberFormatter setLocale:_firstProduct.priceLocale];
        self.firstProductPrice = [numberFormatter stringFromNumber:_firstProduct.price];
        self.secondProductPrice = [numberFormatter stringFromNumber:_secondProduct.price];
        self.thirdProductPrice = [numberFormatter stringFromNumber:_thirdProduct.price];
        self.fourthProductPrice = [numberFormatter stringFromNumber:_fourthProduct.price];

        static int counter = 0;
        if (counter == 4) {
            counter = 0;
        }
        if ( [_productsAvailable count] > 0){
            if (_indexPath.row == 0)
            {[self.priceLabel setText:_firstProductPrice];}
            if (_indexPath.row == 1)
            {[self.priceLabel setText:_secondProductPrice];}
            if (_indexPath.row == 2)
            {[self.priceLabel setText:_thirdProductPrice];}
            if (_indexPath.row == 3)
            {[self.priceLabel setText:_fourthProductPrice];}
            counter++;
        }
    }

#pragma mark - SKProductsRequestDelegate
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
#if DEBUG
    NSLog(@"log-IAP> request -> failedWithError: %@", error);
    [SVProgressHUD showErrorWithStatus:@"Request timed out. Try again later."];
#endif
}

- (void)requestDidFinish:(SKRequest *)request{
#if DEBUG
    NSLog(@"log-IAP> requestDidFinish?");
#endif
}


- (void)setIndexPath:(NSIndexPath *)indexPath {
    _indexPath = indexPath;
    NSString *imageName = [NSString stringWithFormat:@"touupbg_%ld",indexPath.row];
    self.bgImageV.image = [UIImage imageNamed:imageName];
    if (indexPath.row == 0) {
        [self.bgImageV mas_updateConstraints:^(MASConstraintMaker *make) {
            make.height.equalTo(kScale(367*scale));
            make.width.equalTo(kScale(308*scale));
        }];
    } else if (indexPath.row == 1) {
        [self.bgImageV mas_updateConstraints:^(MASConstraintMaker *make) {
            make.height.equalTo(kScale(380*scale));
            make.width.equalTo(kScale(308*scale));
        }];
    }else if (indexPath.row == 2) {
        [self.bgImageV mas_updateConstraints:^(MASConstraintMaker *make) {
            make.height.equalTo(kScale(373*scale));
            make.width.equalTo(kScale(316*scale));
        }];
    }else if (indexPath.row == 3) {
        [self.bgImageV mas_updateConstraints:^(MASConstraintMaker *make) {
            make.height.equalTo(kScale(403*scale));
            make.width.equalTo(kScale(308*scale));
        }];
    }else if (indexPath.row == 4) {
        [self.bgImageV mas_updateConstraints:^(MASConstraintMaker *make) {
            make.height.equalTo(kScale(400*scale));
            make.width.equalTo(kScale(308*scale));
        }];
    }else if (indexPath.row == 5) {
        [self.bgImageV mas_updateConstraints:^(MASConstraintMaker *make) {
            make.height.equalTo(kScale(401*scale));
            make.width.equalTo(kScale(317*scale));
        }];
    }
}
@end
0
picciano On

Take a look at overriding the prepareForReuse() function in your TopUpMoneyCell. In that function, cancel any asynchronous calls that you may have started to load the price.

0
BenW On

Without seeing any code, it's a little difficult to see what you're doing, but it sounds like you might want to have your TopUpViewController conform to the UICollectionViewDataSource protocol (https://developer.apple.com/documentation/uikit/uicollectionviewdatasource?language=objc)

Then you could implement something like the following there:


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
                  cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell* cell = [self.testCollectionView dequeueReusableCellWithReuseIdentifier:@"SomeReuseID"
                                                                                    forIndexPath:indexPath];

    // set your custom labeling on the cell here (you probably have a subclass)

    return cell;
}

Don't forget to tell the UICollectionView what to use for its dataSource.

From what you are describing, it sounds like your cells are querying some source of data directly, so that when the UICollectionView chooses to reuse a cell, the labels are not in the order you intend.