Twitter threads are great when a single, concise thought is simply not enough. Threads are easy to create, but may be distracting to read. This prompted developers to create apps that enhance this experience; on iOS, Threader and Thread It For Twitter (an early adopter of this technique) are examples of nice reading and bookmarking apps built on the Twitter API.
In this tutorial, we’re focusing on iOS 14 using Swift 5.1; if you’re impatient, you can check the sample project on our TwitterDev Github. You’ll notice that the app is actually just a Share Extension built in SwiftUI, which allows us to invoke the reader directly from the Twitter app:
With the new Twitter API, you can build a thread reader experience more efficiently. You can now request a conversation ID field for each Tweet payload and the entire conversation for that Tweet using recent search. Tweets are in a thread when they are to and from the same user, and when they share the same conversation ID, meaning that you’ll be able to unroll a thread from any part of it:
In the v2 Twitter API, each endpoint returns the same payload and accepts the same base query parameters. This makes it very easy to reuse the same code across your project. Let’s define a set of base parameters to request additional fields, such as poll metadata (also new in v2).
While we’re at it, we’re also expanding the author_id field into a fully-fledged user object. This way, we can save precious calls and still render details about the author of the thread.
Like the name suggests, recent search returns Tweets that are no older than seven days. Before pulling a thread using that endpoint, let’s make sure the original Tweet is publicly available and created a week ago or earlier:
Note how the code takes advantage of Swift’s Result type to avoid relying too heavily on callbacks. Twitter.request method encapsulates the networking logic. Inside this method, a semaphore signals when a request is completed. Because all requests run asynchronously in a Grand Central Dispatch closure, you can both chain sequential requests and run multiple requests in parallel if needed.
Working with JSON in Swift is overwhelmingly pleasant, and the new Twitter API also makes it easy to model our native object against what’s returned in the payload. TweetLookupResponse is one of the Codable structs that we’ll define.
We’ll also extend these structs with convenience lookup methods to check if a Tweet contains an expanded attachment in the includes payload. Here’s how to check if a Tweet contains a poll:
Recent search will only return Tweets created in the past seven days, so it’s a good idea to check that the thread is still fresh. The app checks that through a computed property. A simple and easy way that saves you unnecessary requests.
On the topic of optimizing things, the app also implements a straightforward caching mechanism.
You’ll notice that the app only caches search results. That allows it to optimize on Tweet usage caps and rate limiting by requesting the conversation only once. When serving cached content, the app checks that the conversation still exists by making an uncached Tweet lookup request:
Thanks to SwiftUI, the rest is smooth sailing. The app defines a main ConversationView that renders all the parts of a Tweet:
Each component is well defined as a separate view, which allows flexibility in case you want to tweak the appearance of the thread. The app is simply instantiating a UIHostingController to serve the SwiftUI view from the Share Extension:
This is all you need to create a thread reading experience using the latest iOS development stack. Once again, take a look at the finished project on Github. Let us know if you end up building it into your app!