Published in


Modifying and Improving EmojiSaver

In this post, I take an Emoji Screensaver for macOS and modify it to do even more cool stuff.


This post is imported from my old blog.

Please note I cannot give the source code or compiled product for this as this is a modification of code given by a paid subscription to Guilherme Rambo’s Patreon. However, feel free to support him yourself and add my modifications to his code! Send me a message on Twitter or Discord for help on this (not all the required code is in this post).


A few days ago, I subscribed to Guilherme Rambo on Patreon. Rambo is a popular iOS and Mac developer who recently discovered unreleased iOS and iPhone photos, info, and more, and leaked a lot of the Apple’s September Event beforehand. Apart from leaking Apple’s stuff, Rambo also makes apps and hacks for Mac and iOS. As a perk for donating to Rambo, I got access to some of his projects. One of them includes EmojiSaver. It’s a screensaver he made for mac with random Emoji popping up and pulsing (zooming in and out).

After testing out the screen saver and watching his coding session (where he made the saver) to understand how it was built, I went and chose to try modify a few things:

  1. Make emoji rotate slowly
  2. Make emoji move around randomly
  3. Change the first emoji that is generated

I’ll now go through each of these 3 tasks and detail how I made them, with code examples.

Task 1

Making emoji rotate slowly

As I had never really written any Objective-C code before, this was a blunt introduction to it.

I started out by going into the code, where I found how Rambo made Emoji rotate:

SKAction *zoomIn = [SKAction scaleBy:kEmojiMaxScale duration:3];
SKAction *zoomOut = [SKAction scaleBy:kEmojiMinScale duration:3];
SKAction *pulse = [SKAction repeatActionForever:[SKAction sequence:@[zoomIn, zoomOut]]];
[label runAction:pulse];

Just by looking through the code, we can quickly see the basics of this:

  1. Create an action (zoomIn) that scales the Emoji up to the max scale in 3 seconds
  2. Create an action (zoomOut) that scales the Emoji down to the min scale in 3 seconds
  3. Create an action (pulse) that repeats the sequence of zoomIn zoomOut
  4. Run the pulse action

Taking this code, I used Xcode’s autocomplete to test out some other action types, where I found the following 3 types for a search of “rotate”:

Xcode Autocomplete for ‘rotate’

Looking at these, it seems like rotateByAngle should work — and this is correct. However, it’s not that easy.

In my initial code, I used:

SKAction *rotateBy = [SKAction rotateByAngle:1 duration:1];
SKAction *rotateForever = [SKAction repeatActionForever:[SKAction sequence:@[rotateBy]]];
[label runAction:rotateForever];

However, this had multiple problems. First, it didn’t run. It turns out

[SKAction sequence:@[rotateBy]]

requires more than one item — replacing it with just rotateBy fixed it. Second, it was way too quick, so I changed the duration to 4 (seconds). Third, the angle was too…. fixed. I wanted something more random, so I used

SSRandomFloatBetween(-1, 1)

Finally, this is the working code I settled on for this task:

SKAction *rotateBy = [SKAction rotateByAngle:SSRandomFloatBetween(-1, 1) duration:4];
SKAction *rotateForever = [SKAction repeatActionForever:rotateBy];
[label runAction:rotateForever];

Task 2

Making emoji move around randomly

After doing task 1, this wasn’t too hard. However, it wasn’t too easy, either.

I started off, again, with Rambo’s pulse code:

SKAction *zoomIn = [SKAction scaleBy:kEmojiMaxScale duration:3];
SKAction *zoomOut = [SKAction scaleBy:kEmojiMinScale duration:3];
SKAction *pulse = [SKAction repeatActionForever:[SKAction sequence:@[zoomIn, zoomOut]]];
[label runAction:pulse];

I won’t repeat the explanation of that code, but I tried what I did in task 1 again — using Auto Complete to suggest other actions.

These are the suggestions I got this time around:

Xcode Autocomplete for ‘move’

As you can see, it seems incredibly obvious!

I immediately picked suggestion 1, so my code looked a bit like this:

SKAction *moveBy = [SKAction moveBy:1 duration:1];
SKAction *moveForever = [SKAction repeatActionForever:moveBy];
[label runAction:moveForever];

Unfortunately, this triggered an error: value 1 (for moveBy) was not a “CGVector”.

Not knowing anything about CGVector or what it was, I simply went on Google and searched something like this:

objective c spritekit move element to point

Eventually, after going through lots of options, I chose to try one of the smart ways I saw to implement this:

SKAction *moveBy = [SKAction moveByX:100 y:100 duration:1];

This worked! However, there was one last problem: All emoji just moved in thesame direction! I used my code from Task 1 to select

SSRandomFloatBetween(-100, 100)

for the task, giving me the final code of:

SKAction *moveBy = [SKAction moveByX:SSRandomFloatBetween(-100, 100) y:SSRandomFloatBetween(-100, 100) duration:1];
SKAction *moveForever = [SKAction repeatActionForever:moveBy];
[label runAction:moveForever];

This worked perfectly, so I moved on to task 3.

Task 3

Change the first emoji generated

This last task was the easiest out of the 3.

Basically, I copied the random emoji spawner and changed

label.text = emoji.glyph;


label.text = @"CUSTOM_FIRST_EMOJI_HERE";

Then, I just made the initial call of the random emoji spawner call this one instead

([self spawnFirstEmoji];) 

and kept the timer (which makes emoji spawn every second) calling the real random spawner.


After all this, I now had a very good looking and smart screensaver.

I hope this blog post was interesting and made you understand a few things about what I did, as well as give some kind of an introduction to Objective C.

I’d like to give full credit to Guilherme Rambo for the initial idea and code. I also highly recommend anyone who found this post interesting to subscribe to him on Patreon.

Thanks for reading.




technology alone is not enough

Recommended from Medium

First Post — Welcome to my Blog

12 Best Data Science and Machine Learning Books and Courses to learn with Python and R in 2022

12 Best Data Science and Machine Learning Books and Courses

How I made an MVP in excel and validated the use case.

Kubernetes Story — Linux namespaces and cgroups: What are containers made from?

It’s turtles all the way down for OpenStack

Know the benefits of cloud-native networking for SASE

Magento 2 Open Source Community Fork vs Adobe Commerce Cloud

From Monolith to Kubernetes Architecture — Part IV — GKE / GCP

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store


More from Medium

How to display permission to track in iOS 14.5 and above in Objective-C?

ITMS-90165 error

ITMS-90165 error

Dependency Management in iOS

Nimo: A Small But Important Step Toward Something More

A man in a white t-shirt wears thick black glasses with silver accents and a few small buttons.