Изменение внутренних свойств объектов NSO (в частности, SKPaymentTransaction)

Я пытаюсь протестировать наш сервер проверки квитанций, и хотя я могу изменить внутренний API, чтобы избежать этой проблемы, это означает, что мы не полностью тестируем клиентский API, поэтому я бы хотел этого избежать.

Как часть нашего API, мы проходим через SKPaymentTransaction и затем передаем Transaction.transactionReceipt на наш сервер.

Чтобы проверить это правильно, я бы хотел создать экземпляр SKPaymentTransaction с транзакцией по моему выбору (действительные и недействительные значения).

К сожалению, SKPaymentTransaction определяет свойство actionReceipt только для чтения, и я не могу объявить расширение / подкласс, определяющее его как readwrite из-за этого.

Мне также кажется, что я не могу привести указатель SKPaymentTransaction к символу *, чтобы вручную вставить значения в память, поскольку XCode не позволяет этого в ARC.

Кто-нибудь имеет представление о том, как я могу добиться того, что я ищу?

Спасибо ли

2 ответа

Решение

Оказывается, я могу быстро получить получатель транзакции и получить свои данные в вызове.

Так что я получаю что-то вроде

-(void)test_function
{
    SKPaymentTransaction* invalidTransaction = [[SKPaymentTransaction alloc] init];

    Method swizzledMethod = class_getInstanceMethod([self class], @selector(replaced_getTransactionReceipt));
    Method originalMethod = class_getInstanceMethod([invalidTransaction class], @selector(transactionReceipt));

    method_exchangeImplementations(originalMethod, swizzledMethod);

    // Call to receipt verification server
}

- (NSData*)replaced_getTransactionReceipt
{
    return [@"blah" dataUsingEncoding:NSUTF8StringEncoding];
}

Я написал сообщение в блоге, показывающее мой процесс и дающее немного больше деталей здесь.
http://engineering-game-dev.com/2014/07/23/injecting-data-into-obj-c-readonly-properties/

Я вложил в подкласс SKPaymentTransaction (например, MutableSKPaymentTransaction), переопределяя параметры только для чтения. Уже существует изменяемая транзакция SKPaymentTransaction, которую вы можете использовать, или вы можете переопределить SKPayment аналогичным образом.

Пример:

в файле заголовка (MutableSKPaymentTransaction.h)

#import <StoreKit/StoreKit.h>

@interface MutableSKPaymentTransaction : SKPaymentTransaction

@property (readwrite, copy, nonatomic) NSError * error;
@property (readwrite, copy, nonatomic) SKPayment * payment;
@property (readwrite, copy, nonatomic) NSString * transactionIdentifier;
@property (readwrite, copy, nonatomic) NSDate * transactionDate;
@property (readwrite, copy, nonatomic) NSArray * downloads;
@property (readwrite, copy, nonatomic) SKPaymentTransaction *originalTransaction;
@property (assign, nonatomic) SKPaymentTransactionState transactionState;

@end

и в файле метода (MutableSKPaymentTransaction.m):

#import "MutableSKPaymentTransaction.h"

@implementation MutableSKPaymentTransaction

// readonly override
@synthesize error = _error;
@synthesize payment = _payment;
@synthesize transactionIdentifier = _transactionIdentifier;
@synthesize transactionDate = _transactionDate;
@synthesize downloads = _downloads;
@synthesize originalTransaction = _originalTransaction;
@synthesize transactionState = _transactionState;

@end
Другие вопросы по тегам