The app you built has to be on the App Store (as long as it compiles)

Back in the day when I was getting into cycling, although I didn’t know what to expect, I knew one thing for sure: I had to pick the bike with the right frame. It didn’t take too long until I found myself inside an ocean of parameters because I came to notice that bike frames had many attributes alongside the size. One of them was the angles of where the parts meet each other and depending on these, the bike would give you a different ride experience like a comfortable one, or an aerodynamic one, and such.

I was serious, and I had to pick not just any frame, but the best for my needs. Well, there was a problem: Not every buyer or seller cared about every detail, and I wasn’t able to find all the details of the frames I was looking at, more specifically, the angles within the frame body.

So I came up with an idea: How about I make a small app that’s just for solving the problem at hand: Measuring the angles on a given photo. Did I do that right away? Yes. Did I use it for measuring angles on bike frames? Yes. Did I get the “best” frame for myself? No, but that’s another topic. What followed all of these is that I decided to put that app on the app store. It was awfully primitive, probably had the worst UX ever, and the code behind was… Catastrophic, to say the least. But I wasn’t expecting anything, to be honest. It was a small effort for me to publish and I would be more than happy if it just helped someone, somehow.

The app was being downloaded and used over the years, but I wasn’t getting any feedback, although that was fine. The thing about the internet is that it’s like a sea into which you throw your bottle with a note. You don’t know what will happen to the bottle, or if someone will ever read your note, but most importantly, whether you’ll ever get a response. Because we all fetch other people’s bottles, but we don’t always respond.

Well, after 3 years, I received a bottle. It was from a senior who presented himself as “a blue-collar guy or laborer” who had an injury at work and would never be the way he was. He had to measure the angles of the stairs he fell to see whether they match the industrial staircase requirements. He wanted my help because he thought that he was not educated in this discipline although it was a simple calculation (I told you that the app UX was horrible). He wanted to pay me for my service but I refused since I was more than happy to help, then he asked for a charity that he can donate to instead. I was just a guy who uploaded the app he built for himself, and not only did I help a handicapped senior from the other half of the world, a charity was getting a donation because of me! I was speechless.

If I had taken a perfectionist decision, I wouldn’t have released this app. If I hadn’t spared the small amount of time to put this online, I wouldn’t have released this app. There were so many reasons not to release it, but I did it anyway, and it took only one person to make me appreciate my decision.

I have 3 other apps on the App Store alongside Angles in Photo: One app for cross-multiplication (yes, I made an app for that, and yes, people use it), another one for checking the glycemic index of a food (I was quite obsessed with my nutrition once, we’ve all been there), and another one that I built when Safari was getting very slow on my old iPhone so I decided to build the simplest web browser that doesn’t do 1000 things in the background. Some of them have advertisements to help me pay my bills, but they’re all free to use. People do use them, and people do give feedback, although I never show the care I’m supposed to – but that’s the whole point, and if I was obsessed with that, I wouldn’t have kept them online, and no one would be using them.

You might not always appreciate what you do, but that shouldn’t mean that other people won’t. If they won’t, you won’t lose anything, but if they do, then you realize that something that’s too little for you might mean a lot to someone else.

Oh, I had another feedback for Angles in Photo, saying “Helped me get through my divorce”. I can’t imagine how that happened, but, there you go!

A gentle introduction to async/await in Swift

Ian Walton/Getty Images

Swift was announced at WWDC 2014, and at the end of 2015, it was made open-source under the Apache License 2.0 (with some exceptions). If you have been following along since the beginning, the language had so many changes, especially on the surface (syntax), that after some period of time they almost became a developer joke, like whether the changes were to rename methodX to aMethodX in the next release (credits to good ol’ Xcode who would do the most of the migration automatically).

This is, of course, also due to the nature of the open-source software. The exception with Swift is, in my opinion, that it now became a software language that’s (well, to a certain degree) community-driven, but also has the resources to continue its evolution, having a tech titan behind. It’s hard to argue with the assessment that this is an amazing thing for the community and the software itself.

One of the things that I like about the open-source software development is the transparency. You are able opt-in all the events in the life of a feature even from the very beginning. Which means, if you really want to, you can even be a part of the change yourself. If not, you can just keep monitoring and get excited about it until it’s released, and who knows, maybe you will already be a master of the feature by the time it’s released!

If you are here before async/await is released or announced very publicly (I guess it means to get promoted during WWDC, etc.), then you are probably in the second group I mentioned above. After raising awareness regarding what a great thing open-source software is, we can finally talk about it.

Why?

There’s this proposal that’s made for the feature and I’ll try to summarize it below, leaving some comments. It makes sense to start with the “why” which is explained very well in the “Motivation” section of the proposal, roughly as follows:

Problem 1: Pyramid of doom

The pyramid of doom is a common problem that arises when a program uses many levels of nested indentation to control access to a function.

Wikipedia

Closures. As soon as we learned how to use them, we started building these pyramids ourselves, embedding one closure in another. Apparently, over time it became so disturbing for everyone that it is mentioned as the first reason for this change.

Problem 2: Error handling

Callbacks make error handling difficult and very verbose. (…) The addition of Result to the standard library improved on error handling for Swift APIs. Asynchronous APIs were one of the main motivators for Result. It’s easier to handle errors when using Result, but the closure-nesting problem remains.

Problem 3: Conditional execution is hard and error-prone

If you really wonder what that really means, see here, but basically, the problem is:

This pattern inverts the natural top-down organization of the function: the code that will execute in the second half of the function must appear before the part that executes in the first half.

Even though I agree with the problem, the example that was given in the link doesn’t seem like the perfect fit, I mean, why don’t you just create a new method rather than creating a closure and assign it to a constant? But anyway, this doesn’t change the fact that this problem does exist when you can’t just export the code into a method.

Problem 4: Many mistakes are easy to make

It’s quite easy to bail-out of the asynchronous operation early by simply returning without calling the correct completion-handler block.

It simply means that you have something to do as soon as your closure is about to exit, but if you have lots of conditions inside of your closure and in some of them you exit the closure earlier, it’s easy to forget your last step code before exiting the closure. This happened to me many times, I’m sure it happened to you as well.

Problem 5: Because completion handlers are awkward, too many APIs are defined synchronously

Seriously? That’s just… Sad.

I think everything above is somewhat reasonable, but the ones that I agree with the most are #1 and #4.

Solution in a nutshell

Asynchronous functions—often known as async/await—allow asynchronous code to be written as if it were straight-line, synchronous code.

So, for example, this:

func printDelayedVar() {
    self.getMyDelayedVar { (delayedVar) in
        print(delayedVar)
    }
}
​
func getMyDelayedVar(completion: (Int) -> Void) {
    DispatchQueue.main.async {
        sleep(3)
        completion(5)
    }
}

Becomes this:

@asnycHandler func printDelayedVar() {
    let delayedVar = await self.getMyDelayedVar()
    print(delayedVar)
}
​
func getMyDelayedVar() async -> Int {
    // Code to be revealed in the rest of the article
}

No reason to worry because of your pyramids getting lost. We still neste things within one another inside of the async methods, but at least we call our async method like a synchronous method in printDelayedVar. I guess the pyramids are just getting… Smaller?

Before moving further, I want to make a disclaimer that the part that I’m covering in this post is simply the tip of the iceberg. In the announcement post of the approval of this proposal, the review manager says:

This is an important first step on our concurrency journey. To help navigate how this proposal relates to expected future proposals, this diagram should be of help:

Swift Concurrency Dependencies
Swift Concurrency Dependencies

As you can see, concurrency in Swift is in fact just getting warmed up. If you want to learn more about this feature, see the References section at the end of the page.

async/await hands on

Before experimenting with this syntax, there are a couple of things we need to do:

1. Download and install the latest* development snapshot from swift.org.

Go to https://swift.org/download/#snapshots and from the section ‘Trunk Development (main)’, download and install the one that’s for Xcode.

* Some things might have changed until the time you read this post, so try this alternative snapshot if things work out differently for you after you install.

2. Configure Xcode to use the respective toolchain

Open Xcode and from the Xcode menu, select Toolchains -> Swift Development Snapshot YYYY-mm-dd. You can do the same through Preferences -> Components -> Toolchains.

3. Add flags to enable experimental feature

From your Project’s build settings, find Swift Compiler - Custom Flags section and add the following flags to Other Swift Flags section: -Xfrontend -enable-experimental-concurrency.

4. Import experimental concurrency module

Add import _Concurrency to the header of the file that you are going to use for experimenting the feature. Note the underscore (_) in the beginning of the name of the module which indicates that it’s yet under development.

Done! You can now use async/await in your code. Xcode won’t highlight them yet but it will nicely compile and won’t block your way.

How to use async/await

By the time this feature is released, it’s quite likely that Apple will have converted some (hopefully many) asynchronous methods to async, but right now, we need to build our own async method. To do that, we will use a helper that comes with the _Concurrency module, that is, withUnsafeContinuation. We’ll come to that in a second.

The “sad” code (what we already do)

Assuming what you see below is the code you want to rewrite using async/await because you are unhappy with it (because of the problems we mentioned above):

class SendSelectedPhotoWithEmailViewController: UIViewController {
    func startFlow() {
        // Get access to user's photo library, when the access is granted, display photo picker.
        // When the user picks a photo, first upload it to the server, then send the uploaded file URL
        // via email. Finally, show the user the result of the process.
        PhotosAPI.grantPhotosAccess { didGrantAccess in
            if didGrantAccess {
                PhotosAPI.selectPhoto { selectedPhoto in
                    NetworkAPI.upload(image: selectedPhoto) { uploadedFileUrl in
                        NetworkAPI.sendUrlWithEmail(urlString: uploadedFileUrl) { [weak self] didSend in
                            self?.displayResultAlert(didSendEmail: didSend)
                        }
                    }
                }
            }
        }
    }
}

We will not convert every method above since the logic is almost the same. We will just convert one for demonstration and refactor the other lines as if the corresponding methods were also converted.

Let’s pick NetworkAPI.upload(image:completion:) method. If we were mocking the API and faking the network delay using sleep, the method would be something like this:

static func upload(image: UIImage, completion: @escaping (String) -> Void) {
    DispatchQueue.main.async {
        sleep(1) // Fake wait
        completion("fake URL")
    }
}
  • Problem 1: Our method deals with asynchronous code so it cannot return anything. That’s why it takes a closure where it passes the result.
  • Problem 2: When we use the trailing closure syntax in the place we call this method and embed such methods within each other, things get out of control.

The “happy” code (async/await)

Here, let’s create a method step by step, keeping the problem duo above in mind, and hopefully fix them.

We start with the method signature. If we want to get rid of the closure, we need our method to return the value that we pass into the closure. Something like:

static func upload(image: UIImage) -> String

Now, when we create the method body, the compiler will say “Missing return in a function expected to return 'String'“.

This is fine. That’s what we’re aiming to fix with async/await. But how?

withUnsafeContinuation

We can think of withUnsafeContinuation as a wrapper that you use around your asynchronous code which blocks the thread until you explicitly resume. If you write tests for your asynchronous code, you should be familiar with this pattern from using XCTestExpectation and its fulfill method.

static func upload(image: UIImage) -> String {
    withUnsafeContinuation { continuation in // Compiler error 1: "'async' in a function that does not support concurrency"
        DispatchQueue.main.async {
            sleep(1) // Fake wait
            completion("fake URL") // Compiler error 2: "Cannot find 'completion' in scope"
        }
    }
}

So the compiler is not yet content. The second error is something we are familar with, but the first one is new: “'async' in a function that does not support concurrency“.

My developer instincts tell me to mark this function somehow to tell the compiler that it supports concurrency. Maybe make it more explicit that my function is… async.

So changing from method signature from

static func upload(image: UIImage) -> String

to

static func upload(image: UIImage) async -> String

actually works! Why did I put async there and not somewhere else in the signature? Well, maybe I tried different places until it doesn’t produce an error, who knows!

For the second error, “Cannot find 'completion' in scope“, I’m just going to go ahead and remove that line. Sometimes you just need to ignore your problems until they’re gone, right?

We have a new compiler error, “Call is 'async' but is not marked with 'await'” but it’s so easy to fix that even Xcode itself offers a solution. We just mark our call with await.

Here’s how our method looks now:

static func upload(image: UIImage) async -> String {
    await withUnsafeContinuation { continuation in
        DispatchQueue.main.async {
            sleep(1) // Fake wait
        }
    }
}

We just wrote a couple of lines and barely did what we wanted to, but our code compiles… Some things are missing, right? Like a puzzle. Let’s go one by one:

  1. Our method signature returns a String, but the method body doesn’t return anything yet it still compiles.

The answer is Swift 5.1, or more specifically, “Implicit returns from single-expression functions”. So our method actually does return something, and that is the result of the withUnsafeContinuation method. But maybe it’s a good idea to make return explicit to avoid confusion.

  1. In the original method, we would return a string using the completion block, here we just erased it and didn’t put anything else instead.

Fair point. But we can’t just return something in the body of DispatchQueue.main.async (“Unexpected non-void return value in void function“), so there must be a different way of doing that. Maybe calling a method?

  1. withUnsafeContinuation passes a value of type UnsafeContinuation into its closure but we never use it. What is it for?

There’s only one way to figure it out: To play with it. When we try to use it, we see that it has only one method available, which is continuation.resume(returning:). Could it be the method we were looking for in the previous problem?

Now we can finalize our method using continuation.resume(returning:). The complete version looks like this:

static func upload(image: UIImage) async -> String {
    return await withUnsafeContinuation { continuation in
        DispatchQueue.main.async {
            sleep(1) // Fake wait
            continuation.resume(returning: "fake URL")
        }
    }
}

Time to get a pulse-check. In the “sad” code above, we mentioned two problems so let’s refresh our memories and note down our progress:

  • Problem 1: Our method deals with asynchronous code so it cannot return anything. That’s why it takes a closure where it passes the result.

This is now fixed as the method returns a String in the signature and the method body is updated accordingly.

  • Problem 2: When we use the trailing closure syntax in the place we call this method and embed such methods within each other, things get out of control.

This is not yet fixed because we didn’t refactor the part we call this method, but it doesn’t take a closure anymore so we made good progress there.

It’s time to use our new method, so let’s scrap everything in startFlow() and just call this new method:

func startFlow() {
    let url = NetworkAPI.upload(image: UIImage(named: "an-image")!) // Compiler error: "'async' in a function that does not support concurrency"
}

Well, we are familiar with the compiler error but something different happens when we use Xcode suggestion to correct this: The method gets marked with @asyncHandler. Okay, our method is literally an async handler so the signature feels right, let’s leave it as it is. And the new error “Call is 'async' but is not marked with 'await'” is also easy to fix, we just mark our call with await and we have the following:

@asyncHandler func startFlow() {
    let url = await NetworkAPI.upload(image: UIImage(named: "an-image")!)
}

Everything seems to work. So, if we were to use the same syntax for our other methods, the final state of startFlow() would be something like this:

@asyncHandler func startFlow() {
    guard await PhotosAPI.grantPhotosAccess() else { return }
    let selectedPhoto = await PhotosAPI.selectPhoto()
    let uploadedFileUrl = await NetworkAPI.upload(image: selectedPhoto)
    let didSendUrlWithEmail = await NetworkAPI.sendUrlWithEmail(urlString: uploadedFileUrl)
    self.displayResultAlert(didSendEmail: didSendUrlWithEmail)
}

What do you think? Much cleaner, right? There’s one last thing we didn’t talk about, that is @asyncHandler.

@asyncHandler

We can think of @asyncHandler like a stamp you use in the method signature to tell the compiler that your method does not return anything but just handles other async functions. When you mark your method with @asyncHandler, you can use it in other methods without having to mark them with @asyncHandler or async. Consider @asyncHandler as the last wrapper in your async code because eventually, you need to call these methods from a method that you can’t touch the signature, for instance, from UIViewController overrides.

Final words

As a final recap, let’s see the code before async/await:

Here’s the code with async/await:

As you can see, the new code is almost no different than a synchronous code block but the code is more readable and more manageable compared to the one with closures, thanks to async/await. I hope this post helped you get familiar with how async/await works and you are as excited about the future of concurrency in Swift as I am. Feel free to leave a comment on this post or send me a tweet on Twitter.

Oh, and for the full code, check out my gist on Github.

References

Aligning SKPhysicsBody Correctly with SKShapeNode

When you want to create a circle in SpriteKit, SKShapeNode is the quickest and the simplest way for it. You don’t need to create images, you can manage the size, fill colour, stroke colours etc.

However, if you want this node to involve with collisions, you may get some trouble when creating an SKPhysicsBody for that node. The creating process is similar to SKSpriteNode but the alignment of it is different.

By default, SKShapeNode anchor points begin from (0, 0) and there isn’t any property to set it as we want. When we assign a SKPhysicsBody to this node, body’s anchor is its center point so the body doesn’t cover the node correctly.

Here’s how it looks when you want to implement for SKShapeNode as you do in SKSpriteNode:

skshapenode-skphysicsbody

There are plenty of people who were unable to solve this issue. Yet there is one answer on SO that helped me out with this.

To work around this situation, you can create an SKSpriteNode to implement the body and an SKShapeNode as the SKSpriteNode’s child to draw the shape.

First, create an SKSpriteNode and set the width and height same with the diameter of the circle

float radius = 30.0;
SKSpriteNode *aCircle = [SKSpriteNode spriteNodeWithColor:[UIColor clearColor] size:CGSizeMake(radius * 2, radius * 2)];

Then create a circular SKPhysicsBody for the SKSpriteNode (thankfully, this is possible)

SKPhysicsBody *circleBody = [SKPhysicsBody bodyWithCircleOfRadius:radius];
[circleBody setDynamic:NO];
[circleBody setUsesPreciseCollisionDetection:YES];
[aCircle circleBody];

Here is the key part. Create a CGPathRef as an ellipse in the rect with correct center values.

CGPathRef bodyPath = CGPathCreateWithEllipseInRect(CGRectMake(-[aCircle size].width / 2, -[aCircle size].height / 2, [aCircle size].width, [aCircle size].width), nil);
SKShapeNode *circleShape = [SKShapeNode node];
[circleShape setFillColor:[UIColor redColor]];
[circleShape setLineWidth:0];
[circleShape setPath:bodyPath];
[aCircle addChild:circleShape];
CGPathRelease(bodyPath);

Don’t forget to add the child to the scene then you are done. As you can see below, the physics body now matches the node frame correctly.

skspritenode-skshapenode-skphysicsbody.png

Source link of the answer:
SKPhysicsBody not as expected

Other questions about similar issues:
How to align SKPhysicsBody and SKShapeNode?
Align SKPhysicsBody with SKShapeNode
SKPhysicsBody does not work on SKShapeNode
SKshapenode is not responding to Physicsbody
how to make collisions with skshapenode circles
Keeping an SKShapeNode within the bounds of an SKSpriteNode

Vi Cheatsheet

a -> Append cursor (After position)
i -> Insert cursor (At position)
esc -> Remove cursor if active
:wq -> Save and quit
:q -> Ask to save and quit
:q! -> Quit without saving
dd -> Cut the line
yy -> Copy the line
p -> Paste the line
:n -> Go to line n
/text -> Search for ‘text’
n -> Jump to next match when search is active
0 -> Go to the beginning of the line
$ -> Go to the end of the line
G -> Go to the end of the document
yn + arrow down -> Copy the current line with next n lines
yn + arrow up -> Copy the current line with previous n lines

Gamification: http://vim-adventures.com (Even though it’s for vi not vim there shouldn’t be any major differences as mentioned here.)

Sample Apple Push Notification PHP Script

This is an old script that I used to use for sending notifications. I don’t remember the source, on the other hand, it has been modified a couple of times already.

Even though I could manage to send notifications with this script, the Apple server was rejecting the connection after the amount reaches more than 50. It was usually getting cut off around 70. So it needs to get some management for not sending in a loop, like threading or whatever.

<?php
 
// set time limit to zero in order to avoid timeout
set_time_limit(0);
 
// charset header for output
header('content-type: text/html; charset: utf-8');
 
// this is the pass phrase you defined when creating the key
$passphrase = 'my_secret_pass';
 
// you can post a variable to this string or edit the message here
if (!isset($_POST['msg'])) {
$_POST['msg'] = "Notification message here!";
}
 
// tr_to_utf function needed to fix the Turkish characters
$message = tr_to_utf($_POST['msg']);
 
// load your device ids to an array
$deviceIds = array(
'lh142lk3h1o2141p2y412d3yp1234y1p4y1d3j4u12p43131p4y1d3j4u12p4313',
'y1p4y1d3j4u12p43131p4y1d3j4u12p4313lh142lk3h1o2141p2y412d3yp1234'
);
 
// this is where you can customize your notification
$payload = '{"aps":{"alert":"' . $message . '","sound":"default"}}';
 
$result = 'Start' . '<br />';
 
////////////////////////////////////////////////////////////////////////////////
// start to create connection
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'MyAppGenerated.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
 
echo count($deviceIds) . ' devices will receive notifications.<br />';
 
foreach ($deviceIds as $item) {
    // wait for some time
    sleep(1);
     
    // Open a connection to the APNS server
    $fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT, $ctx);
 
    if (!$fp) {
        exit("Failed to connect: $err $errstr" . '<br />');
    } else {
        echo 'Apple service is online. ' . '<br />';
    }
 
    // Build the binary notification
    $msg = chr(0) . pack('n', 32) . pack('H*', $item) . pack('n', strlen($payload)) . $payload;
     
    // Send it to the server
    $result = fwrite($fp, $msg, strlen($msg));
     
    if (!$result) {
        echo 'Undelivered message count: ' . $item . '<br />';
    } else {
        echo 'Delivered message count: ' . $item . '<br />';
    }
 
    if ($fp) {
        fclose($fp);
        echo 'The connection has been closed by the client' . '<br />';
    }
}
 
echo count($deviceIds) . ' devices have received notifications.<br />';
 
// function for fixing Turkish characters
function tr_to_utf($text) {
    $text = trim($text);
    $search = array('Ü', 'Þ', 'Ð', 'Ç', 'Ý', 'Ö', 'ü', 'þ', 'ð', 'ç', 'ý', 'ö');
    $replace = array('Ãœ', 'Åž', '&#286;ž', 'Ç', 'Ä°', 'Ö', 'ü', 'ÅŸ', 'ÄŸ', 'ç', 'ı', 'ö');
    $new_text = str_replace($search, $replace, $text);
    return $new_text;
}
 
// set time limit back to a normal value
set_time_limit(30);