About In-App Purchase: 5. Delivering Products

The summary of the official documentation of Apple Developer, About In-App Purchase.

Purchase process 3): Delivering Products

Your app
– waits for the App Store to process the payment request,
– stores information about the purchase for future launches,
– downloads the purchased content,
– marks the transaction as finished

Waiting for the App Store to Process Transactions

The transaction queue
– lets your app communicate with the App Store through the StoreKit framework.
– to which you add work that the App Store needs, e.g. payment request.

When the transaction’s state changes (e.g. when a payment request succeeds),
– StoreKit calls the app’s transaction queue observer.

In very small apps,
=> you could handle all the StoreKit logic in the app delegate, including observing the transaction queue.
In most apps,
=> you create a separate class that handles this observer logic along with the rest of your app’s store logic.

SKPaymentTransactionObserver (protocol)
– The observer must conform to

——
Using an observer: your app doesn’t constantly poll the status of its active transactions.

Your app also uses the transaction queue
– for payment requests,
– to download Apple-hosted content
– to find out that subscriptions have been renewed.

——
when your app is launched
– Register a transaction queue observer [4-1].
– Make sure that the observer is ready to handle a transaction at any time, not just after you add a transaction to the queue.
e.g. a user bought something in your app right before going into a tunnel.
=> Your app isn’t able to deliver the purchased content because there’s no network connection.

The next time your app is launched:
StoreKit
– calls your transaction queue observer again
– delivers the purchased content

e.g. if your app fails to mark a transaction as finished
=> StoreKit calls the observer every time your app is launched until the transaction is properly finished.

Listing 4-1 Registering the transaction queue observer

paymentQueue:updatedTransactions: (method)
– a method called by StoreKit.
– Implement it on your transaction queue observer.
– StoreKit calls when the status of a transaction changes
e.g. when a payment request has been processed.

The transaction status
– tells you what action your app needs to perform [4-1] [4-2]
– Transactions in the queue can change it in any order.

Your app needs to be ready to work on any active transaction at any time.

Table 4-1 Transaction statuses and corresponding actions

Listing 4-2 Responding to transaction statuses

SKPaymentTransactionObserver (protocol)
– from which the transaction queue observer can implement optional methods
– keeps your user interface up to date while waiting as follows.

paymentQueue:removedTransactions: (method)
– is called when transactions are removed from the queue
– remove the corresponding items from your app’s UI.

paymentQueueRestoreCompletedTransactionsFinished: (method)
paymentQueue:restoreCompletedTransactionsFailedWithError: (method)
– is called when StoreKit finishes restoring transactions, depending on whether there was an error.

In your implementation of these methods,
=> update your app’s UI to reflect the success or error.

Persisting the Purchase

After making the product available,
your app
– needs to make a persistent record of the purchase.
– uses that persistent record on launch to continue to make the product available.
– uses that record to restore purchases
– whose persistence strategy depends the type of products you sell and the versions of iOS.
—-
– For non-consumable products and auto-renewable subscriptions
[iOS 7 and later] => use the app receipt as your persistent record.
[earlier than iOS 7] => use the User Defaults system or iCloud to keep a persistent record.

– For non-renewing subscriptions,
=> use iCloud or your own server to keep a persistent record.

– For consumable products
=> your app updates its internal state to reflect the purchase, but there’s no need to keep a persistent record because consumable products aren’t restored or synced across devices.
Ensure that
– the updated state is part of an object that supports state preservation (in iOS)
– you manually preserve the state across app launches (in iOS or macOS).
—-
When using the User Defaults system or iCloud,
=> your app can store a value, such as a number or a Boolean, or a copy of the transaction receipt.

In macOS,
=> the user can edit the User Defaults system using the defaults command.

Storing a receipt requires more application logic,
but prevents the persistent record from being tampered with.

When persisting via iCloud,
=> note that your app’s persistent record is synced across devices,
but your app is responsible for downloading any associated content on other devices.

Persisting Using the App Receipt

The app receipt contains
– a record of the user’s purchases,
– cryptographically signed by Apple.

Information about consumable products
– is added when they’re paid for and remains in the receipt until you finish the transaction.
– is removed the next time the receipt is updated—for example, the next time the user makes a purchase after you finish the transaction

Information about all other kinds of purchases
– is added to the receipt when they’re paid for
– remains in the receipt indefinitely.

Persisting a Value in User Defaults or iCloud

Set the value for a key
– to store information in User Defaults or iCloud

Persisting a Receipt in User Defaults or iCloud

Set the value for a key to the data of that receipt
– to store a transaction’s receipt in User Defaults or iCloud

Persisting Using Your Own Server

Send a copy of the receipt to your server along with some kind of credentials or identifier
=> so you can keep track of which receipts belong to a particular user.
e.g. let users identify themselves to your server with an email or user name, plus a password.

Don’t use the identifierForVendor property of UIDevice
– you can’t use it to identify and restore purchases made by the same user on a different device,
– different devices have different values for this property.

Unlocking App Functionality

If the product enables app functionality,
set a Boolean value to
– enable the code path
– update your user interface as needed.

Consult the persistent record that your app made when the transaction occurred.
– to determine what functionality to unlock,

Your app needs to update this Boolean value
– whenever a purchase is completed
– at app launch.

e.g. using the app receipt:

e.g. using the User Defaults system:

Then use that information
– to enable the appropriate code paths in your app.

Delivering Associated Content

If the product has associated content, your app needs to deliver that content to the user.
e.g. purchasing a level in a game requires delivering the files that define that level
e.g. purchasing additional instruments in a music app requires delivering the sound files needed to let the user play those instruments.

– You can embed that content in your app’s bundle
– you can download it as needed
=> Each approach has its advantages and disadvantages.

If you include too little content in your app bundle,
– the user must wait for even small purchases to be downloaded.

If you include too much in your app bundle,
– the initial download of the app takes too long
– the space is wasted for users who don’t purchase the corresponding products.
– users won’t be able to download it over cellular networks.

Embed smaller files (up to a few megabytes) in your app, especially if you expect most users to buy that product.
[+] Content in your app bundle can be made available immediately when the user purchases it.
[-] To add or update content in your app bundle, you have to submit an updated version of your app.

Download larger files when needed.
– Separating content from your app bundle keeps your app’s initial download small.
e.g. a game can include the first level in its app bundle and let users download the rest of the levels when they’re purchased.
– Assuming your app fetches its list of product identifiers from your server,
– not hard-coded in the app bundle,
– you don’t need to resubmit your app to add or update content that is downloaded by your app.

In iOS 6 and later,
– most apps should use Apple-hosted content for downloaded files.
– You create an Apple-hosted content bundle using the In-App Purchase Content target in Xcode and submit it to iTunes Connect.
– When you host content on Apple’s servers you don’t need to provide any servers
– your app’s content is stored by Apple using the same infrastructure that supports other large-scale operations, such as the App Store.
– Apple-hosted content automatically downloads in the background even if your app isn’t running.

You might choose to host your own content if you already have server infrastructure,
– if you need to support older versions of iOS,
– if you share your server infrastructure across multiple platforms.

Note:
You can’t patch your app binary or download executable code.
– Your app must contain all executable code needed to support all of its functionality when you submit it.
– If a new product requires code changes, submit an updated version of your app.

Loading Local Content

Load local content using the NSBundle class,
– just as you load other resources from your app bundle.

Downloading Hosted Content from Apple’s Server

When the user purchases a product that has associated Apple-hosted content,
– the transaction passed to your transaction queue observer also includes an instance of SKDownload that lets you download the associated content.
—-
To download the content,
– add the download objects from the transaction’s downloads property to the transaction queue
– by calling the startDownloads: method of SKPaymentQueue.

If the value of the downloads property is nil,
– there’s no Apple-hosted content for that transaction.

Unlike downloading apps,
– downloading content doesn’t automatically require a Wi-Fi connection for content larger than a certain size.
– Avoid using cellular networks to download large files without an explicit action from the user.
—-
Implement the paymentQueue:updatedDownloads: method on the transaction queue observer
– to respond to changes in a download’s state—for example, by updating progress in your UI.
– If a download fails, use the information in its error property to present the error to the user.
—-
Ensure that your app handles errors gracefully.
e.g. if the device runs out of disk space during a download,
– give the user the option
– to discard the partial download or
– to resume the download later when space becomes available.
—-
Update your user interface while the content is downloading
– using the values of the progress and timeRemaining properties.
– You can use the pauseDownloads:, resumeDownloads:, and cancelDownloads: methods of SKPaymentQueue from your UI to let the user control in-progress downloads.
– Use the downloadState property to determine whether the download has completed. – Don’t use the progress or timeRemaining property of the download object to check its status—these properties are for updating your UI.

Note:
Download all Apple-hosted content before finishing the transaction.
After a transaction is complete,
– its download objects can no longer be used.

Prefer readonly to const

51zy3ojm4kl-_sx379_bo1204203200_

Effective C# (Covers C# 4.0): 50 Specific Ways to Improve Your C# by Bill Wagner.

C# has two different versions of constants:

runtime constant: readonly
– slightly slower, but far flexible.
– cannot be declared with method scope.
– can be any type.
– resolved at runtime.
– The IL is generated when you reference a readonly constant references the readonly variable, not the value.
– So you can distribute an infrastructure assembly includes runtime constant without rebuilding the application assembly.

compile-time constant: const
– slightly faster, but far less flexible.
– can be declared inside methods.
– can be used only for primitive types (built-in integral and floating-point types), enums, or strings.
– cannot be initialized using the new operator, even when the type being initialized is a value type.
– Use when performance is critical.
– Use when the value will never change between releases.

From Effective C# (Covers C# 4.0): 50 Specific Ways to Improve Your C# by Bill Wagner.

C# Performance Tricks: How To Radically Speed Up Your Code

Finished an online program @ Udemy.

スクリーンショット 2017-02-01 7.58.15
C# Performance Tricks: How To Radically Speed Up Your Code

Codility – Lesson 5 Prefix Sums – MinAvgTwoSlice

プログラミング能力を評価するオンラインテスト、Codilityで、Lesson 5 Prefix Sums – MinAvgTwoSliceに回答しました。

問題と結果画面
50%の評価。

Design Patterns

415dbbsnrcl

C# Design Pattern Essentials by Tony Bevis.

Chapter 01
——————
Creational Patterns
——————
Abstract Factory
Builder
Factory Method
Prototype
Singleton

——————
Structural Patterns
——————
Adapter
Bridge
Composite
Decorator
Facade
Flyweight
Proxy

——————
Behavioural Patterns
——————
Chain of Responsibility
Command
Interpreter
Iterator
Mediator
Memento
Observer
State
Strategy
Template Method
Visitor
(more…)

ページトップへ