iOS consuming API design - ios

I am going to develop an iOS app for a web application. (The web app uses code igniter)
I am going to create an API Service that the iOS app will consume.
I am thinking of creating an api version, so when the web api changes, the iOS app will know.
Concerns:
iOS app will need to be updated when web application api changes (unless I keep legacy api available..Is this a good option)
If iOS app is updated when web app api is NOT updated this will cause a problem too
Should my iOS app specify the version of the api it requires?
If iOS app api is less than web api: Display Message: Please update iOS app
If iOS app api is greater than web api: Display Message: Please update web app
Is this best practice?
Should I make an api class for every version and extend the previous version and override methods when they change?
Example
ApiV1 extends CI_Controller
{
function list_customers(){//Code}
function saveSale() {//Code}
}
ApiV2 extends ApiV1
{
function saveSale()
{
//New way of saving sale
}
}
Also what happens if I make a change to the database structure where the v1 api will no longer work? (Example, changed the name of a database table?)

In general, you want to create a fairly loose coupling between your service API and your client. As a rule, there will be multiple versions of the client always floating around in the wild, and you want to force upgrades on users as rarely as possible.
A full rev of an API version is actually somewhat rare in web services, and usually only corresponds to significant changes to the data model, security model, etc. Allowing multiple versions to coexist may require some extra work on the service, but can be worth it to allow existing clients to keep working.
To that end, think carefully in the design up front about the "model" you're using as an abstract entity independent of the current client UI needs. (If you want more specific thinking around your particular case, you may wish to post a separate question about modeling your needs.) But don't worry too much about solving all of the needs forever in advance, because requirements will inevitably change.
Once you've done this, do prepare for the future by building some notion of versioning into the service API. Some things to consider:
An explicit version as part of the URL scheme or specified initially during e.g. auth handshake. This is a way to cleanly namespacing what the client accesses. (The former would result in explicit URL routing on the service, the latter would require more gymnastics to route after cracking an auth token.)
A known error response that means "this API call is obsolete", which an earlier client can recognize to tell the user that their client requires an update
On the service, your design can be as explicit as you note, with a controller with method overrides, but at a little higher level: the saveSale method is somewhat unlikely to behave very differently between versions. It would seem more likely to have a saveSale method in V1 that does the baseline thing, and then maybe e.g. saves some extra bit of data in V2. When that happens, the code might just have conditional branching if that extra bit of data is present. All of this is another way of saying that a service API doesn't actually change incompatibly that often. list_customers could return more information over time. That doesn't necessarily mean that your API needs a new version or that old clients shouldn't just ignore any extra information they don't need.
Re: your final question about database table names. Those may change internally, but you aren't required to map those explicitly to what the client sees. An API is a stable interface that should ideally hide the implementation details of your ever-evolving service.
You'll choose to rev the API when, as a whole, you decide that the overall picture of what the API needs to do is significantly changed enough that it cannot peacefully serve the needs of existing clients. You'll choose to deprecate and obsolete certain client versions when you decide that maintaining support for them on the service is causing you more headache than the install base is worth (a very business/case specific issue).
Good luck.

I don't know if having your iOS app specify the version of the api it requires is good practice but, I would think it is a safe play; one concern though, if you frequently update your api then it won't be long before it becomes a hassle/anoying having to frequently update the app.
I would keep legacy method name(s) and add method(s) with a different name to avoid users having to update to new version of the app when you change the web api.
I would not create an api class for every version to extend the previous version of the api.
I would say changing the database structure would require changing/updating your api, unless you also want to keep legacy version of your table name or definition or data, which it is not feasible/practical/convenient in most instances/situations. In this case you want your users to update to the new app and api.
Look at this answer that points to a presentation of API design principles and practices.

I do not know as to what best practice, however I would definitely recommend that your iOS app keep track of what version of your API it is looking for, and specifically request that version. For instance, a URL of '/api/v1/....'. This way When you update your API, you can simply up it to a different version ('/api/v2/...', and leave v1 alone for the iOS app to consume. Obviously you should display a message to the iOS user to upgrade (perhaps a meta field in your response) when a newer version exists.
This approach should allow you to continue development on your API without cutting off people who haven't been able to upgrade their app.
Update
Just one more thing; if you make a change that will make a previous version inoperable (such as changing table names, schema, etc), you should have a status code for that that your iOS app will understand. Something associated with the message 'This API version has been retired. You must update'.
I would also recommend a similar header (or something) when an API is deprecated (ie, a new version exists). Obviously continue to provided the requested information/actions, however a warning that the version is not supported anymore and that they should upgrade (or even triggering something in your app to upgrade) can be helpful.

Related

Consuming Webhook payloads in Vue/Pinia in real time

So, i'm relatively new to Vue, and I'm currently using it to build a small app that displays order data from Square's API.
I'm currently working on a stack that uses rails to make api calls using the square.rb gem. The frontend is entirely Vue which uses Pinia as a store, and there isnt going to be any kind of database behind this because reasons.
All data is provided directly via Square's API. I am currently polling to update order info, but my client wants to make this app truly real time, as it deals with food deliveries through ride-share companies and the purpose of this app is to show in real time statuses of orders for an in house screen at the restaurant.
Now Square has a webhook subscription service, and based on my reading it sounds like I can consume these to update my app, but there are a few logical leaps that I havent been able to make yet with how to get that data to the frontend of my app.
My questions are the following, with the intent being to connect the dots between the different technologies I might need to employ here to make this work. Kinda get a sense of what i'd need and where to link it up.
Can I use vue to consume webhook payloads directly and update through reactivity? That would be ideal, but I have found no docs yet that give me a good idea of whether thats possible.
If that is not possible, do I need to use some sort of socket connection (socket.io) to listen for these webhook updates?
If the current setup or proposed setup in the questions above is not feasible, what is a better solution for handling this while still using Vue?

What is the JSONAPI equivalent of Ruby on Rails Nested Attributes create/update?

We are considering changing our rails app (which relies heavily on Nested Attributes-style data creation) to use JSONAPI instead. However, it seems that JSONAPI may not support this style of document creation/updating?
I've read around and this is sometimes referred to as "compound documents" or "sideposting". My research has been inconclusive, so posting here in hopes that someone out there knows the deal.
For example if in our app we had a Person that has many PhoneNumber, I would like to be able to send a PATCH to /person/1 that had information relating to phone numbers. RoR Nested Attributes allows for sending new phone numbers (ones without an id), modifying existing ones, and deleting existing ones. Is there an equivalent for this in JSONAPI?
If not, how would a client go about submitting this data to the server? A separate request for every object? On some of our pages that could result in 100 plus requests... and each one would need to be managed for errors indivdually?
JSON:API specification v1.0 does not support to create, update or delete more than one resource with one request. So if your server only supports that version of the specification without any custom modification the client would need to submit separate requests for each resource that should be created, updated or deleted. That means the client needs to handle errors for each one individually. This may include rolling back partial changes if one requests fails in a series of related updates.
The missing support for atomic operations is known to be a problematic limitation for some use cases. It should be resolved with the upcoming v1.1. This version is planned to add extensions to the specification. An extension can extend the specification. An extension Atomic Opersions is proposed, which would add support for creating, updating and deleting multiple resources with one request. A client would be able to provide a list of mutations that must be processed in a linear and atomic manner by matter by a server implementing that extension. This means that the modifications are processed in order and will either completely succeed or fail together.

Need advice on syncing data between iOS devices in one app

I built an in-house app for selling tickets and checking-in students to our High School dances. At the moment the app can scan a QR code with the student's information and add their name to either a "Sales" list or "Check In" list. Then the app can export these lists to a CSV file and we compile all the data.
App works perfectly as expected. NOW I want to be able to sync data between multiple devices so that every device will see an up to date Sales and Check in list. The check in list is most important because then our faculty chaperones can all see who has arrived to the dance in real time. I figured I would need to build a server to hold all the data as opposed to on the individual devices like I am doing now (CoreData). Can anyone please give me guidance or advice as to where to go from here? I am using Swift and developing for iOS 10.
I would just answer the general approach to tackle this problem since the implementations would largely be depending on many factors (what database technology is available, the platform of the server, etc.)
You are absolutely right, you need a server to hold the data. Technically speaking, it is a database that holding the data. Thus, you need a database running on your server (there are tons of selections here: Maria DB, SQL Server, Mongo DB, etc.).
Next, you need to build a web service on top of the database so that the iOS app can interact with the database (add/delete/update/read rows). Web service is a very common layer in full-stack application since you normally don't access the database directly.
Finally, you need to guard your web service with some sort of authentication. I.e. you don't want any random person out there to be able to access your web service without permission. There are many implementations out there to secure your web service and you should be able to google that easily.
Firebase might be the easiest solution. Its pretty simple to setup, and its pretty simple to set up data persistence when you go off line. I'm big on trying to stick with the built in Apple services, but Firebase is hard to beat for simple apps.
Take a look at CloudKit, or perhaps Firebase or Azure, as services that will provide a back end server for you, and give you a tested SDK to build against.

Anonymous contact form iOS app

I currently work at a school and have an idea to create an app that allows students to contact a grown up (for example, the principle) anonymously through an app. The app would quite simply consist of a contact form. I am trying to find out the best, and easiest way to achieve this without setting up servers with a separate API. Does anyone have a suggestion on how to achieve it? Is there any way to set up an e-mail form with a pre set recipient and a built in sender-account? Please guide me in the right direction.
You would need to implement an SMTP client. You can use open source code like skpsmtpmessage
It's likely that their example app could be your solution.
Your biggest problem will be the deployment. You definitely need to pay an $99/y developer account and add all the students device ID's to your account (with a maximum of 100 devices/y) or register all of them as beta tester (I don't know the limitations).
Probably this isn't doable so easily, as it seems you don't have iOS developing experience so far. Maybe you can find something on the app store that works with self hosted databases. But you definitely need to host some kind of webApp/API.
You may want to give Appygram a try to handle the back-end if you are able to set up the contact form itself. While it's a separate hosted API, at least you don't have to build/manage it.
Appygram is a free web service that would allow you to configure all the details such as which adults could be contacted, their point(s) of contact (i.e. email address), and it would process and send all the submissions for you. All your app needs to do is send a form post request.
A nice thing about having this information outside of the iOS app itself is that you can change the contact details on the fly without requiring an update to the iOS app itself. Whether you use Appygram (which, since I contribute to it, I am slightly biased toward!) or something similar, I would say that since this is for students, I would recommend a solution that would allow you to update your configuration without requiring app updates.
Finally, I'd second what Julian said. The challenge here could be with deployment. One possible alternative would be to make this a mobile-friendly web page accessible only via student login or on the school network (or both). Would probably be easier development-wise and wouldn't require installs nor the hurdles that Julian described with device registration, etc. And, Appygram would still work with this setup as well.
Good luck!

Core Data Sync With Multiple Users

I would like to sync a core data app with a user with a different iCloud ID and I am trying to figure out the most graceful way to do this. I do not want the data to sync with all users, but want to be able to sync among family members for instance. From the research I have done, I do not think I can do that using iCloud Core Data sync because it only syncs between devices with the same iCloud ID. I have looked at this stackoverflow answer and read a little bit about Ensembles, Parcelkit and TICoreDataSync, Parse etc., but it is not clear to me if any of those options will allow me to sync with multiple users. Does anyone have a good method for syncing a Core Data app with multiple users?
Ensembles and TiCoreDataSync might work. They can use Dropbox file syncing, so in principle they should work with Dropbox shared folders. I don't think these are the main intended uses, so I suggest contacting the developers and/or doing some good testing yourself before assuming this would actually work.
You'll need to think about the user experience, though. At a minimum, your users would both need Dropbox accounts and would have to set up a shared folder before beginning to sync data this way.
Parcelkit probably won't work. It uses Dropbox's data store API which, unlike other Dropbox services, doesn't appear to support shared data.
Services that do support this kind of sharing exist-- for example, Parse and Firebase-- but make sure to review their pricing carefully before using them. Also of course, there have been any number of projects that have their own custom server back end, but that obviously requires having someone on the team who can do that kind of work.
You need to think about other device types (Android at least) if you want your application to be reaching more users.
I'm doing the same now by the following way:
Setup an online database with proper web services (careful with implementation for security matters - DB should NEVER be exposed by anything other than the web services).
Create a Class for your communication with the server (using Class methods with security handling like authentication and authorisation).
Use the class in your app to communicate with the server (SQL operations are done on the server).
To integrate with CoreData you need to create the model in your app similar to the structure in the backend database. Then you need to create a similar class for the app that deals with only local CoreData.
A higher level class might be required if you want to make sure that operations done on both server and local data storage.
Besides, you have to implement a lot of conditions to make sure that data written in local ONLY after making sure that it is stored online (or create an engine for differed operations to run later).
Another Way if you are familiar with notifications:
Use structured notifications between devices for data operations in order to keep everything in sync with other users. The problem with this is the "Autonomy" of the operations. If two operations were done in approximately the same time, you have to find a way to make sure the order of the operations is done properly (maybe timestamp or something).
I'm looking into the same thing for my app and I 'think' you can do a fairly unsecured version of what you are after using using the public folder in cloud kit as mentioned in this question (no accepted answer at time of posting) : Private data sharing using CloudKit
You would need to find a way to differentiate between data that is truly public and those shared among the users you need and some level of authentication.
I'm going to try exporting a permission file with access permission in it to whomever I want to share with combined with a unique identifier located in that permission file.
Keep in mind, as mentioned in the comments of the linked answer, my implementation will be security by obscurity (thanks for that phrase) unless you find a way of adding proper validation to it but my data is relatively insensitive.
Hope this, or any ridicule in the comments, points you in the right direction : )

Resources