Circular Scrolling + Inertia

Why Inertia?

I’ve talked a lot on this blog about the circular scroll-view/table-view thing I created for my metronome app, and while I’m very pleased with how the whole thing turned out, I was still annoyed that I hadn’t figured out how to do one thing: give it inertia like UIScrollView. A commenter on one of the posts even asked me about inertia, and I basically just flat out said I’d like to, but it would be too hard! But after that, it just kept bugging me; there had to be a way. Inertial scrolling on iOS – and now on OS X too – just feels so nice. It’s one of those things that many people probably don’t even think about or notice until it’s gone. After feeling the smooth scrolling and realistic deceleration of UIScrollViews, my little rotary control just feels like garbage. I mean, come on, you give it a little flick and it stops rotating immediately when you lift your finger!? Lame! Frankly, my control just doesn’t feel quite completely at home on iOS yet, and I want to change that.

Maybe UIScrollView Can Help!

I got really exciting after watching the WWDC 2012 video for Session 223: Enhancing User Experience with Scroll Views. In the presentation, they give an excellent demo of how to leverage the physics of UIScrollView even when your app uses OpenGL. The UIScrollView is not used for any drawing, but by passing touches through it, listening for the scrollViewDidScroll, and reading the contentOffset, you can enjoy all the benefits of UIScrollView like inertia and edge bounce without actually drawing your content in the scroll view itself. Maybe, I thought, I can use that same trick on my circular scroller. Using the same techniques from the video, I was able to get up and running with the same circular action as well as a bit of UIScrollView provided inertia, but it just did not feel right at all. The geometry of linear scrolling and deceleration just don’t line up with what I need in terms of angular rotation.


The video technique didn’t work out quite like I had hoped, but I still took away one key idea: implement the inertia in the touch handler, not in the circular view itself. Seeing as how no one has seen the details of my implementation, that might not make sense to anyone but me right now, but I’ll try to explain. At its most basic, my control has two parts: the transparent view which interprets the touches as circular movements (a gesture recognizer, if you will, although it’s not an actual UIGestureRecognizer subclass) and the display view that receives notifications of those movements and rotates, swapping elements in and out sort of like UITableView cells. I had already implemented a bit of animation in the view component that allowed it to center on a certain cell, and I kept trying to think how I could make this also work with a longer rotation, and I was running into a lot of problems with the cell swapping during the rotation animation. But, if I implement the inertia on the control side and use the same delegate call for rotation that comes from an actual touch OR from the inertia, the view side doesn’t even know the difference. And it actually worked pretty well without much modification at all!

Check out the Repo

So, here’s the real/final point of this post: I’d love to get this whole rotation control thing (or most of it, at least) out into the wild as an open source component, but it’s been hard finding the time. It’s a fairly complex API, and I don’t feel like I can just release it without some more clarity and focus, as well as a nice sample project. So, I’m going to try to get it out there piece by piece if possible. I’ve put up a little bare bones project on GitHub – my first! – to test the waters. Let me know what you think, and of course, feel free to fork it and make it better. Right now it’s just a simple version of the rotation control view (RDDRotationControlSurface) which is hooked up to a UIViewController delegate that spins a UIImageView based on the input. Wow, that sounds way more complicated than it is – it’s just spinning a little picture of a very nice-looking German (or Austrian; can’t remember where this picture was taken) man in a cool getup. Don’t ask me why I chose this picture; it was there, and I went with it!

PS: You may be wondering why I didn’t go with a UIGestureRecognizer subclass for this. As far as I can tell, the gesture recognizer API would not work very well with something like this which needs to continue sending updates even after all touches have stopped. So, in the end, I’d still end up with a UIView subclass of some kind. Doesn’t mean GR couldn’t help here, but I just didn’t go that route.


Macro for Device Specific Settings (There’s a new iPhone Screen Size!)

iPhone 5

Well, it finally happened. Apple is releasing an iPhone with a different screen size and aspect ratio. “Oh no!” everyone screamed. iOS is headed down the path of Android! Fragmentation is here!! OK, there’s probably (almost ) no one actually saying that. Yes, there’s a new device, but the fragmentation situation for Apple – even including the various combination of screen size, processor type, iOS version, etc. – doesn’t even come CLOSE to that of Android. The fact is, Apple know what they’re doing. Agree or disagree with their reasoning for the iPhone 5’s new screen, it’s clear that they don’t take this type of change lightly. I mean, just listen to how Sir Jonathan Ive opens this video. How can you not agree with everything this man ever says?!

The first big “disruption” to the iOS ecosystem, was of course, the iPad. But guess what, Apple took careful measures to make sure that every single existing app would automatically run. I’m sure there were examples of apps that didn’t take to the simulated iPhone environment perfectly, but for the most part, everything just worked. And that was no small feat of engineering, I’m sure! Yes, we were all pushed to build native apps for the iPad, but they weren’t going to immediately alienate thousands of developers and millions of app users just because they decided to make a cool new device. The next disruption was iPhone 4 and Retina Display. Once again, great new technology for those who incorporate it, but in the meantime, existing apps for the most part ran just fine. And now, last week, the 4″ screen of the iPhone 5. But guess what, all existing apps will run just fine, only letter-boxed. But what about those who want to take advantage of this new technology, to create an app that makes full use of that new tall screen? Continue reading “Macro for Device Specific Settings (There’s a new iPhone Screen Size!)”

UIKit and GCD

Graphics Bottlenecks

Creating a responsive user interface is one of the most important considerations for a mobile developer, and the smooth scrolling and quick responsiveness of iOS has been one of its hallmarks since day 1. — I’ve gotta be honest here; I still find myself every now and then finding great amusement in just flicking around a simple web view or scrolling some text on my phone. It just feels so right! — Keeping a smooth flow and one to one correspondence between user touch and visual display is crucial for maintaining the illusion and feeling that one is directly interacting with the objects on the screen. One key consideration to make this happen is do not block the main thread. If you are doing anything that might take a significant amount of time, you must do this on a background thread.

With iOS 4.0 and the introduction of blocks and Grand Central Dispatch, it became much easier to complete tasks in the background asynchronously without having to dive into the implementation details of threads and such. If you haven’t yet tried out GCD, take a look at the docs, or check out this tutorial to get you up and running quickly. It’s great for parsing data, downloading from the network, etc. off the main thread, and GCD makes it very easy to write code that will call back into the main thread once the background process completes. What it doesn’t work well for is anything to do with UIKit or the user interface. All drawing and touch interaction takes place, by design, on the main thread. So, what do you do if your drawing itself is taking too long and blocking the main thread? I’m sure there were people much cleverer than me who found some ways to get around it and do some drawing in the background, but basically up until iOS 4, UIKit was not thread-safe at all. If your drawing is too complicated and blocks, then you need to optimize it or simplify it. However, the release notes for iOS 4.0 contain the following short section:

Drawing to a graphics context in UIKit is now thread-safe. Specifically:

  • The routines used to access and manipulate the graphics context can now correctly handle contexts residing on different threads.
  • String and image drawing is now thread-safe.
  • Using color and font objects in multiple threads is now safe to do.

This was not something I had really been interested in or concerned myself with until I ran into just such a problem recently. I created a custom subclass of UILabel which adds a colored, blurred shadow to the label to give it a glow effect. But, this drawing took drastically longer than the regular string drawing. For example, for the drawing that happens at app startup, using regular UILabels takes 104 milliseconds total in drawRect:. To draw the exact same strings with shadows takes 1297 milliseconds! So, you can imagine what this does to frame rates when there are multiple labels being updated rapidly during an already CPU intensive section of the code.

Multi is fun threading!

Since I already know ahead of time exactly what strings I need to display during this particular bottleneck, it would be nice to be able to draw all the labels at once in the background and cache them for later. My first approach was, Continue reading “UIKit and GCD”

SVG to CoreGraphics Conversion

*UPDATE – August 2, 2014*

There’s been a LOT of different tools come out in the last several years since I posted this. I’m still seeing a fair amount of traffic showing up here from google, so I thought I’d stick in a little update here with some links to newer apps/tools/converters for generating CoreGraphics code from other file types or graphical editors. I haven’t tried all of these, and I have no connection to their creators, just providing some links.

I’m sure there’s more, so let me know in the comments if you’ve got another one. Hope this helps, and if you’re still interested in going into the SVG standard a little deeper or in seeing what I did earlier, then read on!


I’ve got another tutorial type post for today, but it’s really equal parts: “here’s what I found that helped but didn’t quite work,” “here’s what I did,” and, “anybody have any better ideas?” If you already know something about Core Graphics and why/when to use it and just want the gist of what I did to convert SVG files to Core Graphics calls, go ahead and skip on down to “SVG to the Rescue.” Otherwise, read on to hear about my experience.

Why Core Graphics?

If you’ve spent any time programming for iOS or OSX, you’ve probably been exposed at some level to the Core Graphics frameworks, otherwise known as Quartz. (BTW, if you’re looking for documentation in Xcode, you have to search “Quartz” in Xcode to find the Programming Guide. Searching “Core Graphics” won’t get you anything helpful. A common occurrence with the Xcode documentation browser in my experience, but, that’s a rant for a different day.) The documentation is actually quite good at getting you up and running with the APIs. There’s also some great tutorials in the Graphics and Animation section here from Ray Wenderlich’s site. As a framework, Quartz is the name for the complete 2D drawing engine on iOS and OSX, and it covers everything from drawing to the screen, to working with images and PDFs, to color management, and also includes low-level support for drawing text. It’s resolution and device independent, meaning it’s great for generating interface elements for your iOS apps. No need to manually create multiple versions of each resource – iPhone, iPad, @2x for Retina displays (presumably @2x iPad Retina at some point in the future) – just render the interface at runtime, and as long as you do it right, the OS will handle all the scaling and render everything at the right resolution. It’s also perfect for those times when you need to draw dynamic interfaces that are based on some kind of data or input rather than a static “look” that you design and then display. Although it’s not exactly easy to reverse-engineer the Apple apps and see exactly what they’re doing, it’s safe to say that many of them are rendering directly in app with Core Graphics, rather than loading static images. The WWDC 2011 video, “Practical Drawing for iOS Developers” shows step by step how the Stocks app renders its views, entirely in Quartz. If you’re starting from scratch, the docs, WWDC videos, and tutorials will have you drawing lines, arcs, and basic shapes in no time, all with strokes, fills, and even gradients.

Complex Shapes

The problem I ran into was how to get past just the basics. The API’s for Quartz path drawing go something like this: move to this point, add a line to this point, add a bezier curve to this point with control points at these locations, etc. It’s relatively easy to think about and describe basic geometric shapes in these kind of terms, and Core Graphics even provides convenient methods for creating things like rounded rectangles and ellipses. Even complex views like the stocks app are still very much data/number driven types of views, and even though the drawing process itself is more complicated, it’s not hard to imagine how you would programmatically calculate and describe, say, points on a graph. But, what if you want to draw something a little more organic? What about more complex shapes with lots of curves?
Quarter RestTake this Quarter Rest symbol, for example. As a vector graphic in Illustrator, it contains 3 straight lines and 13 different Bezier curves, each with two control points – and even that is after trying to simplify it as much as possible without losing the desired shape. The problem quickly becomes apparent – it’s virtually impossible to establish a good mental connection between the graphic as conceived by the artist/designer, and the actual code used to produce it on screen. Bret Victor has a great write-up on this artistic disconnect when it comes to dynamic and interactive images/interfaces. It was immediately evident to me that trying to build this graphic in code, line by line – guesstimating and then tweaking the coordinates of the lines, curves and control points – could only end in one way: much swearing and me throwing my computer out the window in frustration.

The main reason I wanted to use Core Graphics rather than static images is to be able to display these musical symbols with dynamic coloring and shadows for some highlight/glow effects. Now, the shadow part of this is actually possible using pre-rendered images. You can set shadow properties like color, radius, distance, on any UIView (technically, on the CALayer of the UIView), including UIImageViews. Quartz will use the alpha values of the pixels to calculate where the edges are, and will generate a nice shadow behind the elements of the image. I say it’s possible, but it’s not actually that practical. Doing it this way requires an extra offscreen rendering pass, and the performance will very likely suffer. In my case, it completely tanked, from somewhere around 53-54 fps with normal content, to around 15 fps when adding a shadow to static images. In some situations, you could work around this by using the shouldRasterize feature of CALayer, but for dynamic content, this could actually make performance even worse. After my experiment, I knew there was no way around it but to keep working on some way to convert my vector images in Illustrator into something I could use in my app. Enter the .svg format.

SVG To the Rescue!

SVG – scalable vector graphics – is a widely used standard for storing, well, just what the name says. Most vector based graphics programs, including Adobe Illustrator, can open SVG, and will also export to SVG. Since SVG is a web standard, one option is to use a UIWebView to render the SVG to the iPhone screen, but that option doesn’t work for me. I googled far and wide for some kind of svg to Quartz converter, and had a bit of luck:

This site was a good start. It provides a resource where you can copy and paste the path data from an svg file, and it will export Quartz source code. I had some weird results from my files, though and a little difficulty figuring out the proper data to paste into the form.

Here’s an Objective-C class, under a Creative Commons Attribution license, which will also take the path data from an svg and output a UIBezier path (iOS) or NSBezier path (OSX).

I also found this library, but as of right now, the site appears to be down. Perhaps just a temporary issue. (UPDATE: Looks like it’s back up, and now that I can see it again, this page is mostly just a link to this on github. A library that takes SVG files and turns them into CAShapeLayers.)

I didn’t test any of these options extensively, but they appear to be good options, especially the second. If they work for you, then great! What they all have in common though is that you first need to extract the path data from the .svg file, meaning, I had to do some research on the standard anyway. Turns out, .svg is just an XML format that you can open in any text editor. And, even better, the svg path commands are very similar to the Core Graphics API’s. Each individual path is contained in a <path> tag, and the specific commands are in the “d” attribute. Here’s the file for that Quarter Rest symbol – open in the browser to see it rendered, or download and open in a text editor and you’ll see the path data clearly separated. The svg standard includes lots of fancy things like fills, strokes, gradients, patterns, masking, even animation, but all I’m using here is a simple, single path. Path commands in svg are single letters, with parameters following.

  • M (x, y) – move to point.
  • C (x1, y1, x2, y2, x, y) – Add cubic bezier curve to point (x, y) with control points (x1, y1 and x2, y2).
  • L (x, y) – add line to point.
  • Z is the command to close the current path.
  • There’s also H, and V for horizontal and vertical lines, and S for curves with an assumed first control point relative to the last command.

Once I got the file into this format, each move was easily converted to Quartz API calls to build a path:

  • CGPathMoveToPoint
  • CGPathAddCurveToPoint (where the point parameters are even in the same order as the SVG command)
  • CGPathAddLineToPoint
  • CGPathCloseSubpath
  • The “H,” “V,” and “S” commands don’t have a Quartz counterpart, so they need to be adapted.

And, here’s the end result of that Quarter Rest symbol, rendered in app with Core Graphics, complete with shadow/glow effect and maintaining nice, snappy frame rates.

Parsing Gotchas

Parsing the svg file by hand turned out to be a little challenging. For one thing, in the interest of keeping file size small, there are almost no separators between items. No whitespace, but also not many commas or other delimiters, wherever it can be omitted. For example, a “move” command, followed by an “add curve” command might look something like this: “M60.482,613.46c0,0-17.859,0.518-26.997,0” Each place there’s a negative number, the separating comma is eliminated as unnecessary, and each command runs right into the next one, so it’s important to know that the parameters for each command come after the letter. Also, when the same command is used multiple times in a row, it’s possible according to the standard to omit the command the second time. So, a “c” followed by 12 numbers is actually two separate curve commands. One other catch: each of these svg commands is using absolute coordinates, but most of them also have a corresponding command using relative coordinates. These use the same single letters, but in lower case. For example, M 10 10 m 5 5  means move to absolute point (10, 10) and then move to (5, 5) relative to this point – so (15, 15) absolute. Unfortunately, Illustrator exports svg files using mostly these relative commands, so I also needed to convert them to absolute point values for Quartz.

You’re Still Reading? Wow!

OK, this was a long post, so if you’ve read this far, that means you’ve got some actual interest in the subject and/or need for an efficient way to get path data into Core Graphics. So here’s the part where you’re hoping I have the link to some parsing code or maybe a script I wrote that will do this work for you. But, I have to confess, I did all mine by hand. I only had a handful of symbols I needed for this project, each of which is a pretty simple, single path, so I did the parsing and converting by hand along with some rounding and cleaning up along the way. Maybe next time I’ll get it automated, but for now, it was a good exercise in exploring a new file format and diving deeper into Core Graphics. But, if you’ve given some of this a try yourself, I’d love to hear what you came up with! Did any of these other resources work well for you? Got any nice scripts to share with everyone else? Or, perhaps even more likely, am I way off track? Is there an even better workflow for getting from design in a visual editor to Quartz source code? If so, I’d be grateful to hear your ideas.

BONUS: of course, just as I’m finishing this post, I stumbled across yet another resource. From the looks of it, it might be the best yet. It’s an Objective-C parser that will take a portion of an Illustrator eps file and convert it to CGPath. Guess I’ll have to try that out now too! Method for Interpreting Illustrator Art Assets as Cocoa CGPathRef

Using CGAffineTransform for Circular Layout and Scrolling


Hello, and thanks for stopping by my blog! This marks my first post as part of iDevBlogADay. If you’ve never heard of it, you should go and check it out. It’s basically a group of indie iOS developers who are committed to blogging on a regular basis about all the experiences of being an indie developer – everything from marketing tips, to code examples, to graphic design, to just about anything else you can think of. If you’ve found my blog through iDevBlogADay, then I just want to say a special thanks for stopping by to see one of the “new guys.” Hopefully you’ll find something here that’s helpful or encouraging, no matter what stage you’re in as an indie developer. Just a quick intro to me: I’m a relative newcomer to the developer scene and have been doing iOS development for just over two full years, with no other substantial programming experience prior to that. Currently I’ve got one app for sale on the app store (plus the Lite version) called theDrumDictionary. If you’re interested in that or more info about me and my background, you can find it on the previous posts in this blog. As of right now, this app and basically all my current ideas for future apps are focused on the area of tools for musicians. So if you have a particular interest in music or music apps, be sure to stop back by – or subscribe to the feed – and I’ll try to keep the blog posts coming with everything from specific music and audio programming things I’ve learned, to more widely applicable topics like interface design and code.

Circular Scrollers

For this post, I’d like to share a bit about the major interface control I’m working on for my upcoming metronome app. The basic idea is a rotary control that allows users to select between different values or options by scrolling around in a circle rather than simply scrolling up and down on a UITableView or UIPickerView.

The basic idea is inspired by the beautiful Convertbot by the Tapbots crew. The circular scroller idea itself goes back even further to the many generations of click wheel iPods prior to the rise of the iPhone and multitouch.

Convertbot Interface

It’s a fairly complicated mechanism, and there’s a lot that I could share about the implementation and why I chose this format, but I think I’ll save that for later posts. For now, how about a quick intro to the world of UIViews, CALayers and transforms that form the basis of my version of this control.

Circles are Freakin’ Hard!

If you’ve done any work on interface design on iOS then you’ve surely made use of the UIKit framework. For basic layout and presentation of views, UIView and its various iterations – UIImageView, UIScrollView, etc. – are pretty simple and straightforward. There’s a whole slew of properties you can access to set sizes and positions of views, as well as background color and alpha, and to top it all off, many properties are animatable. With very little code, you can get some pretty complicated looks and have all kinds of things flying in and out, zipping around, fading in and out, growing and shrinking, whatever you want to do. Combine this with the concept of adding views as subviews of others, and you can do all sorts of interesting layouts and animation with minimal effort. The first sort of problem we run into though is the fact that everything, and I mean everything, in the UIKit system is based around rectangles. CGRects to be exact. Every view has a square frame, is positioned within its superview in relation to the superview’s square shape, is defined in terms of rectangular sizes, etc. If you want to deal with circles – or any shape other than a rectangle for that matter – and handle touches, layout, etc. you’re going to have to take on some extra burden to get things looking and acting the way you want. Core Graphics, of course, offers methods for getting circles drawn onto the screen, or you can use pre made images with transparency, but either way, we’re still talking about a circle sitting inside a square UIView. 

The other major problem you’ll notice is that in all of the available properties for UIView, there is no “rotation.” Well, that’s a problem because this whole concept is based on nothing BUT rotation, and laying out views at various angles around a circle. For rotation, we have to turn to the UIView’s “transform” property. This property is of the type CGAffineTransform and allows us to take the underlying view hierarchy and model and transform it in various ways so that when it comes time to draw to the screen, the view has been altered. Views can be translated, scaled, and rotated. Even if you don’t understand the math behind matrix transforms – and I certainly don’t – you can still make good use of the CGAffineTransform using some Apple-provided functions. For rotation there’s CGAffineTransformRotate, which takes an existing transform as it’s first parameter and then rotates it by the angle (in radians, not degrees) given as the second parameter, adding to whatever translation, scale or rotation was already a part of the transform. Or, there’s CGAffineTransformMakeRotation, which will return a new transformation with only rotation at the given angle. Now that we’ve found the functions we need, for this post, we’ll just focus on getting a rudimentary number dial running. It’s not gonna be pretty, but it’ll get the job done. First thing to do is decide how many numbers we want to show and create the views to display them. I’m just going to use UILabels. So here’s what it looks like after the first step of just adding the main circle image to the view and adding 9 number labels as subviews of the circle in the center of the image. I gave the labels a background color to better see what going on, and an alpha of .2 so you can see that right now, it’s 9 labels all right on top of each other in the center. Now, to get them arranged around the circle, we’ll need to apply the rotation transform. Since we’ve got 9 labels, each label will be rotated 2π/9 radians more than the previous one to fill out the entire circle evenly. UIViews rotate around their centers, so in order to arrange the labels around the edge, we can make sure each label is the same width as the circle, then apply the rotation to get this:

Now, it looks OK, but you can easily tell that it’s not ideal. (Unless of course you’re making a kaleidoscope app!) All of these multiple overlapping views mean extra work for the rendering system, not to mention all the just plain waste of having each view extend all the way across the circle.

Cleaning It Up

How can we clean this up? The answer is to dive just a little bit deeper and access the “layer” property of the labels. Every UIView is backed by a CALayer that’s responsible for the actual drawing. UIView adds support for touch handling and presents a different set of API’s to interact with the drawing and animations, but behind every UIView, by default, is a CALayer. If you’ve got a developer login and can access the 2011 WWDC videos, I highly recommend the one called “Understanding UIKit Rendering.” It has a great chart that details some of the shared properties between UIView and CALayer and how they are accessed in each, as well as some of the differences. One property on CALayer that cannot be accessed from UIView is the anchorPoint. The anchorPoint is a CGPoint that defines the exact spot within the view’s own bounds that acts as its anchor to its superview. Confusing right? Maybe this will help: think of the layer as a sheet of paper that you’re pinning to a bulletin board. The anchorPoint is the spot on the piece of paper where the pin will be pushed through. The position property of CALayer is the spot where the pin will be stuck on the bulletin board. 

By default the anchorPoint is set to the center: (0.5, 0.5) – 50% of the way across in both the x and y directions. The exact relationship between UIView’s frame, bounds, center and CALayer’s  bounds, position, and anchorPoint can be difficult to understand at first, but the most important thing for us right now is to know that setting a CALayer’s anchorPoint means any rotation will be applied around that point, again, just like a piece of paper stuck to a cork board will rotate around the pin. So, first, let’s cut the width of our labels in half and position them at the left edge.  Then, we’ll set the anchorPoint to (1.0, 0.5) – the far right side and centered vertically. Now, when we apply the rotation transformation, the labels line up the exact same way as before, but without all the unnecessary size and extra overlapping.

Take out the red color, and we’ve got a decent start to a number dial. If we want to rotate the whole dial, apply a rotation transform on the whole circle image. Since the labels are subviews of the circle, they will rotate right along with it and also maintain their relative positions because of their own rotations. Aren’t transforms fun!!

Two things to note: 1) CALayer also has a transform property, but it’s separate and of a completely different type than the UIView’s transform property. BUT, since the UIView’s drawing is done in its CALayer, we can modify the layer’s anchorPoint property, and still see the results we’re looking for when we rotate the UIView’s transform. It’s all a bit confusing, but very powerful. 2) If you’re not already doing it, in order to access the CALayer API’s you’ll need to link against the QuartzCore framework and import that header in your file. Alright, I think that’s enough for now. Here’s the code on Pastebin for the final version if you’d like to check it out. Add it to viewDidLoad or similar, and don’t forget to clean up the memory (I was lazy for the example)! Happy transforming!

Head to Part 2, for adding rotation based on touch input.

Here’s a look at this concept “in action” as a tempo selector in my app.

The design is far from finished, but you can at least get an idea of what the control looks like. As this is my first iDevBlogADay attempt, I’d love to hear your feedback about the post: too long, too boring, too simple, did I get something wrong? Let me know what you’d like to read about! Thanks!