2011-08-22 5 views
21

Chạy thử nghiệm để mua ứng dụng của tôi (lần đầu tiên thực hiện trong mua ứng dụng). Tôi nhận được EXC_BAD_ACCESS trên dòng thứ ba của mã này:EXC_BAD_ACCESS trong khi thử nghiệm mua ứng dụng

SKPayment *payment = [SKPayment paymentWithProduct:electronicProd]; 
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; 
    [[SKPaymentQueue defaultQueue] addPayment:payment]; 

Dưới IBAction cho một nút. electronicPack được khai báo trong tiêu đề dưới dạng SKProduct. Đã ném một số NSLog trong các sản phẩmRequest didReceiveResponse và khi sản phẩm được yêu cầu (trong viewDidLoad) và chúng cho thấy nó đã tìm nạp đúng sản phẩm và lưu trữ nó trong gói điện tử. Định nghĩa gói điện tử là [[request.products] objectAtIndex: 0] trong trang didReceiveResponse. Thật vậy. Đó là nơi im tại, không biết phải làm gì. Bất kỳ trợ giúp được đánh giá cao.

UPDATE: cố định vô tình để lại trong mã đã được bổ sung thêm một người quan sát giao dịch thêm lol

+0

Trong định nghĩa electronicProd, bạn đã gọi giữ lại tin nhắn? Mỗi sự kiện được bao bọc trong một nhóm autorelease, nếu bạn khởi tạo đối tượng của mình bằng phương thức init tĩnh, mục đó sẽ được giải phóng khi phương thức viewDidLoad kết thúc. – andreamazz

+0

bạn có hỏi tôi có thích: gói điện tử = [SKProduct alloc] init] ? Câu trả lời cho điều này là không. Nếu đó không phải là những gì bạn yêu cầu thì im không chắc chắn những gì bạn đang nói, im một chút mới để ballgame này. lol –

+0

Im không quá tốt với việc quản lý toàn bộ bộ nhớ, công cụ tài sản. và tất cả điều đó. Chỉ được lập trình khoảng một tháng và havent khá chọn mà lên được nêu ra. Bệnh cho rằng một thử tho và xem nếu nó sửa chữa bất cứ điều gì EDIT: thực hiện self.elec .. etc công cụ và không thay đổi. vẫn gặp lỗi –

Trả lời

9

Bạn cần phải giữ lại các đối tượng mà bạn đang tạo

- (void)viewDidLoad { 
    //... stuff 
    SKProduct* electronicProduct = //... 
    [electronicProduct retain]; 
    //... otherstuff 
} 

viewDidLoad được bọc bởi hệ thống trong một hồ bơi autorelease , paymentWithProduct: trả về một đối tượng autorelease. Khi viewDidLoad được thực hiện, tất cả các đối tượng autorelease được phát hành, đó là lý do tại sao bạn nhận được một truy cập bộ nhớ xấu khi bạn cố gắng truy cập vào nó sau này.

39

Tôi đã có cùng một vấn đề, giải pháp của tôi là để gọi

[[SKPaymentQueue defaultQueue] removeTransactionObserver:self]; 

trên rời khỏi In-App Store trong App của tôi. Có thể nó sẽ giúp ai đó trong tương lai.

+1

Bạn đã lưu ngày của tôi! Cảm ơn! –

+0

Ohhoo .. Tuyệt vời .. Cảm ơn –

+0

Đã làm việc cho tôi, cảm ơn bạn! – JustMe

26

Có vẻ như vấn đề là do cố gắng thêm người quan sát giao dịch trước khi xóa người quan sát trước đó. Thêm phần sau vào bộ điều khiển của bạn để khắc phục sự cố này:

- (void)viewDidDisappear:(BOOL)animated 
{ 
    [super viewDidDisappear:animated]; 
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self]; 
} 

Hy vọng điều này sẽ hữu ích!

+1

Đây là câu trả lời cho tôi. Vẫn hợp lệ với Xcode 6.3 và iOS 8.3 – Paul

+2

Tuyệt vời, cảm ơn !! Đối với tôi điều này cũng đã làm việc, sử dụng mã từ Mihael Isaev (dưới đây) và đưa nó vào ViewDidDisappear. – Pieter

2

Tôi đã gặp lỗi tương tự, khá đơn giản để giải quyết thực sự. Trong tập tin tiêu đề của tôi, tôi đã có một SKProduct tuyên bố:

@property SKProduct *product; 

Tôi chỉ thay đổi nó để:

@property (retain) SKProduct *product; 

và tất cả hoạt động tốt. Hy vọng điều này sẽ giúp ai đó.

+0

dường như giải quyết được vấn đề của tôi. – NSGodMode

11

Câu trả lời của Mr.T là giải pháp tốt nhất!

Trong nhanh chóng tôi gọi removeTransactionObserver này ở đây:

deinit { 
    SKPaymentQueue.defaultQueue().removeTransactionObserver(self) 
} 
+0

Bạn làm deinit ở đâu !? tệp appdelegate !? – Learn2Code

0

I Have cùng một vấn đề, giải pháp của tôi là để gọi [[SKPaymentQueue defaultQueue] removeTransactionObserver: tự];

trên cửa hàng giao dịch quan sát viên kết thúc/thất bại/callbacks hoàn

1

Nếu bạn đang tạo một lớp dành riêng cho SKPaymentTransactionObserver đừng quên rằng nó phải được giữ lại.

Tôi đã nhận lỗi trước khi nhận ra điều này, sau đây là một ví dụ trong AppDelegate:

class AppDelegate: UIResponder, UIApplicationDelegate { 

    var window: UIWindow? 
    var myTransactionObserver: MyTransactionObserver! 


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 

     // don't 
     let myTransactionObserver = MyTransactionObserver() 

     // do 
     myTransactionObserver = MyTransactionObserver() 

     SKPaymentQueue.default().add(myTransactionObserver) 

     return true 
    } 

    // ... 
}