In DeclarativeTextKit, I found the abstraction of an “expression” in my vocabulary to represent the Domain-Specific Language’s instructions useful. Here is an example of a valid block of changes: This uses two kinds of Swift Result Builder to define the DSL’s grammar: The rules of the grammar are essentially this:
The recent release of TableFlip v1.6 is the first one that includes a new in-app purchase (IAP) component I assembled for my projects. It’s used in TableFlip to purchase a lifetime license within the app.
With future releases, the package will support in-app purchases of consumables or individual features, too.
A FastSpring account with the modern backend that everyone gets. (If you are still on “Classic”, you’ll know.)
Create an Embedded Storefront to display a very minimal shopping UI on a HTML page. Put this on your website or another trusted source: You will have to tell FastSpring that the form is legit with a domain-based allow-list, so you should really own the source.
Include the package in your app and point to the URL of your self-hosted embedded storefront.
Bonus: if you use my Trial and Licensing package, you can quickly unlock the app after a purchase has been made. The IAP component notifies your app on success.
With that in place, you can display a dedicated purchase window inside your app that doesn’t require a large context switch to the browser to make a sale:
TableFlip’s dedicated purchase window
The setup is quite short. I use a dedicated service object:
classPurchaseLicense{letstore:FastSpringStoreinit(){self.store=FastSpringStore(storeURL:storeURL,purchaseCallback:{store,purchasesin// Could have multiple purchased items, e.g. if you// offer in-app purchases of bundled features.assert(purchases.count==1)guardletpurchase=purchases.firstelse{return}forlicenseinpurchase.licenses{// Unlock via license.licenseName & license.licenseCode, e.g.// using the https://github.com/CleanCocoa/TrialLicensing package://// TrialLicensing.AppLicensing.register(// name: license.licenseName,// licenseCode: license.licenseCode// )}})}funcshowStore(){// Localize and customize the window title:store.showStore(title:"Purchase MyApp")}}
I introduced this feature to my apps because its predecessor was a popular choice to purchase a license among WordCounter users. There, it is being picked for about 50% of license sales in total.
It appears that if the option exists, it will be used. I can’t tell whether having this option actually increases sales or not, though.
There’s been progress on the Declarative Text Kit API idea, and today I want to share an insight into building a DSL with Swift Result Builders. A detail that I didn’t grok until I built it. {{TOC}} Inserting text into a string, text view, or other kind of text buffer is simple enough: you need a location and then use the appropriate API to put a string into the target there.
I invested the past two weeks into making the Markdown highlighting component of my app The Archive better overall. More secure C token pointer handling, more performant token tree mutations, so faster highlighting and fewer pitfalls to worry about.
Use open source liberally to make progress. Avoid open source dependencies in the long run if you can. Start a project by ingesting open source libraries to make progress fast and see if your product works. That’s fine. If it’s not too much, you can leave them in. But when the product matures, and if you offer a library yourself, you may benefit from reducing dependencies to ease product maintenance. Pick what you really need:
As the saying goes, if the title of a post is a question, the answer is “no”. I don’t know how you would sensibly apply that to this one 🙂 Most of the days, for most of the time, I’m a software developer. I code, I plan, I think and learn. At other times, I’m writing things: on this blog, for book manuscripts, as letters and email; to plan, to help, to teach and to share.