From 88e40e15c72be2ebc5914174bfc01635c4e13aed Mon Sep 17 00:00:00 2001
From: Tibor Bodecs Learn how to build a controller component that can serve models as JSON objects through a RESTful API written in Swift. We should start by implementing the non-generic version of our code, so after we see the pattern we can turn it into a more generalized Swift code. If you start with the API template project there is a pretty good example for almost everything using a Todo model. NOTE: Start a new project using the toolbox, just run Open the project by double clicking the A controller is a collection of request handler functions around a specific model. HTTP is a text transfer protocol that is widely used around the web. In the beginning it was only used to transfer HTML files, but nowadays you can use it to request almost anything. It’s mostly a stateless protocol, this means you request something, you get back a response and that’s it. It’s like ordering a pizza from a place through phone. You need a number to call (URL), you pick up the phone, dial the place, the phone company initializes the connection between (you & the pizza place) the two participants (the network layer does the same thing when you request an URL from a server). The phone on the other side starts ringing. 📱 Someone picks up the phone. You both introduce yourselves, also exchange some basic info such as the delivery address (server checks HTTP headers & discovers what needs to be delivered to where). You tell the place what kind of pizza you’d like to have & you wait for it. The place cooks the pizza (the server gathers the necessary data for the response) & the pizza boy arrives with your order (the server sends back the actual response). 🍕 Everything happens asynchronously, the place (server) can fulfill multiple requests. If there is only one person who is taking orders & cooking pizzas, sometimes the cooking process will be blocked by answering the phone. Anyways, using non-blocking i/o is important, that’s why Vapor uses Futures & Promises from SwiftNIO under the hood. In our case the request is a URL with some extra headers (key, value pairs) and a request body object (encoded data). The response is usually made of a HTTP status code, optional headers and response body. If we are talking about a RESTful API, the encoding of the body is usually JSON. All right then, now you know the basics it’s time to look at some Swift code. Defining a data structure in Swift is pretty easy, you just have to create a struct or a class. You can also convert them back and forth to JSON using the built-in Codable protocol. Vapor has an extension around this called Content. If you conform the the protocol (no need to implement any new functions, the object just needs to be Codable) the system can decode these objects from requests and encode them as responses. Models on the other hand represent rows from your database. The Fluent ORM layer can take care of the low level abstractions, so you don’t have to mess around with SQL queries. This is a great thing to have, read my other article if you like to know more about Fluent. 💾 The problem starts when you have a model and it has different fields than the content. Imagine if this Todo model was a User model with a secret password field? Would you like to expose that to the public when you encode it as a response? Nope, I don’t think so. 🙉 I believe that in most of the Cases the Model and the Content should be separated. Taking this one step further, the content of the request (input) and the content of the response (output) is sometimes different. I’ll stop it now, let’s change our Todo model according to this. We should start by implementing the non-generic version of our code, so after we see the pattern we can turn it into a more generalized Swift code. If you start with the API template project there is a pretty good example for almost everything using a Todo model. NOTE: Start a new project using the toolbox, just run Open the project by double clicking the A controller is a collection of request handler functions around a specific model. HTTP is a text transfer protocol that is widely used around the web. In the beginning it was only used to transfer HTML files, but nowadays you can use it to request almost anything. It’s mostly a stateless protocol, this means you request something, you get back a response and that’s it. It’s like ordering a pizza from a place through phone. You need a number to call (URL), you pick up the phone, dial the place, the phone company initializes the connection between (you & the pizza place) the two participants (the network layer does the same thing when you request an URL from a server). The phone on the other side starts ringing. 📱 Someone picks up the phone. You both introduce yourselves, also exchange some basic info such as the delivery address (server checks HTTP headers & discovers what needs to be delivered to where). You tell the place what kind of pizza you’d like to have & you wait for it. The place cooks the pizza (the server gathers the necessary data for the response) & the pizza boy arrives with your order (the server sends back the actual response). 🍕 Everything happens asynchronously, the place (server) can fulfill multiple requests. If there is only one person who is taking orders & cooking pizzas, sometimes the cooking process will be blocked by answering the phone. Anyways, using non-blocking i/o is important, that’s why Vapor uses Futures & Promises from SwiftNIO under the hood. In our case the request is a URL with some extra headers (key, value pairs) and a request body object (encoded data). The response is usually made of a HTTP status code, optional headers and response body. If we are talking about a RESTful API, the encoding of the body is usually JSON. All right then, now you know the basics it’s time to look at some Swift code. Defining a data structure in Swift is pretty easy, you just have to create a struct or a class. You can also convert them back and forth to JSON using the built-in Codable protocol. Vapor has an extension around this called Content. If you conform the the protocol (no need to implement any new functions, the object just needs to be Codable) the system can decode these objects from requests and encode them as responses. Models on the other hand represent rows from your database. The Fluent ORM layer can take care of the low level abstractions, so you don’t have to mess around with SQL queries. This is a great thing to have, read my other article if you like to know more about Fluent. 💾 The problem starts when you have a model and it has different fields than the content. Imagine if this Todo model was a User model with a secret password field? Would you like to expose that to the public when you encode it as a response? Nope, I don’t think so. 🙉 I believe that in most of the Cases the Model and the Content should be separated. Taking this one step further, the content of the request (input) and the content of the response (output) is sometimes different. I’ll stop it now, let’s change our Todo model according to this. We expect to have a title when we insert a record (we can generate the id), but when we’re returning Todos we can expose the id property as well. Now back to the controller. WARN: Don’t forget to run Fluent migrations first: The flow is pretty simple. Decode the Input type from the content of the request (it’s created from the HTTP body) and use it to construct a new Todo class. Next save the newly created item to the database using Fluent. Finally after the save operation is done (it returns nothing by default), map the future into a proper Output, so Vapor can encode this to JSON format. We expect to have a title when we insert a record (we can generate the id), but when we’re returning Todos we can expose the id property as well. Now back to the controller. WARN: Don’t forget to run Fluent migrations first: The flow is pretty simple. Decode the Input type from the content of the request (it’s created from the HTTP body) and use it to construct a new Todo class. Next save the newly created item to the database using Fluent. Finally after the save operation is done (it returns nothing by default), map the future into a proper Output, so Vapor can encode this to JSON format. NOTE: If the input is the same as the output, you just need one ( This is what’s left off the controller (not much, haha): NOTE: If the input is the same as the output, you just need one ( This is what’s left off the controller (not much, haha): The router object also shortened a bit: Get started with server-side Swift using the Vapor 4 framework. Learn how to build a really simple HTTP/2 backend server. In short, it’s the second major version of Hypertext Transfer Protocol (HTTP), but obviously you’re not here for the short version. HTTP/2 is a huge upgrade, it was derived from the experimental SPDY protocol, nowadays it’s widely used by about 40% of all the websites. Yes it’s time to upgrade your infrastructure (soon). 😉 The HTTP protocol is basically a client-server (request-response) communication protocol where the client asks for a resource and the server returns a response (a HTML document, a stylesheet, a JavaScript file, or anything else…). This all happens on top of a TCP/IP connection layer using sockets. If you don’t know anything about TCP/IP ports and sockets, you should read the linked article. NOTE: HTTP2 is secure by default, so it only works via TLS/SSL, but for the sake of simplicity I’m not going into the details of HTTPS, cryptography or secure connection. HTTP is an application layer protocol, that describes how you can interact with various resources identified by an URL/URI (or URN). HTTP is simple (a few methods like GET, POST), yet extensible (via headers), stateless, but not sessionless (just think about Cookies) and it’s definitely dominating the world wide web (browsers). 🌎 HTTP version 1.1 has some disadvantages. It is a text based unencrypted protocol, plus as websites evolved and more and more resources were needed in order to render a webpage, HTTP/1.1 started to face some speed issues, because you are only allowed to download only one resource at a time on a HTTP/1.1 connection. You have to wait for it… The best (and most advanced feature) of HTTP/2 is request multiplexing. It allows you to download multiple files asynchronously from the server. This enables browsers and other applications to think about loading resources in a nice promie-like way instead of the old-fashioned blocking connection. You can send all your requests on the same connection and they can be fulfilled in parallel. 🚀 First of all HTTP/2 server push is not a push notification system for applications. You can use it to send additional cache-able resources to the client that is not requested, but it’s highly anticipated in future requests. Real quick example: if the client requests for an index.html file, you can push back the corresponding sytle.css and main.js files in the response, so they’ll be there by the time the client actually needs them. I could continue with the benefits of the HTTP/2 but I believe the most important factor here is speed. HTTP/2 has a lighter network footprint and also eliminates some security concerns which is great for everyone. You can read more about the protocol on other sites, but for now let’s just stop right here. Let’s start creating our HTTP/2 server in Swift using Vapor 4! 🤓 Apple’s cross-platform asynchronous event-driven network application framework supports HTTP/2 for a while. Vapor uses SwiftNIO since version 3, but only the 4th major version will have the brand new protocol support. Anyway it was a very long road, but we’re finally getting there and I’m really glad that this is happening now. Both Swift, SwiftNIO and Vapor matured a lot in the past few years, if you’d like to spend more time on the server-side now it’s the best time to start learning these technologies and frameworks. Vapor 4 is going to be amazing, and I hope that server-side Swift apps will dominate the market in a few years. #swifttotalworlddomination Backend language “hype” evolution: PHP -> node.js -> Swift? As usual, let’s start by creating a brand new project using the Vapor toolbox: In short, it’s the second major version of Hypertext Transfer Protocol (HTTP), but obviously you’re not here for the short version. HTTP/2 is a huge upgrade, it was derived from the experimental SPDY protocol, nowadays it’s widely used by about 40% of all the websites. Yes it’s time to upgrade your infrastructure (soon). 😉 The HTTP protocol is basically a client-server (request-response) communication protocol where the client asks for a resource and the server returns a response (a HTML document, a stylesheet, a JavaScript file, or anything else…). This all happens on top of a TCP/IP connection layer using sockets. If you don’t know anything about TCP/IP ports and sockets, you should read the linked article. NOTE: HTTP2 is secure by default, so it only works via TLS/SSL, but for the sake of simplicity I’m not going into the details of HTTPS, cryptography or secure connection. HTTP is an application layer protocol, that describes how you can interact with various resources identified by an URL/URI (or URN). HTTP is simple (a few methods like GET, POST), yet extensible (via headers), stateless, but not sessionless (just think about Cookies) and it’s definitely dominating the world wide web (browsers). 🌎 HTTP version 1.1 has some disadvantages. It is a text based unencrypted protocol, plus as websites evolved and more and more resources were needed in order to render a webpage, HTTP/1.1 started to face some speed issues, because you are only allowed to download only one resource at a time on a HTTP/1.1 connection. You have to wait for it… The best (and most advanced feature) of HTTP/2 is request multiplexing. It allows you to download multiple files asynchronously from the server. This enables browsers and other applications to think about loading resources in a nice promie-like way instead of the old-fashioned blocking connection. You can send all your requests on the same connection and they can be fulfilled in parallel. 🚀 First of all HTTP/2 server push is not a push notification system for applications. You can use it to send additional cache-able resources to the client that is not requested, but it’s highly anticipated in future requests. Real quick example: if the client requests for an index.html file, you can push back the corresponding sytle.css and main.js files in the response, so they’ll be there by the time the client actually needs them. I could continue with the benefits of the HTTP/2 but I believe the most important factor here is speed. HTTP/2 has a lighter network footprint and also eliminates some security concerns which is great for everyone. You can read more about the protocol on other sites, but for now let’s just stop right here. Let’s start creating our HTTP/2 server in Swift using Vapor 4! 🤓 Apple’s cross-platform asynchronous event-driven network application framework supports HTTP/2 for a while. Vapor uses SwiftNIO since version 3, but only the 4th major version will have the brand new protocol support. Anyway it was a very long road, but we’re finally getting there and I’m really glad that this is happening now. Both Swift, SwiftNIO and Vapor matured a lot in the past few years, if you’d like to spend more time on the server-side now it’s the best time to start learning these technologies and frameworks. Vapor 4 is going to be amazing, and I hope that server-side Swift apps will dominate the market in a few years. #swifttotalworlddomination Backend language “hype” evolution: PHP -> node.js -> Swift? As usual, let’s start by creating a brand new project using the Vapor toolbox: This will give you a starter Xcode project template, based on the latest Vapor 4 branch. If you are completely new to Vapor, you should read my beginners tutorial about Vapor to get a basic understanding of the main components of the framework. If you have an issue with Vapor, you should join the official Discord server, you’ll find some surprisingly good stuff and a really helpful community there. 😊 Also because HTTP/2 is a secure protocol by default, you’ll need your own SSL certificate. You can generate a self-signed Learn how to implement Asynchronous JavaScript and XML (AJAX) calls using Leaf templates and Vapor 4 as a server. Asynchronous JavaScript and XML (AJAX) is a technology that allows us you to send HTTP requests to your web server from a web page. Based on the response you can use JavaScript to manipulate the HTML Document Object Model (DOM). In short, with the help of AJAX, you can ask for some data, then you can update the contents of the web site based on that. The good thing about AJAX is that you don’t have to reload the entire page, but you can update just a portion of the site. The HTTP request will work on the background so from a user perspective the whole browsing experience will seem faster, than a full page load. ⌛️ AJAX is a frontend technology. It’s a simple JavaScript function call, but some smart people gave it a fancy name. The X in the name comes from the early days of the web, when servers usually returned a “pre-rendered” partial HTML string that you could inject into the DOM without further data manipulation. Nowadays computers are so powerful that most of the servers can return JSON data and then the client can build the necessary HTML structure before the insertion. In order to support AJAX calls on the server side we only have to implement the endpoint that the frontend can ask for. The communication is made through a standard HTTP call, so from a backend developer perspective we don’t really have to put any extra effort to support AJAX calls. 💪 Enough from the introduction, we now know what is AJAX and we are going to build a simple Vapor server to render our HTML document using Leaf Tau. NOTE: Tau was an experimental release, bit it was pulled from the final Leaf 4.0.0 release. Tau will be available later on as a standalone repository with some new features, until that you can still use it if you pin the Leaf dependency to the exact release tag… 🤫 Asynchronous JavaScript and XML (AJAX) is a technology that allows us you to send HTTP requests to your web server from a web page. Based on the response you can use JavaScript to manipulate the HTML Document Object Model (DOM). In short, with the help of AJAX, you can ask for some data, then you can update the contents of the web site based on that. The good thing about AJAX is that you don’t have to reload the entire page, but you can update just a portion of the site. The HTTP request will work on the background so from a user perspective the whole browsing experience will seem faster, than a full page load. ⌛️ AJAX is a frontend technology. It’s a simple JavaScript function call, but some smart people gave it a fancy name. The X in the name comes from the early days of the web, when servers usually returned a “pre-rendered” partial HTML string that you could inject into the DOM without further data manipulation. Nowadays computers are so powerful that most of the servers can return JSON data and then the client can build the necessary HTML structure before the insertion. In order to support AJAX calls on the server side we only have to implement the endpoint that the frontend can ask for. The communication is made through a standard HTTP call, so from a backend developer perspective we don’t really have to put any extra effort to support AJAX calls. 💪 Enough from the introduction, we now know what is AJAX and we are going to build a simple Vapor server to render our HTML document using Leaf Tau. NOTE: Tau was an experimental release, bit it was pulled from the final Leaf 4.0.0 release. Tau will be available later on as a standalone repository with some new features, until that you can still use it if you pin the Leaf dependency to the exact release tag… 🤫 Learn how to implement a user login mechanism with various auth methods using sessions, JWTs, written in Swift only. The official Vapor docs about authentication are pretty good, but for a beginner it can be a little hard to understand, since it covers a lot. In this article I’ll try to explain everything as simple as possible from a different perspective. First let’s define some basic terms. Authentication is the act of verifying a user’s identity. In other words, authentication is the process of transforming a unique key (identifier) to actual user data. This can be a cookie with a session identifier stored in a browser, or another one kept by the API client, but based on this id the backend can retrieve the associated user object. The end user signs in using a login form on a website (or an API endpoint), sends the usual credentials (email, password) to the backend. If those credentials were valid, then the server will return a (randomly generated) identifier to the client. We usually call this identifier, session or token, based on some other principles I’ll cover later on. ⬇️ Next time the client wants to make a request it just needs to send the locally stored id, instead of the sensitive email, password combination. The server just needs to validate the id somehow, if it’s valid then the user is authenticated, we can use it to fetch more details about the user. The act of verifying a previously authenticated user’s permissions to perform certain tasks. How do we know if the authenticated user has access to some endpoint on the server? Is it just a regular visitor, or an admin user? The method of figuring out user roles, permissions, access level is called authorization. It ensures that the authorized user can only access specific resources. 🔒 Consider the following scenario: there are two types of user roles: editors and visitors. An editor can create a new article, but a visitor can only view them (these are the permissions associated to the roles). NOTE: Session ID Vapor only gives you some help to authenticate the user using various methods. Authorization is usually part of your app’s business logic, this means that you have to figure out the details for your own needs, but this is just fine, don’t worry too much about it just yet. 😬 If there is a record on the server side with an identifier, then it is a session. For the sake of simplicity, let’s say that a session is something that you can look up on the server inside some kind of storage. This session is linked to exactly one user account so when you receive a session identifier you can look up the corresponding user through the relation. The session identifier is exchanged to the client after a successful email + password based login request. The client stores session id somewhere for further usage. The storage can be anything, but browsers mainly use cookies or the local storage. Applications can store session identifiers in the keychain, but I’ve seen some really bad practices using a plain-text file. 🙉 Tokens (JWTs) on the other hand have no server side records. A token can be given to the client by the authentication API after a successful login request. The key difference between a token and a session is that a token is cryptographically signed. Thanks to asymmetric keys, the signature can be verified by the application server without knowing the private key that was used to sign the token. A token usually self-contains some other info about the user, expiration date, etc. This additional “metadata” can also be verified by the server, this gives us an extra layer of security. Nowadays JSON Web Token is the golden standard if it comes to tokens. JWT is getting more and more popular, implementations are available for almost every programming language with a wide variety of signing algorithms. There is a really amazing guide to JSON Web Tokens, you should definitely read it if you want to know more about this technology. 📖 Enough theory, time to write some code using Swift on the server. As I mentioned this in the beginning of the article authentication is simply turning a request into actual user data. Vapor has built-in protocols to help us during the process. There is quite an abstraction layer here, which means that you don’t have to dig yourself into HTTP headers or incoming body parameters, but you can work with higher level functions to verify identify. Let me show you all the auth protocols from Vapor 4 and how you can use them in practice. Remember: authentication in Vapor is about turning requests into models using the input. Each and every authentication protocol requires a model that is going to be retrieved during the authentication process. In this example I’ll work with a The official Vapor docs about authentication are pretty good, but for a beginner it can be a little hard to understand, since it covers a lot. In this article I’ll try to explain everything as simple as possible from a different perspective. First let’s define some basic terms. Authentication is the act of verifying a user’s identity. In other words, authentication is the process of transforming a unique key (identifier) to actual user data. This can be a cookie with a session identifier stored in a browser, or another one kept by the API client, but based on this id the backend can retrieve the associated user object. The end user signs in using a login form on a website (or an API endpoint), sends the usual credentials (email, password) to the backend. If those credentials were valid, then the server will return a (randomly generated) identifier to the client. We usually call this identifier, session or token, based on some other principles I’ll cover later on. ⬇️ Next time the client wants to make a request it just needs to send the locally stored id, instead of the sensitive email, password combination. The server just needs to validate the id somehow, if it’s valid then the user is authenticated, we can use it to fetch more details about the user. The act of verifying a previously authenticated user’s permissions to perform certain tasks. How do we know if the authenticated user has access to some endpoint on the server? Is it just a regular visitor, or an admin user? The method of figuring out user roles, permissions, access level is called authorization. It ensures that the authorized user can only access specific resources. 🔒 Consider the following scenario: there are two types of user roles: editors and visitors. An editor can create a new article, but a visitor can only view them (these are the permissions associated to the roles). NOTE: Session ID Vapor only gives you some help to authenticate the user using various methods. Authorization is usually part of your app’s business logic, this means that you have to figure out the details for your own needs, but this is just fine, don’t worry too much about it just yet. 😬 If there is a record on the server side with an identifier, then it is a session. For the sake of simplicity, let’s say that a session is something that you can look up on the server inside some kind of storage. This session is linked to exactly one user account so when you receive a session identifier you can look up the corresponding user through the relation. The session identifier is exchanged to the client after a successful email + password based login request. The client stores session id somewhere for further usage. The storage can be anything, but browsers mainly use cookies or the local storage. Applications can store session identifiers in the keychain, but I’ve seen some really bad practices using a plain-text file. 🙉 Tokens (JWTs) on the other hand have no server side records. A token can be given to the client by the authentication API after a successful login request. The key difference between a token and a session is that a token is cryptographically signed. Thanks to asymmetric keys, the signature can be verified by the application server without knowing the private key that was used to sign the token. A token usually self-contains some other info about the user, expiration date, etc. This additional “metadata” can also be verified by the server, this gives us an extra layer of security. Nowadays JSON Web Token is the golden standard if it comes to tokens. JWT is getting more and more popular, implementations are available for almost every programming language with a wide variety of signing algorithms. There is a really amazing guide to JSON Web Tokens, you should definitely read it if you want to know more about this technology. 📖 Enough theory, time to write some code using Swift on the server. As I mentioned this in the beginning of the article authentication is simply turning a request into actual user data. Vapor has built-in protocols to help us during the process. There is quite an abstraction layer here, which means that you don’t have to dig yourself into HTTP headers or incoming body parameters, but you can work with higher level functions to verify identify. Let me show you all the auth protocols from Vapor 4 and how you can use them in practice. Remember: authentication in Vapor is about turning requests into models using the input. Each and every authentication protocol requires a model that is going to be retrieved during the authentication process. In this example I’ll work with a
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/a-generic-crud-solution-for-vapor-4/index.html b/docs/a-generic-crud-solution-for-vapor-4/index.html
index 0d30e07..1a2245c 100644
--- a/docs/a-generic-crud-solution-for-vapor-4/index.html
+++ b/docs/a-generic-crud-solution-for-vapor-4/index.html
@@ -108,7 +108,7 @@ A generic CRUD solution for Vapor 4
CRUD ~ Create, Read, Update and Delete
vapor new myProjectPackage.swift file, that’ll fire up Xcode (you should be on version 11.4 or later). If you open the Sources/App/Controllers folder you’ll find a sample controller file there called TodoController.swift. We’re going to work on this, but first…HTTP basics: Request -> Response
Contents and models in Vapor
import Fluent
+ CRUD ~ Create, Read, Update and Delete
vapor new myProjectPackage.swift file, that’ll fire up Xcode (you should be on version 11.4 or later). If you open the Sources/App/Controllers folder you’ll find a sample controller file there called TodoController.swift. We’re going to work on this, but first…HTTP basics: Request -> Response
Contents and models in Vapor
import Fluent
import Vapor
final class Todo: Model {
@@ -134,7 +134,7 @@ CRUD ~ Create, Read, Update and Dele
self.title = title
}
}
-
swift run Run migrateCreate
import Fluent
+swift run Run migrateCreate
import Fluent
import Vapor
struct TodoController {
@@ -378,7 +378,7 @@ CRUD ~ Create, Read, Update and Dele
.init(id: self.id!.uuidString, title: self.title)
}
}
-
Context?) struct instead of two.struct TodoController: ApiController {
+Context?) struct instead of two.struct TodoController: ApiController {
typealias Model = Todo
}
func routes(_ app: Application) throws {
diff --git a/docs/a-simple-http2-server-using-vapor-4/index.html b/docs/a-simple-http2-server-using-vapor-4/index.html
index 71e4f04..e3b1037 100644
--- a/docs/a-simple-http2-server-using-vapor-4/index.html
+++ b/docs/a-simple-http2-server-using-vapor-4/index.html
@@ -108,7 +108,7 @@ A simple HTTP/2 server using Vapor 4
What is HTTP/2?
HTTP
Request multiplexing
Server Push
Header compression, encryption, binary format, etc.
SwiftNIO2 + Vapor4 = HTTP/2 support
Project setup
vapor new HTTP2Server
+ What is HTTP/2?
HTTP
Request multiplexing
Server Push
Header compression, encryption, binary format, etc.
SwiftNIO2 + Vapor4 = HTTP/2 support
Project setup
vapor new HTTP2Server
cd HTTP2Server
vapor update -y
Certificate generation
cert.pem and a key.pem files with the following command (fill out the details with some fake data and press enter). 🔐openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
diff --git a/docs/ajax-calls-using-vapor-4/index.html b/docs/ajax-calls-using-vapor-4/index.html
index 7db88a8..7c2c8bc 100644
--- a/docs/ajax-calls-using-vapor-4/index.html
+++ b/docs/ajax-calls-using-vapor-4/index.html
@@ -108,7 +108,7 @@ AJAX calls using Vapor 4
What is AJAX?
Frontend vs backend
Creating the server
// swift-tools-version:5.3
+ What is AJAX?
Frontend vs backend
Creating the server
// swift-tools-version:5.3
import PackageDescription
let package = Package(
diff --git a/docs/all-about-authentication-in-vapor-4/index.html b/docs/all-about-authentication-in-vapor-4/index.html
index d01f60c..b9a3607 100644
--- a/docs/all-about-authentication-in-vapor-4/index.html
+++ b/docs/all-about-authentication-in-vapor-4/index.html
@@ -108,7 +108,7 @@ All about authentication in Vapor 4
Authentication, authorization, sessions, tokens what the f*** is this all about???
Authentication
Authorization
EditorUser is in the group of editors, but VisitorUser only has the visitor role. We can figure out the authority (access level) for each user by checking the roles & permissions.(authentication)> User (authorization)> Roles & PermissionsSessions
Tokens
Implementing auth methods in Vapor
Authentication using a Model
UserModel entity, here’s mine:import Vapor
+ Authentication, authorization, sessions, tokens what the f*** is this all about???
Authentication
Authorization
EditorUser is in the group of editors, but VisitorUser only has the visitor role. We can figure out the authority (access level) for each user by checking the roles & permissions.(authentication)> User (authorization)> Roles & PermissionsSessions
Tokens
Implementing auth methods in Vapor
Authentication using a Model
UserModel entity, here’s mine:import Vapor
import Fluent
final class UserModel: Model {
@@ -154,7 +154,7 @@ Middleware
We’ll need one more (guard) middleware that’s coming from the Authenticatable protocol to respond with an error to unauthenticated requests.
func routes(_ app: Application) throws {
+Firstly, we create a typealias for the associated User type as our UserModel. It is a generic protocol, that’s why you need the typealias.
Inside the authenticator implementation you should look up the given user based on the incoming data, and if everything is valid you can simply call the
req.auth.login([user])method, this will authenticate the user. You should return aVoidfuture from these authenticator protocol methods, but please don’t throw user related errors or use failed futures in this case. You should only supposed to forward database related errors or similar. If the authenticator can’t log in the user, just don’t call the login method, it’s that simple.
The second and final step is to write our authentication logic, in the auth method. You’ll get the request as an input, and you have to return a future with the authenticated user or nil if the authentication was unsuccesful. Pretty easy, fragment is available through the request, and you can look up the entity using Fluent. That’s it, we’re ready. 😅
WARN: The fragment URL part is never going to be available on the server side at all. 💡
How do we use this authenticator? Well the Authenticator protocol itself extends the Middleware protocol, so we can register it right away as a group member. You can use a middleware to alter incoming requests before the next request handler will be called. This definition fits perfectly for the authenticators so it makes sense that they are defined as middlewares.
We’ll need one more (guard) middleware that’s coming from the Authenticatable protocol to respond with an error to unauthenticated requests.
func routes(_ app: Application) throws {
app.grouped(UserModelFragmentAuthenticator(),
UserModel.guardMiddleware())
@@ -162,7 +162,7 @@ Now if you navigate to the http://localhost:8080/sign-in# URL, with a valid UUID of an existing user from the db, the page should display “I’m authenticated”, otherwise you’ll get an HTTP error. The magic happens in the background. I’ll explain the flow one more time.
The “sign-in” route has two middlewares. The first one is the authenticator which will try to turn the request into a model using the implemented authentication method. If the authentication was succesful it’ll store the user object inside a generic request.auth property.
The second middleware literally guards the route from unauthenticated requests. It checks the request.auth variable, if it contains an authenticated user object or not. If it finds a previously authenticated user it’ll continue with the next handler, otherwise it’ll throw an error. Vapor can automatically turn thrown errors into HTTP status codes, that’s why you’ll get a 401.
WARN: The names of the HTTP standard response codes are a little big misleading. You should respond with 401 (unauthorized) for unsuccesful authentication requests, and 403 (forbidden) responses for unauthorized requests. Strange, huh? 😳
You don’t necessary need this second middleware, but I’d recommend using it. You can manually check the existence of an authenticated object using try req.auth.require(UserModel.self) inside the request handler. A guard middleware is available on every Authenticatable object, essentially it is doing the same thing as I mentioned above, but in a more generic, reusable way.
Finally the request handler will only be called if the user is already authenticated, otherwise it’ll never be executed. This is how you can protect routes from unauthenticated requests.
A BasicAuthenticator is just an extension over the RequestAuthenticator protocol. During a basic authentication the credentials are arriving base64 encoded inside the Authorization HTTP header. The format is Authorization: Basic email:password where the email:password or username:password credentials are only base64 encoed. Vapor helps you with the decoding process, that’s what the protocol adds over the top of the request authentication layer, so you can write a basic authenticator like this:
struct UserModelBasicAuthenticator: BasicAuthenticator {
+Now if you navigate to the http://localhost:8080/sign-in# URL, with a valid UUID of an existing user from the db, the page should display “I’m authenticated”, otherwise you’ll get an HTTP error. The magic happens in the background. I’ll explain the flow one more time.
The “sign-in” route has two middlewares. The first one is the authenticator which will try to turn the request into a model using the implemented authentication method. If the authentication was succesful it’ll store the user object inside a generic request.auth property.
The second middleware literally guards the route from unauthenticated requests. It checks the request.auth variable, if it contains an authenticated user object or not. If it finds a previously authenticated user it’ll continue with the next handler, otherwise it’ll throw an error. Vapor can automatically turn thrown errors into HTTP status codes, that’s why you’ll get a 401.
WARN: The names of the HTTP standard response codes are a little big misleading. You should respond with 401 (unauthorized) for unsuccesful authentication requests, and 403 (forbidden) responses for unauthorized requests. Strange, huh? 😳
You don’t necessary need this second middleware, but I’d recommend using it. You can manually check the existence of an authenticated object using try req.auth.require(UserModel.self) inside the request handler. A guard middleware is available on every Authenticatable object, essentially it is doing the same thing as I mentioned above, but in a more generic, reusable way.
Finally the request handler will only be called if the user is already authenticated, otherwise it’ll never be executed. This is how you can protect routes from unauthenticated requests.
A BasicAuthenticator is just an extension over the RequestAuthenticator protocol. During a basic authentication the credentials are arriving base64 encoded inside the Authorization HTTP header. The format is Authorization: Basic email:password where the email:password or username:password credentials are only base64 encoed. Vapor helps you with the decoding process, that’s what the protocol adds over the top of the request authentication layer, so you can write a basic authenticator like this:
struct UserModelBasicAuthenticator: BasicAuthenticator {
typealias User = UserModel
diff --git a/docs/all-about-the-swift-package-manager-and-the-swift-toolchain/index.html b/docs/all-about-the-swift-package-manager-and-the-swift-toolchain/index.html
index cda1159..4b36245 100644
--- a/docs/all-about-the-swift-package-manager-and-the-swift-toolchain/index.html
+++ b/docs/all-about-the-swift-package-manager-and-the-swift-toolchain/index.html
@@ -152,7 +152,7 @@ All about the Swift Package Manager and the Swift toolchain
swift build -Xswiftc -I -Xswiftc ./.build/debug -Xswiftc -L -Xswiftc ./.build/debug -Xswiftc -lmyStaticLib
swift build -Xswiftc -I -Xswiftc ./.build/debug -Xswiftc -L -Xswiftc ./.build/debug -Xswiftc -lmyDynamicLib
-You just have to append a few compiler flags. The -I stands for the import search path, -L is the library search path, -l links the given library. Check swiftc -h for more details and flags you won’t regret it! Voilá now you can distribute closed source Swift packages. At least it was good to know how SPM does the “trick”. 🤓
WARN: Please note that until Swift 5 & ABI stability arrives you can use the precompiled libraries with the same Swift version only! So if you compile a lib with Swift 4.2, your executable also needs to be compiled with 4.2., but this will change pretty soon. 👏
The Swift Package Manager method
After 2 days of research & learning I really wanted to solve this, so I’ve started to check the source code of SPM. The first thing I’ve tried was adding the --verbose flag after the swift build command. Here is the important thing:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc \
+You just have to append a few compiler flags. The -I stands for the import search path, -L is the library search path, -l links the given library. Check swiftc -h for more details and flags you won’t regret it! Voilá now you can distribute closed source Swift packages. At least it was good to know how SPM does the “trick”. 🤓
WARN: Please note that until Swift 5 & ABI stability arrives you can use the precompiled libraries with the same Swift version only! So if you compile a lib with Swift 4.2, your executable also needs to be compiled with 4.2., but this will change pretty soon. 👏
The Swift Package Manager method
After 2 days of research & learning I really wanted to solve this, so I’ve started to check the source code of SPM. The first thing I’ve tried was adding the --verbose flag after the swift build command. Here is the important thing:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc \
--driver-mode=swift \
-L /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/4_2 \
-lPackageDescription \
@@ -167,7 +167,7 @@ All about the Swift Package Manager and the Swift toolchain
error: unable to invoke subcommand:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-lol
(No such file or directory)
-Got ya! The toolchain is the key to everything:
.swiftmodule, .swiftdoc, .dylib files into the proper places under Xcode’s default toolchain library path.NOTE: Swift can resolve subcommands from anywhere “inside” the
PATHvariable. You just have to prefix your Swift script withswift-and you’re good to go.
I had this idea that it’d be nice to have a grunt / gulp like task runner also a continuous integration service on a long term by using this technique I explained above. So I’ve made a similar extension wired into the heart of the Swift toolchain: SwiftCI. ❤️
You can grab the proof-of-concept implementation of SwiftCI from GitHub. After installing it you can create your own CI.swift files and run your workflows.
import CI
+Got ya! The toolchain is the key to everything:
.swiftmodule, .swiftdoc, .dylib files into the proper places under Xcode’s default toolchain library path.NOTE: Swift can resolve subcommands from anywhere “inside” the
PATHvariable. You just have to prefix your Swift script withswift-and you’re good to go.
I had this idea that it’d be nice to have a grunt / gulp like task runner also a continuous integration service on a long term by using this technique I explained above. So I’ve made a similar extension wired into the heart of the Swift toolchain: SwiftCI. ❤️
You can grab the proof-of-concept implementation of SwiftCI from GitHub. After installing it you can create your own CI.swift files and run your workflows.
import CI
let buildWorkflow = Workflow(
name: "default",
diff --git a/docs/authors/tibor-bodecs/index.html b/docs/authors/tibor-bodecs/index.html
index 251b9a7..99d7ae3 100644
--- a/docs/authors/tibor-bodecs/index.html
+++ b/docs/authors/tibor-bodecs/index.html
@@ -409,7 +409,7 @@
- · 2 min read
+ · 3 min read
Swift visitor design pattern
@@ -520,7 +520,7 @@
- · 3 min read
+ · 4 min read
How to use a Swift library in C
@@ -699,7 +699,7 @@
- · 5 min read
+ · 6 min read
Building tree data structures in Swift
@@ -898,7 +898,7 @@
- · 7 min read
+ · 8 min read
Declarative unit tests for Vapor
@@ -966,7 +966,7 @@
- · 7 min read
+ · 8 min read
Memory layout in Swift
@@ -1351,7 +1351,7 @@
Websockets for beginners using Vapor 4 and Vanilla JavaScript
@@ -1396,7 +1396,7 @@
- · 4 min read
+ · 5 min read
What's new in Swift 5.3?
@@ -1712,7 +1712,7 @@
- · 17 min read
+ · 18 min read
Beginner's guide to Server side Swift using Vapor 4
@@ -2247,7 +2247,7 @@
Custom UIView subclass from a xib file
@@ -2826,7 +2826,7 @@
- · 10 min read
+ · 11 min read
Deep dive into Swift frameworks
@@ -3028,16 +3028,17 @@
- Asynchronous validation for Vapor
+ UIKit init patterns
- Learn how to validate input data using an async technique. Unified request validation API for your server side Swift app.
+ Learn about the initialization process of the two well known classes in UIKit. Say hello to UIViewcontroller, and UIView init patterns.
@@ -3051,15 +3052,16 @@
- · 6 min read
+ · 2 min read
- Everything about public and private Swift attributes
+ Top 20 iOS libraries written in Swift
- Have you ever heard about Swift language attributes? In this article I'm trying to gather all the @ annotations and their meanings.
+ I gathered the best open source Swift frameworks on github that will help you to speed up mobile application development in 2019.
@@ -3073,15 +3075,16 @@
- · 6 min read
+ · 7 min read
- How to create reusable views for modern collection views?
+ The ultimate Combine framework tutorial in Swift
- A quick intro to modern collection views using compositional layout, diffable data source and reusable view components.
+ Get started with the brand new declarative Combine framework in practice using Swift. I'll teach you all the goodies from zero to hero.
@@ -3117,16 +3120,15 @@
- The ultimate Combine framework tutorial in Swift
+ How to create reusable views for modern collection views?
- Get started with the brand new declarative Combine framework in practice using Swift. I'll teach you all the goodies from zero to hero.
+ A quick intro to modern collection views using compositional layout, diffable data source and reusable view components.
@@ -3140,16 +3142,15 @@
- · 2 min read
+ · 6 min read
- Top 20 iOS libraries written in Swift
+ Everything about public and private Swift attributes
- I gathered the best open source Swift frameworks on github that will help you to speed up mobile application development in 2019.
+ Have you ever heard about Swift language attributes? In this article I'm trying to gather all the @ annotations and their meanings.
@@ -3163,17 +3164,16 @@
- · 1 min read
+ · 13 min read
- UIKit init patterns
+ Asynchronous validation for Vapor
- Learn about the initialization process of the two well known classes in UIKit. Say hello to UIViewcontroller, and UIView init patterns.
+ Learn how to validate input data using an async technique. Unified request validation API for your server side Swift app.
diff --git a/docs/beginners-guide-to-server-side-swift-using-vapor-4/index.html b/docs/beginners-guide-to-server-side-swift-using-vapor-4/index.html
index c1eeaee..27dd2c3 100644
--- a/docs/beginners-guide-to-server-side-swift-using-vapor-4/index.html
+++ b/docs/beginners-guide-to-server-side-swift-using-vapor-4/index.html
@@ -100,7 +100,7 @@
Beginner's guide to Server side Swift using Vapor 4
diff --git a/docs/beginners-guide-to-swift-package-manager-command-plugins/index.html b/docs/beginners-guide-to-swift-package-manager-command-plugins/index.html
index 884668e..f087365 100644
--- a/docs/beginners-guide-to-swift-package-manager-command-plugins/index.html
+++ b/docs/beginners-guide-to-swift-package-manager-command-plugins/index.html
@@ -176,7 +176,7 @@ Introduction to Swift Pac
}
}
}
-
The snippet above should locate the swiftlint tool using the plugins context then it’ll iterate through the available package targets, filter out non source-module targets and format only those targets that contains actual Swift source files. The process object should simply invoke the underlying tool, we can wait until the child (swiftlint invocation) process exists and hopefully we’re good to go. 🤞
NOTE: Update: kalKarmaDev told me that it is possible to pass the
--in-process-sourcekitargument to SwiftLint, this will fix the underlying issue and the source files are actually fixed.
I wanted to list the available plugins & run my source code linter / formatter using the following shell commands, but unfortunately seems like the swiftlint invocation part failed for some strange reason.
swift package plugin --list
+The snippet above should locate the swiftlint tool using the plugins context then it’ll iterate through the available package targets, filter out non source-module targets and format only those targets that contains actual Swift source files. The process object should simply invoke the underlying tool, we can wait until the child (swiftlint invocation) process exists and hopefully we’re good to go. 🤞
NOTE: Update: kalKarmaDev told me that it is possible to pass the
--in-process-sourcekitargument to SwiftLint, this will fix the underlying issue and the source files are actually fixed.
I wanted to list the available plugins & run my source code linter / formatter using the following shell commands, but unfortunately seems like the swiftlint invocation part failed for some strange reason.
swift package plugin --list
swift package format-source-code #won't work, needs access to source files
swift package --allow-writing-to-package-directory format-source-code
diff --git a/docs/beginners-guide-to-the-asyncawait-concurrency-api-in-vapor-fluent/index.html b/docs/beginners-guide-to-the-asyncawait-concurrency-api-in-vapor-fluent/index.html
index 353331d..1df8137 100644
--- a/docs/beginners-guide-to-the-asyncawait-concurrency-api-in-vapor-fluent/index.html
+++ b/docs/beginners-guide-to-the-asyncawait-concurrency-api-in-vapor-fluent/index.html
@@ -222,7 +222,7 @@ Is async/await going to improve V
.map { .ok }
}
}
-
The very first method that we’re going to convert is the findTodoByIdParam. Fortunately this version of FluentKit comes with a set of async functions to query and modify database models.
We just have to remove the EventLoopFuture type and write async before the throws keyword, this will indicate that our function is going to be executed asynchronously.
NOTE: It is worth to mention that you can only call an async function from async functions. If you want to call an async function from a sync function you’ll have to use a special (deatch) method. You can call however sync functions inside async methods without any trouble. 🔀
We can use the new async find method to fetch the TodoModel based on the UUID parameter. When you call an async function you have to await for the result. This will let you use the return type just like it it was a sync call, so there is no need for completion blocks anymore and we can simply guard the optional model result and throw a notFound error if needed. Async functions can throw as well, so you might have to write try await when you call them, note that the order of the keywords is fixed, so try always comes before await, and the signature is always async throws.
func findTodoByIdParam(_ req: Request) async throws -> TodoModel {
+The very first method that we’re going to convert is the findTodoByIdParam. Fortunately this version of FluentKit comes with a set of async functions to query and modify database models.
We just have to remove the EventLoopFuture type and write async before the throws keyword, this will indicate that our function is going to be executed asynchronously.
NOTE: It is worth to mention that you can only call an async function from async functions. If you want to call an async function from a sync function you’ll have to use a special (deatch) method. You can call however sync functions inside async methods without any trouble. 🔀
We can use the new async find method to fetch the TodoModel based on the UUID parameter. When you call an async function you have to await for the result. This will let you use the return type just like it it was a sync call, so there is no need for completion blocks anymore and we can simply guard the optional model result and throw a notFound error if needed. Async functions can throw as well, so you might have to write try await when you call them, note that the order of the keywords is fixed, so try always comes before await, and the signature is always async throws.
func findTodoByIdParam(_ req: Request) async throws -> TodoModel {
guard let model = try await TodoModel.find(try getTodoIdParam(req), on: req.db) else {
throw Abort(.notFound)
}
diff --git a/docs/building-and-loading-dynamic-libraries-at-runtime-in-swift/index.html b/docs/building-and-loading-dynamic-libraries-at-runtime-in-swift/index.html
index f660775..62ac729 100644
--- a/docs/building-and-loading-dynamic-libraries-at-runtime-in-swift/index.html
+++ b/docs/building-and-loading-dynamic-libraries-at-runtime-in-swift/index.html
@@ -222,7 +222,7 @@ Why should we make a plugin system?<
let myPlugin = plugin(at: "path/to/my/plugin/libPluginA.dylib")
let a = myPlugin.foo()
print(a)
-
We can use the dlopen function to open the dynamic library file, then we are trying to get the createPlugin symbol using the dlsym method. If we have a pointer we still need to cast that into a valid PluginBuilder object, then we can call the build method and return the plugin interface.
Now if you try to run this application using Xcode you’ll get a warning like this:
WARN: Class _TtC15PluginInterface13PluginBuilder is implemented in both… One of the two will be used. Which one is undefined.
This is related to an old bug, but fortunately that is already resolved. This time Xcode is the bad guy, since it is trying to link everything as a static dependency. Now if you build the application through the command line (swift build) and place the following files in the same folder:
You can run the application ./CoreApp without further issues. The app will print out A without the warning message, since the Swift package manager is recognizing that you would like to link the libPluginInterface framework as a dynamic framework, so it won’t be embedded into the application binary. Of course you have to set up the right plugin path in the core application.
We can use the dlopen function to open the dynamic library file, then we are trying to get the createPlugin symbol using the dlsym method. If we have a pointer we still need to cast that into a valid PluginBuilder object, then we can call the build method and return the plugin interface.
Now if you try to run this application using Xcode you’ll get a warning like this:
WARN: Class _TtC15PluginInterface13PluginBuilder is implemented in both… One of the two will be used. Which one is undefined.
This is related to an old bug, but fortunately that is already resolved. This time Xcode is the bad guy, since it is trying to link everything as a static dependency. Now if you build the application through the command line (swift build) and place the following files in the same folder:
You can run the application ./CoreApp without further issues. The app will print out A without the warning message, since the Swift package manager is recognizing that you would like to link the libPluginInterface framework as a dynamic framework, so it won’t be embedded into the application binary. Of course you have to set up the right plugin path in the core application.
Learn how to build complex forms with my updated collection view view-model framework without the struggle using Swift.
WARN: This method is not working, since cells in the form are going to be reused and this leads to some inconsistency… please read my other post. 🤷♂️
My CollectionView framework just got a HUGE update. There are lots of new changes, but one of the biggest improvement is the way I deal with view models. In the past, you had to use long function names in your view model including the generic view & model class names. If you have ever read my ultimate UICollectionView guide you should know what I’m talking about. Good news: I have a way better solution now! 😉
This update not just cleans up my code a lot, but it allows me to add custom view model handlers, so I can interact with input fields, toggles, etc. in a ridiculously easy way. Another huge improvement is that I started to use view identifiers. It was accidental discovery, I only wanted to look for an alternative solution for identifying views by tags, then I had this brilliant idea: why not look up cells by ids as well?
As a result I’m now able to create forms by using the framework. I still believe that collection views are the ultimate building blocks for most of the applications. Yeah, you can still say that there is no silver bullet, but I’m just fine if this solution can cover 90% of the my use-cases. After all, most of the apps are just visualizing JSON data in a nice, or not-so-nice way. 🤷♂️ #sarcasm
Let’s build a form by using the brand new framework. First of all, you’ll need to integrate it by using a package manager. I really hope that in a few weeks we can use Swift Package Manager, until than you you should go with CocoaPods or carthage.
# cocoapods
+ WARN: This method is not working, since cells in the form are going to be reused and this leads to some inconsistency… please read my other post. 🤷♂️
CollectionView and input forms
My CollectionView framework just got a HUGE update. There are lots of new changes, but one of the biggest improvement is the way I deal with view models. In the past, you had to use long function names in your view model including the generic view & model class names. If you have ever read my ultimate UICollectionView guide you should know what I’m talking about. Good news: I have a way better solution now! 😉
This update not just cleans up my code a lot, but it allows me to add custom view model handlers, so I can interact with input fields, toggles, etc. in a ridiculously easy way. Another huge improvement is that I started to use view identifiers. It was accidental discovery, I only wanted to look for an alternative solution for identifying views by tags, then I had this brilliant idea: why not look up cells by ids as well?
As a result I’m now able to create forms by using the framework. I still believe that collection views are the ultimate building blocks for most of the applications. Yeah, you can still say that there is no silver bullet, but I’m just fine if this solution can cover 90% of the my use-cases. After all, most of the apps are just visualizing JSON data in a nice, or not-so-nice way. 🤷♂️ #sarcasm
Reusable form components
Let’s build a form by using the brand new framework. First of all, you’ll need to integrate it by using a package manager. I really hope that in a few weeks we can use Swift Package Manager, until than you you should go with CocoaPods or carthage.
# cocoapods
source 'https://github.com/CoreKit/CocoaPods.git'
pod 'CollectionView', '~> 2.0.0'
@@ -313,7 +313,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/building-tree-data-structures-in-swift/index.html b/docs/building-tree-data-structures-in-swift/index.html
index d6c7592..25c4e83 100644
--- a/docs/building-tree-data-structures-in-swift/index.html
+++ b/docs/building-tree-data-structures-in-swift/index.html
@@ -100,7 +100,7 @@
Building tree data structures in Swift
diff --git a/docs/conventions-for-xcode/index.html b/docs/conventions-for-xcode/index.html
index 1cae831..48f5b68 100644
--- a/docs/conventions-for-xcode/index.html
+++ b/docs/conventions-for-xcode/index.html
@@ -108,10 +108,10 @@ Conventions for Xcode
Learn how to organize your codebase. If you are struggling with Xcode project structure, files, naming conventions, read this.
- Apple has so much frameworks and APIs that I don’t even know many of them. We are also living in the age of application extensions. If you are trying to create a brand new target in Xcode, you might end up scratching your head. 🤔

This is great for both for developers and end-users, but after creating a few targets and platforms (your project grows and) you might ask the question:
How should I organise my codebase?
Don’t worry too much about it, I might have the right answer for you! 😉
The problem with complex projects
You can create apps in Xcode for all the major operating systems: iOS, macOS, tvOS, watchOS. In the latest version of Xcode you can also add more than 20 extension just for iOS, plus there are lots of app extensions available for macOS as well. Imagine a complex application with multiple extensions & targets. This situation can lead to inconsistent bundle identifiers and more ad-hoc naming solutions. Oh, by the way watchOS applications are just a special extensions for iOS targets and don’t forget about your tests, those are individual targets as well! ⚠️
As far as I can see, if you are trying to support multiple platforms you are going to have a lot of targets inside your Xcode project, additionally every new target will contain some kind of source files and assets. Should I mention schemes too? 😂
Even Apple removed it’s Lister sample code, that demonstrated one of a hellish Xcode project with 14 targets, 11 schemes, but the overall project contained only 71 Swift source files. That’s not too much code, but you can see the issue here, right?
It’s time to learn how to organise your project! 💡
Xcode project organization
So my basic idea is to have a reasonable naming conceptand folder structure inside the project. This involves targets, schemes, bundle identifiers, location of source files and assets on the disk. Let’s start with a simple example that contains multiple targets to have a better understanding. 🤓
NOTE: If you are using the Swift Package Manager eg. for Swift backends, SPM will generate your Xcode project files for you, so you shoudn’t care too much about conventions and namings at all. 🤷♂️
Project name
Are you creating a new application? Feel free to name your project as you want. 😉
Are you going to make a framework? Extend your project name with the Kit suffix. People usually prefer to use the ProjectKit style for libraries so that’s the correct way to go. If you have a killer name, use that instead of the kit style! 😛
Available platforms
Always use the following platform names:
- iOS
- macOS
- watchOS
- tvOS
Target naming convention
Name your targets like:
[platform] [template name]
+ Apple has so much frameworks and APIs that I don’t even know many of them. We are also living in the age of application extensions. If you are trying to create a brand new target in Xcode, you might end up scratching your head. 🤔

This is great for both for developers and end-users, but after creating a few targets and platforms (your project grows and) you might ask the question:
How should I organise my codebase?
Don’t worry too much about it, I might have the right answer for you! 😉
The problem with complex projects
You can create apps in Xcode for all the major operating systems: iOS, macOS, tvOS, watchOS. In the latest version of Xcode you can also add more than 20 extension just for iOS, plus there are lots of app extensions available for macOS as well. Imagine a complex application with multiple extensions & targets. This situation can lead to inconsistent bundle identifiers and more ad-hoc naming solutions. Oh, by the way watchOS applications are just a special extensions for iOS targets and don’t forget about your tests, those are individual targets as well! ⚠️
As far as I can see, if you are trying to support multiple platforms you are going to have a lot of targets inside your Xcode project, additionally every new target will contain some kind of source files and assets. Should I mention schemes too? 😂
Even Apple removed it’s Lister sample code, that demonstrated one of a hellish Xcode project with 14 targets, 11 schemes, but the overall project contained only 71 Swift source files. That’s not too much code, but you can see the issue here, right?
It’s time to learn how to organise your project! 💡
Xcode project organization
So my basic idea is to have a reasonable naming conceptand folder structure inside the project. This involves targets, schemes, bundle identifiers, location of source files and assets on the disk. Let’s start with a simple example that contains multiple targets to have a better understanding. 🤓
NOTE: If you are using the Swift Package Manager eg. for Swift backends, SPM will generate your Xcode project files for you, so you shoudn’t care too much about conventions and namings at all. 🤷♂️
Project name
Are you creating a new application? Feel free to name your project as you want. 😉
Are you going to make a framework? Extend your project name with the Kit suffix. People usually prefer to use the ProjectKit style for libraries so that’s the correct way to go. If you have a killer name, use that instead of the kit style! 😛
Available platforms
Always use the following platform names:
- iOS
- macOS
- watchOS
- tvOS
Target naming convention
Name your targets like:
[platform] [template name]
Don’t include project name in the targets (that would be just a duplicate)
Use the extension names from the new target window (eg. Today Extension)
Use “Application” template name for the main application targets
Use “Framework” as template name for framework targets
Order your targets in a logical way (see the example)
Scheme names
Simply use target names for schemes too (prefix with project name if required).
[project] - [platform] [template name]
You can prefix schemes with your project name if you want, but the generic rule is here to use the exact same name as your target. I also like to separate framework schemes visually from the schems that contain application logic, that’s why I always move them to the top of the list. However a better approach is to separate frameworks into a standalone git repository & connect them through a package manager. 📦
Bundle identifiers
This one is hard because of code signing. You can go with something like this:
[reverse domain].[project].[platform].[template name]
-
Here are the rules:
- Start with your reverse domain name (com.example)
- After the domain, insert your project name
- Include platform names, except for iOS, I don’t append that one.
- Use the template name as a suffix (like .todayextension)
- Don’t add application as a template name
- Use .watchkitapp, .watchkitextension for legacy watchOS targets
- Don’t use more than 4 dots (see example below)!
NOTE: If you are going to use com.example.project.ios.today.extension that’s not going to work, because it contains more than 4 dots. So you should simply go with com.example.project.ios.todayextension and names like that. 😢
Anyway, just always try to sign your app and submit to the store. Good luck. 🍀
Project folders
The thing is that I always create physical folders on the disk. If you make a group in Xcode, well by default that’s not going to be an actual folder and all your source files and assets will be located under the project’s main directory.
I know it’s a personal preference but I don’t like to call a giant “wasteland” of files as a project. I’ve seen many chaotic projects without proper file organization. 🤐
No matter what, but I always follow this basic pattern:
- Create folders for the targets
- Create a Sources folder for the Swift source files
- Create an Assets folder for everything else (images, etc).
Under the Sources I always make more subfolders for individual VIPER modules, or simply for controllers, models, objects, etc.
Example use case
Here is a quick example project in Xcode that uses my conventions.

As you can see I followed the pattern from above. Let’s assume that my project name is TheSwiftDev. Here is a quick overview of the full setup:
Target & scheme names (with bundle identifiers):
- iOS Application (com.tiborbodecs.theswiftdev)
- iOS Application Unit Tests (n/a)
- iOS Application UI Tests (n/a)
- iOS Today Extension (com.tiborbodecs.theswiftdev.todayextension)
- watchOS Application (com.tiborbodecs.theswiftdev.watchos)
- watchOS Application Extension (com.tiborbodecs.theswiftdev.watchos.extension)
- tvOS Application (com.tiborbodecs.theswiftdev.macos)
- macOS Application (com.tiborbodecs.theswiftdev.tvos)
NOTE: If you rename your iOS target with a WatchKit companion app, be careful!!! You also have to change the WKCompanionAppBundleIdentifier property inside your watch application target’s Info.plist file by hand. ⚠️
This method might looks like an overkill at first sight, but trust me it’s worth to follow these conventions. As your app grows, eventually you will face the same issues as I mentioned in the beginning. It’s better to have a plan for the future.
+
Here are the rules:
- Start with your reverse domain name (com.example)
- After the domain, insert your project name
- Include platform names, except for iOS, I don’t append that one.
- Use the template name as a suffix (like .todayextension)
- Don’t add application as a template name
- Use .watchkitapp, .watchkitextension for legacy watchOS targets
- Don’t use more than 4 dots (see example below)!
NOTE: If you are going to use com.example.project.ios.today.extension that’s not going to work, because it contains more than 4 dots. So you should simply go with com.example.project.ios.todayextension and names like that. 😢
Anyway, just always try to sign your app and submit to the store. Good luck. 🍀
Project folders
The thing is that I always create physical folders on the disk. If you make a group in Xcode, well by default that’s not going to be an actual folder and all your source files and assets will be located under the project’s main directory.
I know it’s a personal preference but I don’t like to call a giant “wasteland” of files as a project. I’ve seen many chaotic projects without proper file organization. 🤐
No matter what, but I always follow this basic pattern:
- Create folders for the targets
- Create a Sources folder for the Swift source files
- Create an Assets folder for everything else (images, etc).
Under the Sources I always make more subfolders for individual VIPER modules, or simply for controllers, models, objects, etc.
Example use case
Here is a quick example project in Xcode that uses my conventions.

As you can see I followed the pattern from above. Let’s assume that my project name is TheSwiftDev. Here is a quick overview of the full setup:
Target & scheme names (with bundle identifiers):
- iOS Application (com.tiborbodecs.theswiftdev)
- iOS Application Unit Tests (n/a)
- iOS Application UI Tests (n/a)
- iOS Today Extension (com.tiborbodecs.theswiftdev.todayextension)
- watchOS Application (com.tiborbodecs.theswiftdev.watchos)
- watchOS Application Extension (com.tiborbodecs.theswiftdev.watchos.extension)
- tvOS Application (com.tiborbodecs.theswiftdev.macos)
- macOS Application (com.tiborbodecs.theswiftdev.tvos)
NOTE: If you rename your iOS target with a WatchKit companion app, be careful!!! You also have to change the WKCompanionAppBundleIdentifier property inside your watch application target’s Info.plist file by hand. ⚠️
This method might looks like an overkill at first sight, but trust me it’s worth to follow these conventions. As your app grows, eventually you will face the same issues as I mentioned in the beginning. It’s better to have a plan for the future.
diff --git a/docs/custom-uiview-subclass-from-a-xib-file/index.html b/docs/custom-uiview-subclass-from-a-xib-file/index.html
index 895540c..edbcb6f 100644
--- a/docs/custom-uiview-subclass-from-a-xib-file/index.html
+++ b/docs/custom-uiview-subclass-from-a-xib-file/index.html
@@ -100,7 +100,7 @@
Custom UIView subclass from a xib file
diff --git a/docs/custom-views-input-forms-and-mistakes/index.html b/docs/custom-views-input-forms-and-mistakes/index.html
index b7ee94a..a16ca4e 100644
--- a/docs/custom-views-input-forms-and-mistakes/index.html
+++ b/docs/custom-views-input-forms-and-mistakes/index.html
@@ -281,7 +281,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/custom-working-directory-in-xcode/index.html b/docs/custom-working-directory-in-xcode/index.html
index 7c114e7..ff9665a 100644
--- a/docs/custom-working-directory-in-xcode/index.html
+++ b/docs/custom-working-directory-in-xcode/index.html
@@ -108,7 +108,7 @@ Custom working directory in Xcode
Learn how to set a custom working directory in Xcode to solve one of the most common beginner issue when using Vapor.
- What is a custom working directory?
When you try to build and run your Vapor application using Xcode you might face the issue that there are some missing files, resources or Leaf templates. Don’t worry this is a very common rookie mistake, but what causes this problem exactly? 🤔
Vapor is using a place called working directory to set the current environment, locate common resources and publicly available files. This working directory usually contains a Resources folder where you can put your Leaf templates and a Public folder which is used by the FileMiddleware. The server is also trying to search for possible dotenv files to configure environmental variables.
If you run your backend application without explicitly setting a custom working directory, you should see a warning message in Xcode’s console. If you are using Feather CMS, the app will crash without a custom working directory set, because it is required to provide a working environment. 🙃

If you don’t specify this custom work dir, Xcode will try to look for the resources under a random, but uniquely created place somewhere under the DerivedData directory.
This is the internal build folder for the IDE, it usually creates lots of other “garbage” files into the ~/Library/Developer/Xcode/DerivedData directory. In 99% of the cases you can safely delete its contents if you want to perform a 100% clean build. 👍
How to set a custom working directory?
First of all, open your project in Xcode by double clicking the Package.swift manifest file.
WARN: Do NOT use the swift package generate-xcodeproj command to generate a project file!!! This is a deprecated Swift Package Manager command, and it’s going to be removed soon.
✅ I repeat: always open SPM projects through the Package.swift file.

Wait until the IDE loads the required Swift packages. After the dependencies are loaded, click on the target next to the stop button. The executable target is marked with a little terminal-like icon. 💡

Select the “Edit Scheme…” option from the available menu items, this should open a new modal window on top of Xcode.

Make sure that the Run configuration is selected on the left side of the pane. Click on the “Options” tab, and then look for the “Working directory” settings. Check the “Use custom working directory:” toggle, this will enable the input field underneath, then finally click on the little folder icon on the top right side (of the input field) and look for your desired directory using the interface. 🔍
Press the “Choose” button when you are ready. You should see the path of your choice written inside the text field. Make sure that you’ve selected the right location. Now you can click the “Close” button on the bottom right corner, then you can try to start your server by clicking the run button (play icon or you can press the CMD+R shortcut to run the app). ▶️
If you did everything right, your Vapor server application should use the custom working directory, you can confirm this by checking the logs in Xcode. The previously mentioned warning should disappear and your backend should be able to load all the necessary resources without further issues. I hope this little guide will help you to avoid this common mistake when using Vapor. 🙏
+ What is a custom working directory?
When you try to build and run your Vapor application using Xcode you might face the issue that there are some missing files, resources or Leaf templates. Don’t worry this is a very common rookie mistake, but what causes this problem exactly? 🤔
Vapor is using a place called working directory to set the current environment, locate common resources and publicly available files. This working directory usually contains a Resources folder where you can put your Leaf templates and a Public folder which is used by the FileMiddleware. The server is also trying to search for possible dotenv files to configure environmental variables.
If you run your backend application without explicitly setting a custom working directory, you should see a warning message in Xcode’s console. If you are using Feather CMS, the app will crash without a custom working directory set, because it is required to provide a working environment. 🙃

If you don’t specify this custom work dir, Xcode will try to look for the resources under a random, but uniquely created place somewhere under the DerivedData directory.
This is the internal build folder for the IDE, it usually creates lots of other “garbage” files into the ~/Library/Developer/Xcode/DerivedData directory. In 99% of the cases you can safely delete its contents if you want to perform a 100% clean build. 👍
How to set a custom working directory?
First of all, open your project in Xcode by double clicking the Package.swift manifest file.
WARN: Do NOT use the swift package generate-xcodeproj command to generate a project file!!! This is a deprecated Swift Package Manager command, and it’s going to be removed soon.
✅ I repeat: always open SPM projects through the Package.swift file.

Wait until the IDE loads the required Swift packages. After the dependencies are loaded, click on the target next to the stop button. The executable target is marked with a little terminal-like icon. 💡

Select the “Edit Scheme…” option from the available menu items, this should open a new modal window on top of Xcode.

Make sure that the Run configuration is selected on the left side of the pane. Click on the “Options” tab, and then look for the “Working directory” settings. Check the “Use custom working directory:” toggle, this will enable the input field underneath, then finally click on the little folder icon on the top right side (of the input field) and look for your desired directory using the interface. 🔍
Press the “Choose” button when you are ready. You should see the path of your choice written inside the text field. Make sure that you’ve selected the right location. Now you can click the “Close” button on the bottom right corner, then you can try to start your server by clicking the run button (play icon or you can press the CMD+R shortcut to run the app). ▶️
If you did everything right, your Vapor server application should use the custom working directory, you can confirm this by checking the logs in Xcode. The previously mentioned warning should disappear and your backend should be able to load all the necessary resources without further issues. I hope this little guide will help you to avoid this common mistake when using Vapor. 🙏
diff --git a/docs/declarative-unit-tests-for-vapor/index.html b/docs/declarative-unit-tests-for-vapor/index.html
index 1733939..b06e875 100644
--- a/docs/declarative-unit-tests-for-vapor/index.html
+++ b/docs/declarative-unit-tests-for-vapor/index.html
@@ -100,7 +100,7 @@
Declarative unit tests for Vapor
diff --git a/docs/deep-dive-into-swift-frameworks/index.html b/docs/deep-dive-into-swift-frameworks/index.html
index 9b969ec..8c03e19 100644
--- a/docs/deep-dive-into-swift-frameworks/index.html
+++ b/docs/deep-dive-into-swift-frameworks/index.html
@@ -100,7 +100,7 @@
Deep dive into Swift frameworks
@@ -207,7 +207,7 @@ Basic definitions
First of all you should have
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done
-
This little script will remove all the unnecessary slices from the framework, so you’ll be able to submit your app via iTunesConnect, without any issues. (ha-ha-ha. 😅)
NOTE: You have to add this last script to your application’s build phases.
If you want to get familiar with the tools behind the scenes, this article will help you with the basics. I couldn’t find something like this but I wanted to dig deeper into the topic, so I made one. I hope you enjoyed the article. 😉
+This little script will remove all the unnecessary slices from the framework, so you’ll be able to submit your app via iTunesConnect, without any issues. (ha-ha-ha. 😅)
NOTE: You have to add this last script to your application’s build phases.
If you want to get familiar with the tools behind the scenes, this article will help you with the basics. I couldn’t find something like this but I wanted to dig deeper into the topic, so I made one. I hope you enjoyed the article. 😉
Public Swift language attrib print("c") } c() -
The @effects attribute describes how a function affects “the state of the world”. More practically how the optimizer can modify the program based on information that is provided by the attribute.
You can find the corresponding docs here.
@effects(readonly) func foo() { /*...*/ }
+@inlinable is the future (@_inlineable) by Marcin Krzyzanowskim 👏
The @effects attribute describes how a function affects “the state of the world”. More practically how the optimizer can modify the program based on information that is provided by the attribute.
You can find the corresponding docs here.
@effects(readonly) func foo() { /*...*/ }
Basically you can force inlining with the @_transparent attribute, but please read the unofficial documentation for more info.
@_transparent
func example() {
print("example")
diff --git a/docs/get-started-with-the-fluent-orm-framework-in-vapor-4/index.html b/docs/get-started-with-the-fluent-orm-framework-in-vapor-4/index.html
index 68e8f62..de5e5e9 100644
--- a/docs/get-started-with-the-fluent-orm-framework-in-vapor-4/index.html
+++ b/docs/get-started-with-the-fluent-orm-framework-in-vapor-4/index.html
@@ -108,7 +108,7 @@ Get started with the Fluent ORM framework in Vapor 4
Learn how to use the Fluent ORM framework. Migrations, schemas, relations powered by PostgreSQL, written in Swift.
- NOTE: If you want to learn Fluent, but you don’t have a working PostgreSQL installation, you should check my tutorial about how to install and use pgSQL before you start reading this one.
Using the Fluent ORM framework
The beauty of an ORM framework is that it hides the complexity of the underlying database layer. Fluent 4 comes with multiple database driver implementations, this means that you can easily replace the recommended PostgreSQL driver with SQLite, MySQL or MongoDB if you want. MariaDB is also supported through the MySQL driver.
If you are using the SQLite database driver you might have to install the corresponding package (brew install sqlite) if you run into the following error: “missing required module ‘CSQLite’”. 😊
In this tutorial we’ll use PostgreSQL, since that’s the new default driver in Vapor 4. First you have to create a database, next we can start a new Vapor project & write some Swift code using Fluent. If you create a new project using the toolbox (vapor new myProject) you’ll be asked which database driver to use. If you are creating a project from scratch you can alter the Package.swift file:
// swift-tools-version:5.2
+ NOTE: If you want to learn Fluent, but you don’t have a working PostgreSQL installation, you should check my tutorial about how to install and use pgSQL before you start reading this one.
Using the Fluent ORM framework
The beauty of an ORM framework is that it hides the complexity of the underlying database layer. Fluent 4 comes with multiple database driver implementations, this means that you can easily replace the recommended PostgreSQL driver with SQLite, MySQL or MongoDB if you want. MariaDB is also supported through the MySQL driver.
If you are using the SQLite database driver you might have to install the corresponding package (brew install sqlite) if you run into the following error: “missing required module ‘CSQLite’”. 😊
In this tutorial we’ll use PostgreSQL, since that’s the new default driver in Vapor 4. First you have to create a database, next we can start a new Vapor project & write some Swift code using Fluent. If you create a new project using the toolbox (vapor new myProject) you’ll be asked which database driver to use. If you are creating a project from scratch you can alter the Package.swift file:
// swift-tools-version:5.2
import PackageDescription
let package = Package(
@@ -150,7 +150,7 @@ Get started with the Fluent ORM framework in Vapor 4
//...
}
Create a new .env.development file in the project directory with the following contents:
DB_URL=postgres://myuser:mypass@localhost:5432/mydb
-
You can also configure the driver using other methods, but I personally prefer this approach, since it’s very easy and you can also put other specific environmental variables right next to the DB_URL.
NOTE: You can also use the .env file in production mode to set your environmental variables.
Run the application, but first make sure that the current working directory is set properly, read more about this in my previous tutorial about the leaf templating engine.
Well done, you have a working project that connects to the pgSQL server using Fluent. 🚀
Model definition
The official documentation pretty much covers all the important concepts, so it’s definitely worth a read. In this section, I’m only going to focus on some of the “missing parts”.
The API template sample code comes with a Todo model which is pretty much a good starting point for us.
Field keys
Field keys are available from the 5th major beta version of Fluent 4. Long story short, you don’t have to repeat yourself anymore, but you can define a key for each and every database field. As a gratis you never have to do the same for id fields, since fluent has built-in support for identifiers.
extension FieldKey {
+
You can also configure the driver using other methods, but I personally prefer this approach, since it’s very easy and you can also put other specific environmental variables right next to the DB_URL.
NOTE: You can also use the .env file in production mode to set your environmental variables.
Run the application, but first make sure that the current working directory is set properly, read more about this in my previous tutorial about the leaf templating engine.
Well done, you have a working project that connects to the pgSQL server using Fluent. 🚀
Model definition
The official documentation pretty much covers all the important concepts, so it’s definitely worth a read. In this section, I’m only going to focus on some of the “missing parts”.
The API template sample code comes with a Todo model which is pretty much a good starting point for us.
Field keys
Field keys are available from the 5th major beta version of Fluent 4. Long story short, you don’t have to repeat yourself anymore, but you can define a key for each and every database field. As a gratis you never have to do the same for id fields, since fluent has built-in support for identifiers.
extension FieldKey {
static var title: Self { "title" }
}
@@ -241,7 +241,7 @@ Get started with the Fluent ORM framework in Vapor 4
// migration
.field(.labels, .int, .required)
-
NOTE: There is a nice Option protocol OptionSet
Storing dates
Fluent can also store dates and times and convert them back-and-forth using the built-in Date object from Foundation. You just have to choose between the .date or .datetime storage types. You should go with the first one if you don’t care about the hours, minutes or seconds. The second one is good if you simply want to save the day, month and year. 💾
WARN: You should always go with the exact same TimeZone when you save / fetch dates from the database. When you save a date object that is in UTC, next time if you want to filter those objects and you use a different time zone (e.g. PDT), you’ll get back a bad set of results.
Here is the final example of our Todo model including the migration script:
// model definition
+
NOTE: There is a nice Option protocol OptionSet
Storing dates
Fluent can also store dates and times and convert them back-and-forth using the built-in Date object from Foundation. You just have to choose between the .date or .datetime storage types. You should go with the first one if you don’t care about the hours, minutes or seconds. The second one is good if you simply want to save the day, month and year. 💾
WARN: You should always go with the exact same TimeZone when you save / fetch dates from the database. When you save a date object that is in UTC, next time if you want to filter those objects and you use a different time zone (e.g. PDT), you’ll get back a bad set of results.
Here is the final example of our Todo model including the migration script:
// model definition
final class Todo: Model, Content {
static let schema = "todos"
@@ -311,7 +311,7 @@ Get started with the Fluent ORM framework in Vapor 4
return database.schema(Todo.schema).delete()
}
}
-
One more thing…
Nested fields & compound fields
Sometimes you might need to save additional structured data, but you don’t want to introduce a relation (e.g. attributes with different keys, values). This is when the @NestedField property wrapper comes extremely handy. I won’t include here an example, since I had no time to try this feature yet, but you can read more about it here with a working sample code.
The difference between a @CompoundField and a @NestedField is that a compound field is stored as a flat top level field in the database, but the other will be stored as a nested object.
NOTE: Sets are now compatible with the array database type, you can use them like this: .field(.mySetField, .array(of: .string), .required)
I think we pretty much covered everything that you’ll need in order to create DB entities. We’ll have a quick detour here before we get into relations. 🚧
Schemas & migrations
The Todo object is more or less ready to use, but this is just one part of the whole story. We still need to create the actual database table that can store our objects in PostgreSQL. In order to create the DB schema based on our Swift code, we have to run the migration command.
Migration is the process of creating, updating or deleting one or more database tables. In other words, everything that alters the database schema is a migration. You should know that you can register multiple migration scripts and Vapor will run them always in the order they were added.
NOTE: The name of your database table & the fields are declared in your model. The schema is the name of the table, and the property wrappers are containing the name of each field.
Nowadays I prefer to use a semantic version suffix for all my migration objects, this is really handy because I don’t have to think too much about the naming conventions, migration_v1_0_0 is always the create operation, everything comes after this version is just an altering the schema.
You can implement a var name: String { "custom-migration-name" } property inside the migration struct / class, so you don’t have to put special characters into your object’s name
WARN: You should be careful with relations! If you are trying to use a table with a field as a foreign key you have to make sure that the referenced object already exists, otherwise it’ll fail.
During the first migration Fluent will create an internal lookup table named _fluent_migrations. The migration system is using this table to detect which migrations were already performed and what needs to be done next time you run the migrate command.
In order to perform a migration you can launch the Run target with the migrate argument. If you pass the --auto-migrate flag you don’t have to confirm the migration process. Be careful. 😳
swift run Run migrate
+
One more thing…
Nested fields & compound fields
Sometimes you might need to save additional structured data, but you don’t want to introduce a relation (e.g. attributes with different keys, values). This is when the @NestedField property wrapper comes extremely handy. I won’t include here an example, since I had no time to try this feature yet, but you can read more about it here with a working sample code.
The difference between a @CompoundField and a @NestedField is that a compound field is stored as a flat top level field in the database, but the other will be stored as a nested object.
NOTE: Sets are now compatible with the array database type, you can use them like this: .field(.mySetField, .array(of: .string), .required)
I think we pretty much covered everything that you’ll need in order to create DB entities. We’ll have a quick detour here before we get into relations. 🚧
Schemas & migrations
The Todo object is more or less ready to use, but this is just one part of the whole story. We still need to create the actual database table that can store our objects in PostgreSQL. In order to create the DB schema based on our Swift code, we have to run the migration command.
Migration is the process of creating, updating or deleting one or more database tables. In other words, everything that alters the database schema is a migration. You should know that you can register multiple migration scripts and Vapor will run them always in the order they were added.
NOTE: The name of your database table & the fields are declared in your model. The schema is the name of the table, and the property wrappers are containing the name of each field.
Nowadays I prefer to use a semantic version suffix for all my migration objects, this is really handy because I don’t have to think too much about the naming conventions, migration_v1_0_0 is always the create operation, everything comes after this version is just an altering the schema.
You can implement a var name: String { "custom-migration-name" } property inside the migration struct / class, so you don’t have to put special characters into your object’s name
WARN: You should be careful with relations! If you are trying to use a table with a field as a foreign key you have to make sure that the referenced object already exists, otherwise it’ll fail.
During the first migration Fluent will create an internal lookup table named _fluent_migrations. The migration system is using this table to detect which migrations were already performed and what needs to be done next time you run the migrate command.
In order to perform a migration you can launch the Run target with the migrate argument. If you pass the --auto-migrate flag you don’t have to confirm the migration process. Be careful. 😳
swift run Run migrate
You can revert the last batch of migrations by running the command with the –revert flag.
swift run Run migrate --revert
Here is a quick example how to run multiple schema updates by using flatten function. This migration simply removes the existing title field, and creates new unique name field.
extension FieldKey {
static var name: Self { "name" }
@@ -353,7 +353,7 @@ Get started with the Fluent ORM framework in Vapor 4
Batch delete records
You can query all the required records using filters and call the .delete() method on them.
Todo.query(on: req.db)
.filter(\.$status == .completed)
.delete()
-
How to update or delete a single record?
If you know the object identifier it’s pretty simple, the Model protocol has a find method for this purpose. Otherwise you can query the required object and request the first one.
NOTE: Fluent is asynchronous by default, this means that you have to work a lot with Futures and Promises. You can read my tutorial for beginners about promises in Swift.
You can use the .map or .flatMap methods to perform the necessary actions & return a proper response. The .unwrap function is quite handy, since you don’t have to unwrap optionals by hand in the other blocks. Block based syntax = you have to deal with memory management. 💩
// update an existing record (find by uuid)
+
How to update or delete a single record?
If you know the object identifier it’s pretty simple, the Model protocol has a find method for this purpose. Otherwise you can query the required object and request the first one.
NOTE: Fluent is asynchronous by default, this means that you have to work a lot with Futures and Promises. You can read my tutorial for beginners about promises in Swift.
You can use the .map or .flatMap methods to perform the necessary actions & return a proper response. The .unwrap function is quite handy, since you don’t have to unwrap optionals by hand in the other blocks. Block based syntax = you have to deal with memory management. 💩
// update an existing record (find by uuid)
_ = Todo.find(uuid, on: req.db)
.unwrap(or: Abort(.notFound))
.flatMap { todo -> EventLoopFuture<Void> in
@@ -581,7 +581,7 @@ Get started with the Fluent ORM framework in Vapor 4
database.schema(Tag.schema).delete(),
database.schema(TodoTags.schema).delete(),
//...
-
The only new thing here is the siblings property wrapper which defines the connection between the two tables. It’s awesome that Fluent can handle these complex relations in such a nice way.
WARN: The code snippet below is for educational purposes only, you should never use the .wait() method in a real-world application, use futures & promises instead.
Finally we’re able to tag our todo items, plus we can mark some of them as important. 🎊
let defaultGroup = try Group.query(on: app.db).first().wait()!
+
The only new thing here is the siblings property wrapper which defines the connection between the two tables. It’s awesome that Fluent can handle these complex relations in such a nice way.
WARN: The code snippet below is for educational purposes only, you should never use the .wait() method in a real-world application, use futures & promises instead.
Finally we’re able to tag our todo items, plus we can mark some of them as important. 🎊
let defaultGroup = try Group.query(on: app.db).first().wait()!
let shoplist = Group(name: "Shoplist")
let project = Group(name: "Awesome Fluent project")
diff --git a/docs/how-to-build-macos-apps-using-only-the-swift-package-manager/index.html b/docs/how-to-build-macos-apps-using-only-the-swift-package-manager/index.html
index 71cf624..e404998 100644
--- a/docs/how-to-build-macos-apps-using-only-the-swift-package-manager/index.html
+++ b/docs/how-to-build-macos-apps-using-only-the-swift-package-manager/index.html
@@ -158,7 +158,7 @@ Swift scripts and macOS apps
Swift
task.resume()
dispatchMain()
If you call this example with a URL that can return a list of todos it’ll print a nice list of the items.
./main.swift https://jsonplaceholder.typicode.com/todos
-
Yes, you can say that this script is completely useless, but in my opinion it’s an amazing demo app, since it covers how to check command line arguments (CommandLine.arguments), it also shows you how to wait (dispatchMain) for an async task, such as a HTTP call through the network using the URLSession API to finish and exit using the right method when something fails (fatalError) or if you reach the end of execution (exit(0)). Just a few lines of code, but it contains so much info.
NOTE: Have you noticed the new shebang? If you have multiple Swift versions installed on your system, you can use the env shebang to go with the first one that’s available in your PATH.
It’s not just Foundation, but you can import AppKit or even SwiftUI. Well, not under Linux of course, since those frameworks are only available for macOS plus you will need Xcode installed on your system, since some stuff in Swift the toolchain is still tied to the IDE, but why? 😢
Anyway, back to the topic, here’s the boilerplate code for a macOS application Swift script that can be started from the Terminal with one simple ./main.swift command and nothing more.
#!/usr/bin/env swift
+
Yes, you can say that this script is completely useless, but in my opinion it’s an amazing demo app, since it covers how to check command line arguments (CommandLine.arguments), it also shows you how to wait (dispatchMain) for an async task, such as a HTTP call through the network using the URLSession API to finish and exit using the right method when something fails (fatalError) or if you reach the end of execution (exit(0)). Just a few lines of code, but it contains so much info.
NOTE: Have you noticed the new shebang? If you have multiple Swift versions installed on your system, you can use the env shebang to go with the first one that’s available in your PATH.
It’s not just Foundation, but you can import AppKit or even SwiftUI. Well, not under Linux of course, since those frameworks are only available for macOS plus you will need Xcode installed on your system, since some stuff in Swift the toolchain is still tied to the IDE, but why? 😢
Anyway, back to the topic, here’s the boilerplate code for a macOS application Swift script that can be started from the Terminal with one simple ./main.swift command and nothing more.
#!/usr/bin/env swift
import AppKit
import SwiftUI
diff --git a/docs/how-to-build-swiftui-apps-using-viper/index.html b/docs/how-to-build-swiftui-apps-using-viper/index.html
index 6651bee..8750087 100644
--- a/docs/how-to-build-swiftui-apps-using-viper/index.html
+++ b/docs/how-to-build-swiftui-apps-using-viper/index.html
@@ -108,7 +108,7 @@ How to build SwiftUI apps using VIPER?
In this tutorial I'll show you how to combine SwiftUI with the VIPER architecture in a real world iOS application example.
- SwiftUI - the new kid on the block
There are literally hundreds of SwiftUI tutorials around the web, but I was only able to find just one or two that focuses on real world use cases instead of the smaller details like how to configure / make X in SwiftUI. Nice tutorials @mecid keep it up!
I also had my own “struggle” with SwiftUI, because my collection view framework is structured exactly the same way as you write SwiftUI code. After WWDC I was like, hell no! I’m doing the same method for months now, so why should I care? I started to believe that some Apple engineers are reading my blog. 😂
Anyway I knew at day zero that a crazy amount of new SwiftUI tutorials will arrive and everyone will be hyped about the new declarative UI framework, but honestly I already had my universal toolkit for this purpose. That’s why I don’t wanted to write about it. Honestly I still love Combine much more than SwiftUI. I’m also quite disappointed since CollectionView is completely missing from the framework.
Finally, just because what the heck lets try new things and I was curious about how SwiftUI can fit into my app building methodology I started to create a new VIPER template based on those kind of views. I also wanted to make a useful, scalable, modular real world application example using the new framework, which is up-to-date. A lot has changed in SwiftUI during the Xcode 11 beta period, so that’s why I’m only publishing this tutorial now. Enough chatter, shouldn’t we code already? 😛
Learn a modern VIPER architecture
I’ve spent my last two years using the VIPER architecture. Some people say “it’s way too complex” or “it’s not a good fit for small teams”. I can only tell them one word:
Bullshit!
I believe that I’ve created a modern & relatively simple pattern that can be used for literally anything. Learning VIPER will definitely improve your code quality thanks to the clean architecture and the SOLID principles. You’ll have a better understanding of how smaller pieces can work together and communicate with each other.
Isolated smaller components can speed up development, because you just have to work on a little piece at once, plus you can create tests for that particular thing, which is a huge win for testability & code coverage (you don’t have to run your app all the time if you want to test something, you can work on the module you just need).
I’m usually working with a really simple code generator to fire up new modules, this way I can save a lot of time. If you have to work alone on a project the module generator and the predefined structure can even save you some more time. Also you really can’t mess up things or end up with massive files if you are following the basic VIPER rules. I’ll teach you my method in about 10 minutes. ⏰
What the heck is VIPER anyway?
If you never heard about VIPER before, the first thing you should know is that a VIPER module contains the following components:
- View = UIViewController subclass or SwiftUI View
- Interactor = Provides the required data in the proper format
- Presenter = UI independent business logic (what to do exactly)
- Entity = Data objects (sometimes it’s missing from the module)
- Router = Builds up the view controller hierarchy (show, present, dismiss, etc)
I always have a module file next to these ones where I define a module builder which builds up the whole thing from the components above and in that file I also define the module specific protocols. I usually name these protocols as interfaces they make it possible that any of the components can be replaced using dependency injection. This way we can test anything by using mocked objects in our unit tests.
NOTE: Some say that a VIPER module with a Builder is called VIPER/B. I think the module file is an ideal place to store your module builder object, the module interfaces and the module delegate if you need one.
Protocol oriented VIPER architecture
So the key is the 6 main protocol that connects View-Interactor-Presenter-Router. These protocols ensure that none of the VIPER components can see more than it’s required. If you go back to my first tutorial you’ll see that I made a mistake there. The thing is that you can call a method on the router through the presenter from the view, which is bad. This new approach fixes that issue. 🐛
View-to-Presenter
+ SwiftUI - the new kid on the block
There are literally hundreds of SwiftUI tutorials around the web, but I was only able to find just one or two that focuses on real world use cases instead of the smaller details like how to configure / make X in SwiftUI. Nice tutorials @mecid keep it up!
I also had my own “struggle” with SwiftUI, because my collection view framework is structured exactly the same way as you write SwiftUI code. After WWDC I was like, hell no! I’m doing the same method for months now, so why should I care? I started to believe that some Apple engineers are reading my blog. 😂
Anyway I knew at day zero that a crazy amount of new SwiftUI tutorials will arrive and everyone will be hyped about the new declarative UI framework, but honestly I already had my universal toolkit for this purpose. That’s why I don’t wanted to write about it. Honestly I still love Combine much more than SwiftUI. I’m also quite disappointed since CollectionView is completely missing from the framework.
Finally, just because what the heck lets try new things and I was curious about how SwiftUI can fit into my app building methodology I started to create a new VIPER template based on those kind of views. I also wanted to make a useful, scalable, modular real world application example using the new framework, which is up-to-date. A lot has changed in SwiftUI during the Xcode 11 beta period, so that’s why I’m only publishing this tutorial now. Enough chatter, shouldn’t we code already? 😛
Learn a modern VIPER architecture
I’ve spent my last two years using the VIPER architecture. Some people say “it’s way too complex” or “it’s not a good fit for small teams”. I can only tell them one word:
Bullshit!
I believe that I’ve created a modern & relatively simple pattern that can be used for literally anything. Learning VIPER will definitely improve your code quality thanks to the clean architecture and the SOLID principles. You’ll have a better understanding of how smaller pieces can work together and communicate with each other.
Isolated smaller components can speed up development, because you just have to work on a little piece at once, plus you can create tests for that particular thing, which is a huge win for testability & code coverage (you don’t have to run your app all the time if you want to test something, you can work on the module you just need).
I’m usually working with a really simple code generator to fire up new modules, this way I can save a lot of time. If you have to work alone on a project the module generator and the predefined structure can even save you some more time. Also you really can’t mess up things or end up with massive files if you are following the basic VIPER rules. I’ll teach you my method in about 10 minutes. ⏰
What the heck is VIPER anyway?
If you never heard about VIPER before, the first thing you should know is that a VIPER module contains the following components:
- View = UIViewController subclass or SwiftUI View
- Interactor = Provides the required data in the proper format
- Presenter = UI independent business logic (what to do exactly)
- Entity = Data objects (sometimes it’s missing from the module)
- Router = Builds up the view controller hierarchy (show, present, dismiss, etc)
I always have a module file next to these ones where I define a module builder which builds up the whole thing from the components above and in that file I also define the module specific protocols. I usually name these protocols as interfaces they make it possible that any of the components can be replaced using dependency injection. This way we can test anything by using mocked objects in our unit tests.
NOTE: Some say that a VIPER module with a Builder is called VIPER/B. I think the module file is an ideal place to store your module builder object, the module interfaces and the module delegate if you need one.
Protocol oriented VIPER architecture
So the key is the 6 main protocol that connects View-Interactor-Presenter-Router. These protocols ensure that none of the VIPER components can see more than it’s required. If you go back to my first tutorial you’ll see that I made a mistake there. The thing is that you can call a method on the router through the presenter from the view, which is bad. This new approach fixes that issue. 🐛
View-to-Presenter
Presenter-to-View
Router-to-Presenter
diff --git a/docs/how-to-call-c-code-from-swift/index.html b/docs/how-to-call-c-code-from-swift/index.html
index afc463f..80705b6 100644
--- a/docs/how-to-call-c-code-from-swift/index.html
+++ b/docs/how-to-call-c-code-from-swift/index.html
@@ -108,7 +108,7 @@ How to call C code from Swift
Interacting with C libraries from the Swift language is really amazing, from this post can learn the most of C interoperability.
- WARN: From Swift 4 there is native support for wrapping C libraries in Swift system module packages. This means that you can easily ship your own system modules, you just have to learn how to use the Swift Package Manager.😅
Bridging header inside Xcode
Let’s fire up Xcode and start a brand new single view app iOS project. Fill out the required fields, and of course choose the Swift language. Next, add a new file and choose the C file template.
After you enter the name and check the also create header file box, Xcode will ask you about the Objective-C bridging header file. Just create it. The name of this file is tricky, because it also supports other C family languages, like pure C or C++, Objective-C and plus-plus. 😉
Let’s create a public header for the C code (factorial.h):
#ifndef factorial_h
+ WARN: From Swift 4 there is native support for wrapping C libraries in Swift system module packages. This means that you can easily ship your own system modules, you just have to learn how to use the Swift Package Manager.😅
Bridging header inside Xcode
Let’s fire up Xcode and start a brand new single view app iOS project. Fill out the required fields, and of course choose the Swift language. Next, add a new file and choose the C file template.
After you enter the name and check the also create header file box, Xcode will ask you about the Objective-C bridging header file. Just create it. The name of this file is tricky, because it also supports other C family languages, like pure C or C++, Objective-C and plus-plus. 😉
Let’s create a public header for the C code (factorial.h):
#ifndef factorial_h
#define factorial_h
#include <stdio.h>
diff --git a/docs/how-to-create-reusable-views-for-modern-collection-views/index.html b/docs/how-to-create-reusable-views-for-modern-collection-views/index.html
index f47ad45..69c3d92 100644
--- a/docs/how-to-create-reusable-views-for-modern-collection-views/index.html
+++ b/docs/how-to-create-reusable-views-for-modern-collection-views/index.html
@@ -377,7 +377,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/how-to-create-your-first-website-using-vapor-4-and-leaf/index.html b/docs/how-to-create-your-first-website-using-vapor-4-and-leaf/index.html
index 2218da9..3fc4074 100644
--- a/docs/how-to-create-your-first-website-using-vapor-4-and-leaf/index.html
+++ b/docs/how-to-create-your-first-website-using-vapor-4-and-leaf/index.html
@@ -214,7 +214,7 @@ Project setup
Start a brand new project by using t
return eventLoop.future(error: LeafError(.noTemplateExists(template)))
}
}
-
Anyway, this is a more advanced topic, we’re good to go with a single source, also I highly recommend using a .html extension instead of leaf, so Xcode can give us partial syntax highlight for our Leaf files. Now we are going to make our very first Leaf template file. 🍃
NOTE: You can enable basic syntax highlighting for .leaf files in Xcode by choosing the Editor ▸ Syntax Coloring ▸ HTML menu item. Unfortunately if you close Xcode you have to do this again and again for every single Leaf file.
Create a new file under the Resources/Views directory called index.html.
<!DOCTYPE html>
+
Anyway, this is a more advanced topic, we’re good to go with a single source, also I highly recommend using a .html extension instead of leaf, so Xcode can give us partial syntax highlight for our Leaf files. Now we are going to make our very first Leaf template file. 🍃
NOTE: You can enable basic syntax highlighting for .leaf files in Xcode by choosing the Editor ▸ Syntax Coloring ▸ HTML menu item. Unfortunately if you close Xcode you have to do this again and again for every single Leaf file.
Create a new file under the Resources/Views directory called index.html.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
@@ -304,7 +304,7 @@ Project setup
Start a brand new project by using t
</main>
</body>
</html>
-
Now that’s not the most accurate representation of how the LeafRenderer works, but I hope that it’ll help you to understand this whole define / evaluate syntax thing.
NOTE: You can also use the #evaluate tag instead of calling the block (bodyBlock() vs #evaluate(bodyBlock), these two snippets are essentially the same).
It’s time to render the page template. Again, we don’t have to deal with the bodyBlock, since it’s already defined in the home template, the description value also exists, because we created a new constant using the #let tag. We only have to pass around the title, header and message keys with proper values as context variables for the renderer.
app.get { req in
+
Now that’s not the most accurate representation of how the LeafRenderer works, but I hope that it’ll help you to understand this whole define / evaluate syntax thing.
NOTE: You can also use the #evaluate tag instead of calling the block (bodyBlock() vs #evaluate(bodyBlock), these two snippets are essentially the same).
It’s time to render the page template. Again, we don’t have to deal with the bodyBlock, since it’s already defined in the home template, the description value also exists, because we created a new constant using the #let tag. We only have to pass around the title, header and message keys with proper values as context variables for the renderer.
app.get { req in
req.leaf.render(template: "home", context: [
"title": "My Page",
"header": "This is my own page.",
diff --git a/docs/how-to-download-files-with-urlsession-using-combine-publishers-and-subscribers/index.html b/docs/how-to-download-files-with-urlsession-using-combine-publishers-and-subscribers/index.html
index 78f22ba..23682fd 100644
--- a/docs/how-to-download-files-with-urlsession-using-combine-publishers-and-subscribers/index.html
+++ b/docs/how-to-download-files-with-urlsession-using-combine-publishers-and-subscribers/index.html
@@ -145,7 +145,7 @@ A simple image downloader
Downloading
// do something on the main queue
}
}.resume()
-
It’s also worth to mention if you need to use a different HTTP method (other than GET), send special headers (credentials, accept policies, etc.) or provide extra data in the body, you need to construct an URLRequest object first. You can only send these custom requests using the URLSession APIs.
NOTE: On Apple platforms you are not allowed to use the insecure HTTP protocol anymore. If you want to reach a URL without the secure layer (HTTPS) you have to disable App Transport Security.
The problem with data tasks
What about big files, such as images? Let me show you a few tutorials before we dive in:
- UIImageView, Load UIImage from remote URL
- Loading an image into UIImage asynchronously
- How to load a remote image URL into UIImageView
- How To Downloading Image from server URL on Swift 4?
- Downloading UIImage via AlamofireImage?
- Loading images from URL in Swift
- How do I load an image by URL on iOS device using Swift?
- UIImageView and UIImage. Load Image From Remote URL.
- Asynchronously Loading Images in SwiftUI
- How to load remote image in SwiftUI
- Loading/Downloading image from URL on Swift
With all due respect, I think all of these links above are really bad examples of loading remote images. Sure they do the job, they’re also very easy to implement, but maybe we should cover the whole story… 🤐
For small interactions with remote servers, you can use the URLSessionDataTask class to receive response data into memory (as opposed to using the URLSessionDownloadTask class, which stores the data directly to the file system). A data task is ideal for uses like calling a web service endpoint.
What is difference between URLSessionDataTask vs URLSessionDownloadTask?
If we read the docs carefully, it becomes clear that data task is NOT the right candidate for downloading big assets. That class is designed to request only smaller objects, since the underlying data is going to be loaded into memory. On the other hand the download task saves the content of the response on the disk (instead of memory) and you will receive a local file URL instead of a Data object. Turns out that moving from data tasks to download tasks will have a HUGE impact on your memory consumption. I have some numbers. 📈
I downloaded the following image file (6000x4000px 💾 13,1MB) using both methods. I made a brand new storyboard based Swift 5.1 project. The basic RAM usage was ~52MB, when I fetched the image using the URLSessionDataTask class, the memory usage jumped to ~82MB. Turning the data task into a download task only increased the base memory size by ~4MB (to a total ~56MB), which is a significant improvement.
let url = URL(string: "https://images.unsplash.com/photo-1554773228-1f38662139db")!
+
It’s also worth to mention if you need to use a different HTTP method (other than GET), send special headers (credentials, accept policies, etc.) or provide extra data in the body, you need to construct an URLRequest object first. You can only send these custom requests using the URLSession APIs.
NOTE: On Apple platforms you are not allowed to use the insecure HTTP protocol anymore. If you want to reach a URL without the secure layer (HTTPS) you have to disable App Transport Security.
The problem with data tasks
What about big files, such as images? Let me show you a few tutorials before we dive in:
- UIImageView, Load UIImage from remote URL
- Loading an image into UIImage asynchronously
- How to load a remote image URL into UIImageView
- How To Downloading Image from server URL on Swift 4?
- Downloading UIImage via AlamofireImage?
- Loading images from URL in Swift
- How do I load an image by URL on iOS device using Swift?
- UIImageView and UIImage. Load Image From Remote URL.
- Asynchronously Loading Images in SwiftUI
- How to load remote image in SwiftUI
- Loading/Downloading image from URL on Swift
With all due respect, I think all of these links above are really bad examples of loading remote images. Sure they do the job, they’re also very easy to implement, but maybe we should cover the whole story… 🤐
For small interactions with remote servers, you can use the URLSessionDataTask class to receive response data into memory (as opposed to using the URLSessionDownloadTask class, which stores the data directly to the file system). A data task is ideal for uses like calling a web service endpoint.
What is difference between URLSessionDataTask vs URLSessionDownloadTask?
If we read the docs carefully, it becomes clear that data task is NOT the right candidate for downloading big assets. That class is designed to request only smaller objects, since the underlying data is going to be loaded into memory. On the other hand the download task saves the content of the response on the disk (instead of memory) and you will receive a local file URL instead of a Data object. Turns out that moving from data tasks to download tasks will have a HUGE impact on your memory consumption. I have some numbers. 📈
I downloaded the following image file (6000x4000px 💾 13,1MB) using both methods. I made a brand new storyboard based Swift 5.1 project. The basic RAM usage was ~52MB, when I fetched the image using the URLSessionDataTask class, the memory usage jumped to ~82MB. Turning the data task into a download task only increased the base memory size by ~4MB (to a total ~56MB), which is a significant improvement.
let url = URL(string: "https://images.unsplash.com/photo-1554773228-1f38662139db")!
// data task
URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
@@ -358,7 +358,7 @@ A simple image downloader
Downloading
.subscribe(DownloadTaskSubscriber())
}
}
-
This is really nice. We can download a file using our custom Combine based URLSession extension.
NOTE: Don’t forget to store the AnyCancellable pointer otherwise the entire Combine operation will be deallocated way before you could receive anything from the chain / stream.
Putting everything together
I promised a working image downloader, so let me explain the whole flow. We have a custom download task publisher that’ll save our remove image file locally and returns a tuple with the file URL and the response. ✅
Next I’m going to simply assume that there was a valid image behind the URL, and the server returned a valid response, so I’m going to map the publisher’s output to an UIImage object. I’m also going to replace any kind of error with a fallback image value. In a real-world application, you should always do some extra checkings on the URLResponse object, but for the sake of simplicity I’ll skip that for now.
The last thing is to update our image view with the returned image. Since this is a UI task it should happen on the main thread, so we have to use the receive(on:) operation to switch context. If you want to learn more about schedulers in the Combine framework you should read Vadim Bulavin’s article. It’s a gem. 💎
WARN: If you are not receiving values on certain appleOS versions, that’s might because there was a change in Combine around December, 2019. You should check these links: link1, link2
Anyway, here’s the final Swift code for a possible image download operation, simple & declarative. 👍
class ViewController: UIViewController {
+
This is really nice. We can download a file using our custom Combine based URLSession extension.
NOTE: Don’t forget to store the AnyCancellable pointer otherwise the entire Combine operation will be deallocated way before you could receive anything from the chain / stream.
Putting everything together
I promised a working image downloader, so let me explain the whole flow. We have a custom download task publisher that’ll save our remove image file locally and returns a tuple with the file URL and the response. ✅
Next I’m going to simply assume that there was a valid image behind the URL, and the server returned a valid response, so I’m going to map the publisher’s output to an UIImage object. I’m also going to replace any kind of error with a fallback image value. In a real-world application, you should always do some extra checkings on the URLResponse object, but for the sake of simplicity I’ll skip that for now.
The last thing is to update our image view with the returned image. Since this is a UI task it should happen on the main thread, so we have to use the receive(on:) operation to switch context. If you want to learn more about schedulers in the Combine framework you should read Vadim Bulavin’s article. It’s a gem. 💎
WARN: If you are not receiving values on certain appleOS versions, that’s might because there was a change in Combine around December, 2019. You should check these links: link1, link2
Anyway, here’s the final Swift code for a possible image download operation, simple & declarative. 👍
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
diff --git a/docs/how-to-launch-a-macos-app-at-login/index.html b/docs/how-to-launch-a-macos-app-at-login/index.html
index 5115520..7206e4c 100644
--- a/docs/how-to-launch-a-macos-app-at-login/index.html
+++ b/docs/how-to-launch-a-macos-app-at-login/index.html
@@ -108,7 +108,7 @@ How to launch a macOS app at login?
In this tutorial I'll show you how to launch a completely sandboxed macOS application on system startup written in Swift.
- WARN: Update: you should simply add the LaunchAtLogin library to your project. It’ll take care of everything and it has some other cool utility features.
Project setup
Let’s start this tutorial by creating a new Xcode project with a macOS app template. Name it for example MainApplication, use storyboards and of course select Swift as the default language, we don’t need tests for this project at all.
Now that we have the main application target, there is this nice little function available called SMLoginItemSetEnabled. With that function you can register an application bundle identifier to auto start when the user logs in, but you can not register your own app identifier. Sounds crazy, huh? 😜
You can register a bundle identifier embedded into your main application to get auto-launched by the system. To do this you will have to create a new launcher application which will be launched later by your main application.
You also have to code sign your application with your Developer ID, otherwise it won’t start after you log in to macOS. Sandboxing is a crucial part of the process, so make sure that you follow every instruction carefully.
Targets & configurations
Create a new target inside your current project. Name this new target for example LauncherApplication. Enable sandbox and code signing for both targets (main and launcher apps) under the Signing & Capabilities tab. For the LauncherApplication target in the build settings set skip install to yes.

For the launcher app add a new entry to the Info.plist file: Application is background only with the value: yes. This will set your application as a background app, we don’t really need user interface for a launcher tool, right?

Add a new copy file build phase to your main application target to copy your launcher application into the bundle. The destination should be wrapper and the subpath should be Contents/Library/LoginItems.

Link the ServiceManagement.framework to your main application and double check that the launcher app is embedded into your main application.

From the LauncherApplication‘s storyboard file delete your window and your view controller, also you can remove the ViewController.swift file from this target. This is a background app after all, so we don’t need these stupid things to lay around.
Creating the launcher programmatically
Somewhere in your main application you have to register your launcher application’s identifier. When your main application starts you have to kill the launcher application if it’s still running. You can do this by sending a notification to that specific app with the NSDistributedNotificationCenter class.
import Cocoa
+ WARN: Update: you should simply add the LaunchAtLogin library to your project. It’ll take care of everything and it has some other cool utility features.
Project setup
Let’s start this tutorial by creating a new Xcode project with a macOS app template. Name it for example MainApplication, use storyboards and of course select Swift as the default language, we don’t need tests for this project at all.
Now that we have the main application target, there is this nice little function available called SMLoginItemSetEnabled. With that function you can register an application bundle identifier to auto start when the user logs in, but you can not register your own app identifier. Sounds crazy, huh? 😜
You can register a bundle identifier embedded into your main application to get auto-launched by the system. To do this you will have to create a new launcher application which will be launched later by your main application.
You also have to code sign your application with your Developer ID, otherwise it won’t start after you log in to macOS. Sandboxing is a crucial part of the process, so make sure that you follow every instruction carefully.
Targets & configurations
Create a new target inside your current project. Name this new target for example LauncherApplication. Enable sandbox and code signing for both targets (main and launcher apps) under the Signing & Capabilities tab. For the LauncherApplication target in the build settings set skip install to yes.

For the launcher app add a new entry to the Info.plist file: Application is background only with the value: yes. This will set your application as a background app, we don’t really need user interface for a launcher tool, right?

Add a new copy file build phase to your main application target to copy your launcher application into the bundle. The destination should be wrapper and the subpath should be Contents/Library/LoginItems.

Link the ServiceManagement.framework to your main application and double check that the launcher app is embedded into your main application.

From the LauncherApplication‘s storyboard file delete your window and your view controller, also you can remove the ViewController.swift file from this target. This is a background app after all, so we don’t need these stupid things to lay around.
Creating the launcher programmatically
Somewhere in your main application you have to register your launcher application’s identifier. When your main application starts you have to kill the launcher application if it’s still running. You can do this by sending a notification to that specific app with the NSDistributedNotificationCenter class.
import Cocoa
import ServiceManagement
extension Notification.Name {
diff --git a/docs/how-to-make-a-swift-framework/index.html b/docs/how-to-make-a-swift-framework/index.html
index 9e05792..7ee6f56 100644
--- a/docs/how-to-make-a-swift-framework/index.html
+++ b/docs/how-to-make-a-swift-framework/index.html
@@ -108,7 +108,7 @@ How to make a Swift framework?
Creating a Swift framework shouldn't be hard. This tutorial will help you making a universal framework for complex projects.
- What is a framework?
A framework is a hierarchical directory that encapsulates shared resources, such as a dynamic shared library, nib files, image files, localized strings, header files, and reference documentation in a single package.
So in a nutshell, a framework is a highly reusable component for your apps.
How to make it?
There is an article about Xcode conventions which will help you organize your projects, you should check that first, if you haven’t before.
Traditional way
There is a traditional way to make a framework in Xcode. I’m going to create a shared framework for all the apple platforms (iOS, macOS, tvOS, watchOS), which is going to be capable of logging things to the standard console.
Let’s make the project:
- Create a new project using one of the framework targets
- Follow the instructions fill & name all the fields
- Add all the other platform framework targets
- Rename all targets according to the platform names
Now in Finder:
- Create a Sources folder and move all the Swift and header files there
- Create an Assets folder with platforms subfolders
- Move all the Info.plist files into the correct platfrom subdirectory
- Create a Tests folder and move test files there
Back to Xcode:
- Remove every group and add the new Folders from Finder
- Check that every target has the correct files (framework & tests)
- Inside the header file, replace UIKit depencency with Foundation
The goal is to achieve a structure somewhat like this:

Project settings:
- Select the correct plist files for the targets
- Set your bundle identifiers (use my conventions)
- Setup platform versions (advice: support 1 older version too)
- Setup the plist files for the tests from the build settings pane
- Set the product name (Console) in your framework build settings
- Check your build phases and add the public header file.
Scheme settings:
- Go to the scheme settings and setup shared schemes for the frameworks
- Gather coverage data if you need it
- Write your framework you can use Swift “macros” to detect platforms
NOTE: There is a flag in Xcode to allow app extension API only, if you are embedding your framework inside an application extension it should be enabled!
Congratulations, now you have your brand new Swift framework made in the traditional way. Let’s continue with a neat trick.
Universal cross platform framework
It is possible to create a multiplatform single scheme Xcode project with cross platform support for every platform, but it’s not recommended because it’s a hack. However multiple open source libraries do the same way, so why shouldn’t we.
- Delete all the targets, schemes, except macOS!!!
- Rename the remaining target, scheme (we don’t need platform names)
- Use the project configuration file, set the xcconfig on the project
- Delete Info.plist files, use one for the framework and one for the tests
- Rename bundle identifier (we don’t need platform names there too)
WARN: States can be mixed up if you are building for multiple platforms, however this is a nice clean way to support every platforms, without duplications.
How to use a Swift framework?
Embedding your framework is the most straightforward thing to do. You can simply drag the framework project to another Xcode project, the only thing left to do is to the embedded the framework into the application. You can go to the embedded binaries section inside the general project info tab and add the framework as a dependency.
Swift Package Manager
With SPM, you have to make a Package.swift file first, then you’ll be able to build your targets with the swift build command. Now that Xcode supports the Swift Package Manager, it’s really easy to integrate third party frameworks by using it.
You can download the final framework examples from GitHub.
Make sure that you don’t miss out my deep dive into swift frameworks post.
+ What is a framework?
A framework is a hierarchical directory that encapsulates shared resources, such as a dynamic shared library, nib files, image files, localized strings, header files, and reference documentation in a single package.
So in a nutshell, a framework is a highly reusable component for your apps.
How to make it?
There is an article about Xcode conventions which will help you organize your projects, you should check that first, if you haven’t before.
Traditional way
There is a traditional way to make a framework in Xcode. I’m going to create a shared framework for all the apple platforms (iOS, macOS, tvOS, watchOS), which is going to be capable of logging things to the standard console.
Let’s make the project:
- Create a new project using one of the framework targets
- Follow the instructions fill & name all the fields
- Add all the other platform framework targets
- Rename all targets according to the platform names
Now in Finder:
- Create a Sources folder and move all the Swift and header files there
- Create an Assets folder with platforms subfolders
- Move all the Info.plist files into the correct platfrom subdirectory
- Create a Tests folder and move test files there
Back to Xcode:
- Remove every group and add the new Folders from Finder
- Check that every target has the correct files (framework & tests)
- Inside the header file, replace UIKit depencency with Foundation
The goal is to achieve a structure somewhat like this:

Project settings:
- Select the correct plist files for the targets
- Set your bundle identifiers (use my conventions)
- Setup platform versions (advice: support 1 older version too)
- Setup the plist files for the tests from the build settings pane
- Set the product name (Console) in your framework build settings
- Check your build phases and add the public header file.
Scheme settings:
- Go to the scheme settings and setup shared schemes for the frameworks
- Gather coverage data if you need it
- Write your framework you can use Swift “macros” to detect platforms
NOTE: There is a flag in Xcode to allow app extension API only, if you are embedding your framework inside an application extension it should be enabled!
Congratulations, now you have your brand new Swift framework made in the traditional way. Let’s continue with a neat trick.
Universal cross platform framework
It is possible to create a multiplatform single scheme Xcode project with cross platform support for every platform, but it’s not recommended because it’s a hack. However multiple open source libraries do the same way, so why shouldn’t we.
- Delete all the targets, schemes, except macOS!!!
- Rename the remaining target, scheme (we don’t need platform names)
- Use the project configuration file, set the xcconfig on the project
- Delete Info.plist files, use one for the framework and one for the tests
- Rename bundle identifier (we don’t need platform names there too)
WARN: States can be mixed up if you are building for multiple platforms, however this is a nice clean way to support every platforms, without duplications.
How to use a Swift framework?
Embedding your framework is the most straightforward thing to do. You can simply drag the framework project to another Xcode project, the only thing left to do is to the embedded the framework into the application. You can go to the embedded binaries section inside the general project info tab and add the framework as a dependency.
Swift Package Manager
With SPM, you have to make a Package.swift file first, then you’ll be able to build your targets with the swift build command. Now that Xcode supports the Swift Package Manager, it’s really easy to integrate third party frameworks by using it.
You can download the final framework examples from GitHub.
Make sure that you don’t miss out my deep dive into swift frameworks post.
diff --git a/docs/how-to-parse-json-in-swift-using-codable-protocol/index.html b/docs/how-to-parse-json-in-swift-using-codable-protocol/index.html
index f9ad288..dfed9c2 100644
--- a/docs/how-to-parse-json-in-swift-using-codable-protocol/index.html
+++ b/docs/how-to-parse-json-in-swift-using-codable-protocol/index.html
@@ -162,7 +162,7 @@ Dependencies
First of all just a few words about de
PlaygroundPage.current.finishExecution()
}
}.resume()
-
As you can see downloading and parsing JSON from the web is a really easy task. This whole code snippet is around 50 lines of code. Of course it’s just a proof of concept, but it works and you don’t need any dependency. It’s pure Swift and Foundation.
NOTE: To save some typing, you can also generate the final objects directly from the JSON structure with these amazing Xcode extensions.
The Codable protocol - which is actually a compound typealias from Encodable & Decodable protocols - makes the process of parsing JSON data in Swift magical. 💫
+
As you can see downloading and parsing JSON from the web is a really easy task. This whole code snippet is around 50 lines of code. Of course it’s just a proof of concept, but it works and you don’t need any dependency. It’s pure Swift and Foundation.
NOTE: To save some typing, you can also generate the final objects directly from the JSON structure with these amazing Xcode extensions.
The Codable protocol - which is actually a compound typealias from Encodable & Decodable protocols - makes the process of parsing JSON data in Swift magical. 💫
diff --git a/docs/how-to-set-up-pgsql-for-fluent-4/index.html b/docs/how-to-set-up-pgsql-for-fluent-4/index.html
index b6d5d97..7dbf7c4 100644
--- a/docs/how-to-set-up-pgsql-for-fluent-4/index.html
+++ b/docs/how-to-set-up-pgsql-for-fluent-4/index.html
@@ -108,7 +108,7 @@ How to set up pgSQL for Fluent 4?
This is a tutorial for beginners about using PostgreSQL. I'll show you how to automatically backup and restore the database.
- NOTE: If you are already familiar with PostgreSQL, but you don’t know much about how to use databases in Vapor, you should read my other tutorial about Fluent for beginners.
A quick intro to PostgreSQL
PostgreSQL is an open source database, it’s available for macOS, Linux and some other operating systems. You can install it by using the de-facto package manager on every platform. 📦
# Linux
+ NOTE: If you are already familiar with PostgreSQL, but you don’t know much about how to use databases in Vapor, you should read my other tutorial about Fluent for beginners.
A quick intro to PostgreSQL
PostgreSQL is an open source database, it’s available for macOS, Linux and some other operating systems. You can install it by using the de-facto package manager on every platform. 📦
# Linux
sudo apt-get install postgresql postgresql-contrib
sudo service postgresql start
# check service status
@@ -156,7 +156,7 @@ How to set up pgSQL for Fluent 4?
\dt
# Describe table structure (will be useful later on)
\d+ <table>
-
You can learn more about SQL commands using this pgSQL tutorial site.
WARN: The command below can completely wipe your database, be extremely careful!
Now you are ready to play around with Fluent, but before we start I’d like to show you some more tips & tricks. During development, things can go wrong and you might need a fresh start for your DB. Here’s how to drop & reinitiate everything. 😱
# Reset database
+
You can learn more about SQL commands using this pgSQL tutorial site.
WARN: The command below can completely wipe your database, be extremely careful!
Now you are ready to play around with Fluent, but before we start I’d like to show you some more tips & tricks. During development, things can go wrong and you might need a fresh start for your DB. Here’s how to drop & reinitiate everything. 😱
# Reset database
\c mydb
drop schema public cascade;
create schema public;
diff --git a/docs/how-to-use-a-swift-library-in-c/index.html b/docs/how-to-use-a-swift-library-in-c/index.html
index bfb7303..00cd9f9 100644
--- a/docs/how-to-use-a-swift-library-in-c/index.html
+++ b/docs/how-to-use-a-swift-library-in-c/index.html
@@ -100,7 +100,7 @@
How to use a Swift library in C
diff --git a/docs/how-to-use-c-libraries-in-swift/index.html b/docs/how-to-use-c-libraries-in-swift/index.html
index d0f4bb8..965e8a9 100644
--- a/docs/how-to-use-c-libraries-in-swift/index.html
+++ b/docs/how-to-use-c-libraries-in-swift/index.html
@@ -124,7 +124,7 @@ Building a custom C library using
int x;
int y;
};
-
We’ve just defined the public interface for our library. Now if you try to compile it through the swift build command, it’ll complain that the project is missing some source files. We can easily fix this by creating an empty MyPoint.c file under the Sources/MyPoint directory.
When you import a local header file to use in your implementation code, you can skip the “include” path and simply write #include “MyPoint.h”. You could also put all kinds of C family components into this project, this method works with C++, Objective-C and even Objective-C++ files.
NOTE: You could also place header files next to the implementation source code, but in that case the system won’t be able to auto-locate your public (umbrella) header files, so you also have to create a modulemap file and provide the correct location of your headers explicitly. If you use the structure with the include directory SPM will generate everything for you automatically.
Congratulations, you just shipped your first C code with Swift Package Manager. 🥳
Interacting with C libraries using Swift
We’re going to create a brand new Swift package to build an executable application based on the previously created C library. In order to use a local package you can simply specify it as with the path argument under the dependencies in your Package.swift manifest file.
// swift-tools-version:5.3
+
We’ve just defined the public interface for our library. Now if you try to compile it through the swift build command, it’ll complain that the project is missing some source files. We can easily fix this by creating an empty MyPoint.c file under the Sources/MyPoint directory.
When you import a local header file to use in your implementation code, you can skip the “include” path and simply write #include “MyPoint.h”. You could also put all kinds of C family components into this project, this method works with C++, Objective-C and even Objective-C++ files.
NOTE: You could also place header files next to the implementation source code, but in that case the system won’t be able to auto-locate your public (umbrella) header files, so you also have to create a modulemap file and provide the correct location of your headers explicitly. If you use the structure with the include directory SPM will generate everything for you automatically.
Congratulations, you just shipped your first C code with Swift Package Manager. 🥳
Interacting with C libraries using Swift
We’re going to create a brand new Swift package to build an executable application based on the previously created C library. In order to use a local package you can simply specify it as with the path argument under the dependencies in your Package.swift manifest file.
// swift-tools-version:5.3
import PackageDescription
let package = Package(
diff --git a/docs/how-to-use-icloud-drive-documents/index.html b/docs/how-to-use-icloud-drive-documents/index.html
index 4dd533a..bdfb2ab 100644
--- a/docs/how-to-use-icloud-drive-documents/index.html
+++ b/docs/how-to-use-icloud-drive-documents/index.html
@@ -108,7 +108,7 @@ How to use iCloud drive documents?
Learn how to sync files and data through a shared iCloud drive folder using the latest version of Swift programming language.
- iCloud drive project setup tutorial
Let’s start by creating a new project for iOS. You can select the single view application template, don’t worry too much about document based apps, because in this tutorial we’re not going to touch the UIDocument class at all. 🤷♂️

The first step is to enable iCloud capabilities, which will generate a new entitlements file for you. Also you’ll have to enable the iCloud application service for the app id on the Apple developer portal. You should also assign the iCloud container that’s going to be used to store data. Just a few clicks, but you have to do this manually. 💩
NOTE: You need a valid Apple Developer Program membership in order to set advanced app capabilities like iCloud support. So you have to pay $99/year. #greed 🤑

So I believe that now you have a proper iOS app identifier with iCloud capabilities and application services enabled. One last step is ahead, you have to add these few lines to your Info.plist file in order to define the iCloud drive container (folder name) that you’re going to use. Note that you can have multiple containers for one app.
<key>NSUbiquitousContainers</key>
+ iCloud drive project setup tutorial
Let’s start by creating a new project for iOS. You can select the single view application template, don’t worry too much about document based apps, because in this tutorial we’re not going to touch the UIDocument class at all. 🤷♂️

The first step is to enable iCloud capabilities, which will generate a new entitlements file for you. Also you’ll have to enable the iCloud application service for the app id on the Apple developer portal. You should also assign the iCloud container that’s going to be used to store data. Just a few clicks, but you have to do this manually. 💩
NOTE: You need a valid Apple Developer Program membership in order to set advanced app capabilities like iCloud support. So you have to pay $99/year. #greed 🤑

So I believe that now you have a proper iOS app identifier with iCloud capabilities and application services enabled. One last step is ahead, you have to add these few lines to your Info.plist file in order to define the iCloud drive container (folder name) that you’re going to use. Note that you can have multiple containers for one app.
<key>NSUbiquitousContainers</key>
<dict>
<key>iCloud.com.tiborbodecs.teszt</key>
<dict>
@@ -224,7 +224,7 @@ Related posts
Custom UIView subclass from a xib file
diff --git a/docs/how-to-write-swift-scripts-using-the-new-command-api-in-vapor-4/index.html b/docs/how-to-write-swift-scripts-using-the-new-command-api-in-vapor-4/index.html
index 28aa65e..f78fffc 100644
--- a/docs/how-to-write-swift-scripts-using-the-new-command-api-in-vapor-4/index.html
+++ b/docs/how-to-write-swift-scripts-using-the-new-command-api-in-vapor-4/index.html
@@ -142,7 +142,7 @@ Swift Argument Parser vs Vapor
app.commands.use(HelloCommand(), as: "hello")
}
// usage: swift run myProject hello world
-
As you can see they almost look like the same.
NOTE: If you love scripting, you should definitely check swift-sh and Brisk
The Swift Argument Parser library is a lightweight solution if you are only looking for a simple Swift script. A good example is a tool that manipulates files on the system or something similar. It’s just one little dependency, but it removes so much boilerplate from your scripts. It allows you to focus on the script itself, instead of parsing the command line inputs. You can find more detailed examples and a detailed documentation inside the GitHub repository. 🙏
Vapor’s Command API is useful if you want to perform more complicated tasks with your scripts. Anything that’s part of your Vapor application can be triggered from a command, so you can easily create a backend tool that reads (or writes) records from the database using Fluent 4. This is the main advantage of using a Vapor command, instead a standalone Swift script.
Arguments, options, flags
Let’s extend the hello command with a new option and a flag. The main difference between an option and a flag is that an option has an associated value, but a flag is just something that you give to the command or not. Both options and flags start with a single - or a double dash --, usually the single dashed version uses a short name for the same thing. 🤓
NOTE: Arguments are user provided values read in order (e.g. ./hello joe bob john).
Now that you know the basic definitions, here is the example:
final class HelloCommand: Command {
+
As you can see they almost look like the same.
NOTE: If you love scripting, you should definitely check swift-sh and Brisk
The Swift Argument Parser library is a lightweight solution if you are only looking for a simple Swift script. A good example is a tool that manipulates files on the system or something similar. It’s just one little dependency, but it removes so much boilerplate from your scripts. It allows you to focus on the script itself, instead of parsing the command line inputs. You can find more detailed examples and a detailed documentation inside the GitHub repository. 🙏
Vapor’s Command API is useful if you want to perform more complicated tasks with your scripts. Anything that’s part of your Vapor application can be triggered from a command, so you can easily create a backend tool that reads (or writes) records from the database using Fluent 4. This is the main advantage of using a Vapor command, instead a standalone Swift script.
Arguments, options, flags
Let’s extend the hello command with a new option and a flag. The main difference between an option and a flag is that an option has an associated value, but a flag is just something that you give to the command or not. Both options and flags start with a single - or a double dash --, usually the single dashed version uses a short name for the same thing. 🤓
NOTE: Arguments are user provided values read in order (e.g. ./hello joe bob john).
Now that you know the basic definitions, here is the example:
final class HelloCommand: Command {
struct Signature: CommandSignature {
diff --git a/docs/ios-auto-layout-tutorial-programmatically/index.html b/docs/ios-auto-layout-tutorial-programmatically/index.html
index 18fcaa3..4653c9e 100644
--- a/docs/ios-auto-layout-tutorial-programmatically/index.html
+++ b/docs/ios-auto-layout-tutorial-programmatically/index.html
@@ -300,7 +300,7 @@ Rotation support
If your application is going t
square.backgroundColor = .yellow
}
}
-
God forbid the engineer who invented this black magic. 😅
So as you can see we definitely have a problem with constraints. Creating all your constraints sucks, at least it’s going to cost many many lines of code. Of course you can use the magical interface builder, but where’s the fun if you just drag lines?
Creating constraints programmatically is no better than calculating frames, it will lead you to the same level of complexity or even worse, this is why so many 3rd party frameworks came alive and eventually Apple issued the problem as well.
NOTE: I have an amazing article about mastering Auto Layout anchors, I highly recommend reading it if you want to get familiar with anchors. 📖
Anchors
Anchors were born because Auto Layout had some construction flaws.
The NSLayoutAnchor class is a factory class for creating NSLayoutConstraint objects using a fluent API. Use these constraints to programmatically define your layout using Auto Layout.
class ViewController: UIViewController {
+
God forbid the engineer who invented this black magic. 😅
So as you can see we definitely have a problem with constraints. Creating all your constraints sucks, at least it’s going to cost many many lines of code. Of course you can use the magical interface builder, but where’s the fun if you just drag lines?
Creating constraints programmatically is no better than calculating frames, it will lead you to the same level of complexity or even worse, this is why so many 3rd party frameworks came alive and eventually Apple issued the problem as well.
NOTE: I have an amazing article about mastering Auto Layout anchors, I highly recommend reading it if you want to get familiar with anchors. 📖
Anchors
Anchors were born because Auto Layout had some construction flaws.
The NSLayoutAnchor class is a factory class for creating NSLayoutConstraint objects using a fluent API. Use these constraints to programmatically define your layout using Auto Layout.
class ViewController: UIViewController {
weak var square: UIView!
@@ -453,7 +453,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/ios-custom-transition-tutorial-in-swift/index.html b/docs/ios-custom-transition-tutorial-in-swift/index.html
index 0eca387..48d76e2 100644
--- a/docs/ios-custom-transition-tutorial-in-swift/index.html
+++ b/docs/ios-custom-transition-tutorial-in-swift/index.html
@@ -108,7 +108,7 @@ iOS custom transition tutorial in Swift
In this tutorial, you'll learn how to replace the push, pop and modal animations with custom transitions & percent driven interactions.
- UIKit custom transition API - a theoretical lesson
There are many classes and delegates involved during the process of making a custom transition, let’s walk through these items real quick, and do some coding afterwards.
UIViewControllerTransitioningDelegate
Every view controller can have a transition delegate, in that delegate implementation you can provide the custom animation and interaction controllers. Those objects will be responsible for the actual animation process, and this delegate is the place where you can “inject your code” to the UIKit framework. 💉
UINavigationControllerDelegate
The navigation controller delegate also has two methods that are responsible for custom push and pop animations. It’s almost the same as the transitioning delegate for the view controllers, but you’ll see this in action later on. 💥
UINavigationController.Operation
The navigation controller operation is just an enum which contains the “direction” of the navigation animation. Usually push or pop.
NOTE: Presenting and dismissing something modally is not exactly the same thing as pushing & popping view controllers inside a navigation stack. More on this later.
UIViewControllerAnimatedTransitioning
These objects are returned by the transition delegate, so basically this is the place where you implement the fancy custom view animations. 😉
UIViewControllerContextTransitioning
This context encapsulates all the info about the transitioning, you can get the participating views, controllers and many more from this object. The transitioning context is available for you to use it during the animation.
UIPercentDrivenInteractiveTransition
An object that drives an interactive animation between one view controller and another.
In a nutshell, this is the thing that gives you the magical ability to swipe a navigation controller interactively back (and forth if you changed your mind) with your fingers from the edge of the screen. 📱
Custom transition animations programmatically
Let’s do some real coding! I’ll show you how to make a basic fade animation between view controllers inside a navigation stack. First we’ll start with the push animation.
open class FadePushAnimator: NSObject, UIViewControllerAnimatedTransitioning {
+ UIKit custom transition API - a theoretical lesson
There are many classes and delegates involved during the process of making a custom transition, let’s walk through these items real quick, and do some coding afterwards.
UIViewControllerTransitioningDelegate
Every view controller can have a transition delegate, in that delegate implementation you can provide the custom animation and interaction controllers. Those objects will be responsible for the actual animation process, and this delegate is the place where you can “inject your code” to the UIKit framework. 💉
UINavigationControllerDelegate
The navigation controller delegate also has two methods that are responsible for custom push and pop animations. It’s almost the same as the transitioning delegate for the view controllers, but you’ll see this in action later on. 💥
UINavigationController.Operation
The navigation controller operation is just an enum which contains the “direction” of the navigation animation. Usually push or pop.
NOTE: Presenting and dismissing something modally is not exactly the same thing as pushing & popping view controllers inside a navigation stack. More on this later.
UIViewControllerAnimatedTransitioning
These objects are returned by the transition delegate, so basically this is the place where you implement the fancy custom view animations. 😉
UIViewControllerContextTransitioning
This context encapsulates all the info about the transitioning, you can get the participating views, controllers and many more from this object. The transitioning context is available for you to use it during the animation.
UIPercentDrivenInteractiveTransition
An object that drives an interactive animation between one view controller and another.
In a nutshell, this is the thing that gives you the magical ability to swipe a navigation controller interactively back (and forth if you changed your mind) with your fingers from the edge of the screen. 📱
Custom transition animations programmatically
Let’s do some real coding! I’ll show you how to make a basic fade animation between view controllers inside a navigation stack. First we’ll start with the push animation.
open class FadePushAnimator: NSObject, UIViewControllerAnimatedTransitioning {
open func transitionDuration(
using transitionContext: UIViewControllerContextTransitioning?
@@ -397,7 +397,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/logging-for-beginners-in-swift/index.html b/docs/logging-for-beginners-in-swift/index.html
index aed0de1..d8baaf3 100644
--- a/docs/logging-for-beginners-in-swift/index.html
+++ b/docs/logging-for-beginners-in-swift/index.html
@@ -146,7 +146,7 @@ Basic output in Swift using print
The ClosedRange struct is a built-in type with a lowerBound and an upperBound property. While the print function only returned the defined range (1…5), the debugPrint method also revealed the type of the object, dump takes this one step further by showing us the exact lower and upper bound properties of the value. This can be extremely helpful when you have a complex type with lots of underlying properties that you want to quickly inspect for some reason. 🔍
NOTE: By the way, debugging is the act of finding (and resolving) bugs. Bugs are problems in your program code that prevent normal operation. Developers can use debugger tools to run and inspect code step by step, line by line or per instruction, but most of them are simply putting print statements into the code to see the current state or result of a given function. 🤷♂️
Dump has a few more function arguments that you can configure:
dump("test", name: "my-variable", indent: 4, maxDepth: 5, maxItems: 5)
+
The ClosedRange struct is a built-in type with a lowerBound and an upperBound property. While the print function only returned the defined range (1…5), the debugPrint method also revealed the type of the object, dump takes this one step further by showing us the exact lower and upper bound properties of the value. This can be extremely helpful when you have a complex type with lots of underlying properties that you want to quickly inspect for some reason. 🔍
NOTE: By the way, debugging is the act of finding (and resolving) bugs. Bugs are problems in your program code that prevent normal operation. Developers can use debugger tools to run and inspect code step by step, line by line or per instruction, but most of them are simply putting print statements into the code to see the current state or result of a given function. 🤷♂️
Dump has a few more function arguments that you can configure:
dump("test", name: "my-variable", indent: 4, maxDepth: 5, maxItems: 5)
// output: - my-variable: "test"
You can give a name to each dumped variable, add some extra indentation before the dash character, specify the maximum depth for descendents and the maximum number of elements for which to write the full contents. Feel free to play with these parameters for a while. 😉
As you can see dump is quite a powerful method, but still there are other functions for logging purposes, let me show you one that is coming from the Objective-C times.
NSLog - the legacy logger function
If you have ever worked with Objective-C you should be familiar with the NS prefixes. The NSLog function can log an error message to the Apple System Log facility console. It’s not part of the Swift standard library, but you have to import the Foundation framework in order to use NSLog.
import Foundation
diff --git a/docs/mastering-ios-auto-layout-anchors-programmatically-from-swift/index.html b/docs/mastering-ios-auto-layout-anchors-programmatically-from-swift/index.html
index 81151f2..14f1e68 100644
--- a/docs/mastering-ios-auto-layout-anchors-programmatically-from-swift/index.html
+++ b/docs/mastering-ios-auto-layout-anchors-programmatically-from-swift/index.html
@@ -371,7 +371,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/memory-layout-in-swift/index.html b/docs/memory-layout-in-swift/index.html
index 4b58bf0..03fbbe1 100644
--- a/docs/memory-layout-in-swift/index.html
+++ b/docs/memory-layout-in-swift/index.html
@@ -100,7 +100,7 @@
Memory layout in Swift
@@ -153,7 +153,7 @@ Memory layout of value types in S
┌──────────────────┴───────────┴──────┬──────────────────┴───────────┴──────┐
│ 16 bytes size (1+7+8) │ 16 bytes size (1+7+8) │
└─────────────────────────────────────┴─────────────────────────────────────┘
-
This is the main reason why the second example struct has a slightly increased size value. Feel free to create other types and practice by drawing the memory layout for them, you can always check if you were correct or not by printing the memory layout at runtime using Swift. 💡
NOTE: This whole problem is real nicely explained on the [swift unboxed] blog. I would also like to recommend this article by Steven Curtis and there is one more great post about Unsafe Swift: A road to memory. These writings helped me a lot to understand memory layout in Swift. 🙏
Reference types and memory layout in Swift
I mentioned earlier that classes behave quite different that’s because they are reference types. Let me change the Example type to a class and see what happens with the memory layout.
class Example {
+
This is the main reason why the second example struct has a slightly increased size value. Feel free to create other types and practice by drawing the memory layout for them, you can always check if you were correct or not by printing the memory layout at runtime using Swift. 💡
NOTE: This whole problem is real nicely explained on the [swift unboxed] blog. I would also like to recommend this article by Steven Curtis and there is one more great post about Unsafe Swift: A road to memory. These writings helped me a lot to understand memory layout in Swift. 🙏
Reference types and memory layout in Swift
I mentioned earlier that classes behave quite different that’s because they are reference types. Let me change the Example type to a class and see what happens with the memory layout.
class Example {
let bar: Bool = true // 1
let foo: Int = 0 // 8
}
diff --git a/docs/networking-examples-for-appleos/index.html b/docs/networking-examples-for-appleos/index.html
index 028ae6e..e43b105 100644
--- a/docs/networking-examples-for-appleos/index.html
+++ b/docs/networking-examples-for-appleos/index.html
@@ -108,7 +108,7 @@ Networking examples for appleOS
Learn how to use Bonjour, with UDP/TCP sockets, streams and how to communicate through CoreBluetooth or the watch APIs.
- WARN: This article was originally written back in the end of 2015. The source code is deprecated and not compatible with current Swift versions, so I removed it.
If you want to learn how to make a network connection between your devices using Bonjour discovery service you are on the right place. In this post I am going to show you the basics, so for example you will be able to make a remote controller from your watch or iOS device in order to send data directly to any tvOS or macOS machines.
Multi-platform development
If you want to create an app that supports multiple platforms, you might want to target macOS, iOS, watchOS, tvOS and soon Linux as well. The code snippet below is going to help you detecting the current platform that you are working with.
#if os(iOS)
+ WARN: This article was originally written back in the end of 2015. The source code is deprecated and not compatible with current Swift versions, so I removed it.
If you want to learn how to make a network connection between your devices using Bonjour discovery service you are on the right place. In this post I am going to show you the basics, so for example you will be able to make a remote controller from your watch or iOS device in order to send data directly to any tvOS or macOS machines.
Multi-platform development
If you want to create an app that supports multiple platforms, you might want to target macOS, iOS, watchOS, tvOS and soon Linux as well. The code snippet below is going to help you detecting the current platform that you are working with.
#if os(iOS)
let platform = "iOS"
#elseif os(macOS)
let platform = "macOS"
@@ -123,7 +123,7 @@ Networking examples for appleOS
#endif
print(platform)
-
Network connection 101
Bonjour discovery service
Bonjour, also known as zero-configuration networking, enables automatic discovery of devices and services on a local network using industry standard IP protocols.
So basically with Bonjour you can find network devices on your local network. This comes very handy if you are trying to figure out the list of devices that are connected to your LAN. Using NetService class will help you to detect all the devices with the available services that they support. The whole Bonjour API is relatively small and well-written. From the aspect of server side you just have to create the NetService object, and listen to the incoming connections through the NetServiceDelegate.
NOTE: You have to be on the same WiFi network with all devices / simulators.
TCP connection
TCP provides reliable, ordered, and error-checked delivery of a stream of octets (bytes) between applications running on hosts communicating by an IP network.
With the help of TCP you can build up a reliable network connection. There is a Stream class in Foundation to help you sending data back and forth between devices. If you have a working connection form NetServiceDelegate, just listen to the stream events to handle incoming data through the StreamDelegate. I don’t want to go into the details, just download the example code and check it out for yourself.
UDP connection
With UDP, computer applications can send messages, in this case referred to as datagrams, to other hosts on an Internet Protocol (IP) network.
If you look at the article about UDP you’ll clearly see that the main difference from TCP is that this protocol will not guarantee you safety of the data delivery. Data may arrives unordered or duplicated, it’s your task to handle these scenarios, but the UDP is fast. If you want to build a file transfer app you should definitely go with TCP, but for example controlling a real-time action game UDP is just as good enough.
CocoaAsyncSocket
This library is the absolute winner for me and probably it is the best option for everyone who wants to set up a network connection really quickly, because it requires way less code than implementing delegates. Of course you’ll still need the Bonjour layer above the whole thing, but that’s just fine to deal with.
If you are using CocoaAsyncSocket you will see that the API is straightforward, only after 5 minutes I could relatively easily figure it out what’s going on and I was able to send messages through the network. It supports all the Apple platforms, you can seamlessly integrate it using Carthage or CocoaPods.
CoreBluetooth APIs
I was not really familiar with the CoreBluetooth framework API’s, that’s the reason why I basically just followed and ported this tutsplus.com code example to Swift 4. Honestly I felt that the API is somehow over-complicated with all those messy delegate functions. If I have to chose between CoreBluetooth or CocoaAsyncSocket, I’d go with the last one. So yes, obviously I am not a Bluetooth expert, but this little project was a good first impression about how things are working inside the CB framework.
WatchConnectivity framework
If you want to communicate between iOS and watchOS you’ll probably use the WatchConnectivity framework, especially the WKSession class. It’s really not so complicated, with just a few lines of code you can send messages form the watch to the iPhone. You can read this tutorial, but if you download my final sources for this article, you’ll find almost the same thing inside the package.
+
Network connection 101
Bonjour discovery service
Bonjour, also known as zero-configuration networking, enables automatic discovery of devices and services on a local network using industry standard IP protocols.
So basically with Bonjour you can find network devices on your local network. This comes very handy if you are trying to figure out the list of devices that are connected to your LAN. Using NetService class will help you to detect all the devices with the available services that they support. The whole Bonjour API is relatively small and well-written. From the aspect of server side you just have to create the NetService object, and listen to the incoming connections through the NetServiceDelegate.
NOTE: You have to be on the same WiFi network with all devices / simulators.
TCP connection
TCP provides reliable, ordered, and error-checked delivery of a stream of octets (bytes) between applications running on hosts communicating by an IP network.
With the help of TCP you can build up a reliable network connection. There is a Stream class in Foundation to help you sending data back and forth between devices. If you have a working connection form NetServiceDelegate, just listen to the stream events to handle incoming data through the StreamDelegate. I don’t want to go into the details, just download the example code and check it out for yourself.
UDP connection
With UDP, computer applications can send messages, in this case referred to as datagrams, to other hosts on an Internet Protocol (IP) network.
If you look at the article about UDP you’ll clearly see that the main difference from TCP is that this protocol will not guarantee you safety of the data delivery. Data may arrives unordered or duplicated, it’s your task to handle these scenarios, but the UDP is fast. If you want to build a file transfer app you should definitely go with TCP, but for example controlling a real-time action game UDP is just as good enough.
CocoaAsyncSocket
This library is the absolute winner for me and probably it is the best option for everyone who wants to set up a network connection really quickly, because it requires way less code than implementing delegates. Of course you’ll still need the Bonjour layer above the whole thing, but that’s just fine to deal with.
If you are using CocoaAsyncSocket you will see that the API is straightforward, only after 5 minutes I could relatively easily figure it out what’s going on and I was able to send messages through the network. It supports all the Apple platforms, you can seamlessly integrate it using Carthage or CocoaPods.
CoreBluetooth APIs
I was not really familiar with the CoreBluetooth framework API’s, that’s the reason why I basically just followed and ported this tutsplus.com code example to Swift 4. Honestly I felt that the API is somehow over-complicated with all those messy delegate functions. If I have to chose between CoreBluetooth or CocoaAsyncSocket, I’d go with the last one. So yes, obviously I am not a Bluetooth expert, but this little project was a good first impression about how things are working inside the CB framework.
WatchConnectivity framework
If you want to communicate between iOS and watchOS you’ll probably use the WatchConnectivity framework, especially the WKSession class. It’s really not so complicated, with just a few lines of code you can send messages form the watch to the iPhone. You can read this tutorial, but if you download my final sources for this article, you’ll find almost the same thing inside the package.
@@ -188,7 +188,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/page/1/index.html b/docs/page/1/index.html
index 5bfc9ee..b2cfd55 100644
--- a/docs/page/1/index.html
+++ b/docs/page/1/index.html
@@ -388,7 +388,7 @@
- · 2 min read
+ · 3 min read
Swift visitor design pattern
@@ -494,7 +494,7 @@
- · 3 min read
+ · 4 min read
How to use a Swift library in C
diff --git a/docs/page/2/index.html b/docs/page/2/index.html
index c632706..3d8d3f8 100644
--- a/docs/page/2/index.html
+++ b/docs/page/2/index.html
@@ -154,7 +154,7 @@
- · 5 min read
+ · 6 min read
Building tree data structures in Swift
@@ -344,7 +344,7 @@
- · 7 min read
+ · 8 min read
Declarative unit tests for Vapor
@@ -409,7 +409,7 @@
- · 7 min read
+ · 8 min read
Memory layout in Swift
diff --git a/docs/page/3/index.html b/docs/page/3/index.html
index 548a7b3..153e421 100644
--- a/docs/page/3/index.html
+++ b/docs/page/3/index.html
@@ -262,7 +262,7 @@
Websockets for beginners using Vapor 4 and Vanilla JavaScript
@@ -305,7 +305,7 @@
- · 4 min read
+ · 5 min read
What's new in Swift 5.3?
@@ -607,7 +607,7 @@
- · 17 min read
+ · 18 min read
Beginner's guide to Server side Swift using Vapor 4
diff --git a/docs/page/4/index.html b/docs/page/4/index.html
index 96a317b..b45d08d 100644
--- a/docs/page/4/index.html
+++ b/docs/page/4/index.html
@@ -599,7 +599,7 @@
Custom UIView subclass from a xib file
diff --git a/docs/page/6/index.html b/docs/page/6/index.html
index e506018..949bbed 100644
--- a/docs/page/6/index.html
+++ b/docs/page/6/index.html
@@ -131,7 +131,7 @@
- · 10 min read
+ · 11 min read
Deep dive into Swift frameworks
@@ -324,16 +324,17 @@
- Asynchronous validation for Vapor
+ UIKit init patterns
- Learn how to validate input data using an async technique. Unified request validation API for your server side Swift app.
+ Learn about the initialization process of the two well known classes in UIKit. Say hello to UIViewcontroller, and UIView init patterns.
@@ -346,15 +347,16 @@
- · 6 min read
+ · 2 min read
- Everything about public and private Swift attributes
+ Top 20 iOS libraries written in Swift
- Have you ever heard about Swift language attributes? In this article I'm trying to gather all the @ annotations and their meanings.
+ I gathered the best open source Swift frameworks on github that will help you to speed up mobile application development in 2019.
@@ -367,15 +369,16 @@
- · 6 min read
+ · 7 min read
- How to create reusable views for modern collection views?
+ The ultimate Combine framework tutorial in Swift
- A quick intro to modern collection views using compositional layout, diffable data source and reusable view components.
+ Get started with the brand new declarative Combine framework in practice using Swift. I'll teach you all the goodies from zero to hero.
@@ -409,16 +412,15 @@
- The ultimate Combine framework tutorial in Swift
+ How to create reusable views for modern collection views?
- Get started with the brand new declarative Combine framework in practice using Swift. I'll teach you all the goodies from zero to hero.
+ A quick intro to modern collection views using compositional layout, diffable data source and reusable view components.
@@ -431,16 +433,15 @@
- · 2 min read
+ · 6 min read
- Top 20 iOS libraries written in Swift
+ Everything about public and private Swift attributes
- I gathered the best open source Swift frameworks on github that will help you to speed up mobile application development in 2019.
+ Have you ever heard about Swift language attributes? In this article I'm trying to gather all the @ annotations and their meanings.
@@ -453,17 +454,16 @@
- · 1 min read
+ · 13 min read
- UIKit init patterns
+ Asynchronous validation for Vapor
- Learn about the initialization process of the two well known classes in UIKit. Say hello to UIViewcontroller, and UIView init patterns.
+ Learn how to validate input data using an async technique. Unified request validation API for your server side Swift app.
diff --git a/docs/picking-and-playing-videos-in-swift/index.html b/docs/picking-and-playing-videos-in-swift/index.html
index 50e1440..bc1a5ad 100644
--- a/docs/picking-and-playing-videos-in-swift/index.html
+++ b/docs/picking-and-playing-videos-in-swift/index.html
@@ -451,7 +451,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/picking-images-with-uiimagepickercontroller-in-swift-5/index.html b/docs/picking-images-with-uiimagepickercontroller-in-swift-5/index.html
index 3320344..fc53c76 100644
--- a/docs/picking-images-with-uiimagepickercontroller-in-swift-5/index.html
+++ b/docs/picking-images-with-uiimagepickercontroller-in-swift-5/index.html
@@ -108,7 +108,7 @@ Picking images with UIImagePickerController in Swift 5
Learn how to get an image from the photo library or directly from the camera by using the UIImagePickerController class in Swift 5.
- Are you looking for a video picker as well? 🍿 Check out my another post about picking & playing video files in iOS.
A reusable image picker class for iOS
So in this tutorial we’re going to create a reusable class built on top of UIKit in order to make image selection more pleasant for your apps, everything written in Swift 5.
This article was inspired by my previous attempt to solve the image picking issue in a protocol oriented way, but that article is nowadays a little bit obsolated, plus I wouldn’t use that technique anymore.
People always learn from the past, so instead of using a protocol oriented approach, this time I’ll simply go with an ImagePicker class. No singletons, no extra library, just a small helper class that can be instantiated in the appropriate place, to do it’s job. 🌄
NOTE: I’m only going to focus on picking edited images, if you’d like to use live photos or movies, you can always customize the ImagePicker class, or create an abstract one and implement subclasses for each media type. I’d do so too. 😅
So let’s dive in, here is my basic implementation, but you can download a complete example project with video picking as well from The.Swift.Dev. tutorials repository on GitHub.
Privacy first!
Nowadays privacy matters a lot, so you have to add two important keys to your applications Info.plist file, otherwise you’ll end up with a horrible crash! ⚠️
Since you’d like to get some private data, you have to provide an explanation message for the user (and for Apple) why the app is requesting camera & photo library access. The NSCameraUsageDescription is for camera and NSPhotoLibraryUsageDescription key is for photo library access. Both values should be a straightforward string that’ll explain the user why you need his/her nude pictures. Privacy is important! 🔒
<key>NSCameraUsageDescription</key>
+ Are you looking for a video picker as well? 🍿 Check out my another post about picking & playing video files in iOS.
A reusable image picker class for iOS
So in this tutorial we’re going to create a reusable class built on top of UIKit in order to make image selection more pleasant for your apps, everything written in Swift 5.
This article was inspired by my previous attempt to solve the image picking issue in a protocol oriented way, but that article is nowadays a little bit obsolated, plus I wouldn’t use that technique anymore.
People always learn from the past, so instead of using a protocol oriented approach, this time I’ll simply go with an ImagePicker class. No singletons, no extra library, just a small helper class that can be instantiated in the appropriate place, to do it’s job. 🌄
NOTE: I’m only going to focus on picking edited images, if you’d like to use live photos or movies, you can always customize the ImagePicker class, or create an abstract one and implement subclasses for each media type. I’d do so too. 😅
So let’s dive in, here is my basic implementation, but you can download a complete example project with video picking as well from The.Swift.Dev. tutorials repository on GitHub.
Privacy first!
Nowadays privacy matters a lot, so you have to add two important keys to your applications Info.plist file, otherwise you’ll end up with a horrible crash! ⚠️
Since you’d like to get some private data, you have to provide an explanation message for the user (and for Apple) why the app is requesting camera & photo library access. The NSCameraUsageDescription is for camera and NSPhotoLibraryUsageDescription key is for photo library access. Both values should be a straightforward string that’ll explain the user why you need his/her nude pictures. Privacy is important! 🔒
<key>NSCameraUsageDescription</key>
<string>This app wants to take pictures.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app wants to use your photos.</string>
@@ -206,7 +206,7 @@ Picking images with UIImagePickerController in Swift 5
extension ImagePicker: UINavigationControllerDelegate {
}
-
If you don’t need to select from a source type, things are pretty straightforward, you can simply present your picker view controller, handle everything in the delegate and you are done. However, if you need to choose from an input source, that involves a little bit more logic, especially on iPads. 📱
I’m using a UIAlertController in order to compose a source type selection dialog. I’m trying to add 3 actions (based on the picking source type), but only if the source type is available on that given device (e.g. .camera is not available in the simulator). You can check availability through: UIImagePickerController.isSourceTypeAvailable(type).
NOTE: Alert controllers needs a few extra things on iPads, that’s why I’m setting up the popoverPresentationController properties in the present method. It’s usually enough to set the sourceView and the sourceRect properties, but you can also customize arrow directions. ⬅️➡️⬆️⬇️
It’s always your task to check if the device is an iPad & set the proper source view & rect if it’s needed, otherwise your app will crash on iPads. Another thing is that you have to dismiss the UIPickerViewController after the picker did it’s job! ⚠️
Time to say cheese! 🧀
How to use the image picker class?
Well, now you are ready to take some pictures. I’ve made a simple view controller to show you a real quick example. You only need a UIImageView and a UIButton.
Now this is the code for the sample view controller. Nothing magical, I just pass the controller as a presentationController for the ImagePicker so it’ll be able to present the UIImagePickerController on top of that. I separated the delegate from the presentation controller, because sometimes it comes handy. 🤷♂️
class ViewController: UIViewController {
+
If you don’t need to select from a source type, things are pretty straightforward, you can simply present your picker view controller, handle everything in the delegate and you are done. However, if you need to choose from an input source, that involves a little bit more logic, especially on iPads. 📱
I’m using a UIAlertController in order to compose a source type selection dialog. I’m trying to add 3 actions (based on the picking source type), but only if the source type is available on that given device (e.g. .camera is not available in the simulator). You can check availability through: UIImagePickerController.isSourceTypeAvailable(type).
NOTE: Alert controllers needs a few extra things on iPads, that’s why I’m setting up the popoverPresentationController properties in the present method. It’s usually enough to set the sourceView and the sourceRect properties, but you can also customize arrow directions. ⬅️➡️⬆️⬇️
It’s always your task to check if the device is an iPad & set the proper source view & rect if it’s needed, otherwise your app will crash on iPads. Another thing is that you have to dismiss the UIPickerViewController after the picker did it’s job! ⚠️
Time to say cheese! 🧀
How to use the image picker class?
Well, now you are ready to take some pictures. I’ve made a simple view controller to show you a real quick example. You only need a UIImageView and a UIButton.
Now this is the code for the sample view controller. Nothing magical, I just pass the controller as a presentationController for the ImagePicker so it’ll be able to present the UIImagePickerController on top of that. I separated the delegate from the presentation controller, because sometimes it comes handy. 🤷♂️
class ViewController: UIViewController {
@IBOutlet var imageView: UIImageView!
@@ -311,7 +311,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/progressive-web-apps-on-ios/index.html b/docs/progressive-web-apps-on-ios/index.html
index 4a214ca..c70043c 100644
--- a/docs/progressive-web-apps-on-ios/index.html
+++ b/docs/progressive-web-apps-on-ios/index.html
@@ -330,7 +330,7 @@ How to make a PWA for iOS?
A custom working directory for Vapor, this will allow the system to look up the public files from the right place.
NOTE: Your custom icons won’t show up if you are using a self-signed certificate.
Build and run the server and try to bookmark your page again using your phone. When you see the add bookmark page you should be able to validate that the app now uses the predefined Hello PWA name and the image preview should show the custom icon file instead of a screenshot of the page.
Proper status bar color for iOS PWAs
Long story short, there is a great article on CSS-Tricks about the most recent version of Safari and how it handles various theme colors on different platforms. It’s a great article, you should definitely read it, but in most of the cases you won’t need this much info, but you simply want to support light and dark mode for your progressive web app. That’s what I’m going to show you here.
For light mode we’re going to use a white background color and for dark mode we use black. We’re also going to link a new style.css file so we can change the background of the site and the font color according to the current color scheme. First, the new meta tags to support theme colors both for light and dark mode.
struct IndexTemplate: TemplateRepresentable {
+
By adding the FileMiddleware to the app with the public directory path configuration your server app is able to serve static files from the Public directory. Feel free to create it and place the app icons under the Public/img/apple/icons folder. If you are running the server from the command line you’ll be fine, but if you are using Xcode you have to specify a custom working directory for Vapor, this will allow the system to look up the public files from the right place.
NOTE: Your custom icons won’t show up if you are using a self-signed certificate.
Build and run the server and try to bookmark your page again using your phone. When you see the add bookmark page you should be able to validate that the app now uses the predefined Hello PWA name and the image preview should show the custom icon file instead of a screenshot of the page.
Proper status bar color for iOS PWAs
Long story short, there is a great article on CSS-Tricks about the most recent version of Safari and how it handles various theme colors on different platforms. It’s a great article, you should definitely read it, but in most of the cases you won’t need this much info, but you simply want to support light and dark mode for your progressive web app. That’s what I’m going to show you here.
For light mode we’re going to use a white background color and for dark mode we use black. We’re also going to link a new style.css file so we can change the background of the site and the font color according to the current color scheme. First, the new meta tags to support theme colors both for light and dark mode.
struct IndexTemplate: TemplateRepresentable {
let context: IndexContext
@@ -665,7 +665,7 @@ Related posts
Custom UIView subclass from a xib file
diff --git a/docs/rss.xml b/docs/rss.xml
index 42260d0..8afa301 100644
--- a/docs/rss.xml
+++ b/docs/rss.xml
@@ -4,7 +4,7 @@
Articles about application development using the Swift programming language.
https://theswiftdev.com/
en-US
- Tue, 15 Oct 2024 17:49:48 +0000
+ Tue, 22 Oct 2024 18:47:43 +0000
Wed, 22 Mar 2023 16:20:00 +0000
250
diff --git a/docs/self-sizing-cells-with-rotation-support/index.html b/docs/self-sizing-cells-with-rotation-support/index.html
index 5895118..645401c 100644
--- a/docs/self-sizing-cells-with-rotation-support/index.html
+++ b/docs/self-sizing-cells-with-rotation-support/index.html
@@ -390,7 +390,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/server-side-swift-projects-inside-docker-using-vapor-4/index.html b/docs/server-side-swift-projects-inside-docker-using-vapor-4/index.html
index aee2b95..1789d3a 100644
--- a/docs/server-side-swift-projects-inside-docker-using-vapor-4/index.html
+++ b/docs/server-side-swift-projects-inside-docker-using-vapor-4/index.html
@@ -108,7 +108,7 @@ Server side Swift projects inside Docker using Vapor 4
Learn how to setup Vapor 4 projects inside a Docker container. Are you completely new to Docker? This article is just for you.
- What the heck is Docker?
Operating-system-level virtualization is called containerization technology. It’s more lightweight than virtual machines, since all the containers are run by a single operating system kernel.
Docker used to run software packages in these self-contained isolated environments. These containers bundle their own tools, libraries and configuration files. They can communicate with each other through well-defined channels. Containers are being made from images that specify their precise contents. You can find plenty of Docker images on DockerHub.
Docker is extremely useful if you don’t want to spend hours to setup & configure your work environment. It helps the software deployment process, so patches, hotfixes and new code releases can be delivered more frequently. In other words it’s a DevOps tool.
NOTE: Guess what: you can use Swift right ahead through a single Docker container, you don’t even need to install anything else on your computer, but Docker. 🐳
Docker architecture in a nutshell
There is a nice get to know post about the Docker ecosystem, but if you want to get a detailed overview you should read the Docker glossary. In this tutorial I’m going to focus on images and containers. Maybe a little bit on the hub, engine & machines. 😅
Docker engine
Lightweight and powerful open source containerization technology combined with a work flow for building and containerizing your applications.
Docker image
Docker images are the basis (templates) of containers.
Docker container
A container is a runtime instance of a docker image.
Docker machine
A tool that lets you install Docker Engine on virtual hosts, and manage the hosts with docker-machine commands.
Docker hub
A centralized resource for working with Docker and its components.
So just a little clarification: Docker images can be created through Dockerfiles, these are the templates for running containers. Imagine them like “pre-built install disks” for your container environments. If we approach this from an object-oriented programming perspective, then an image is a class definition and the container is the instance created from it. 💾
How to run Swift in a Docker container?
Let me show you how to run Swift under Linux inside a Docker container. First of all, install Docker (fastest way is brew install docker), start the app itself (give it some permissions), and pull the official Swift Docker image from the cloud by using the docker pull swift command. 😎
NOTE: You can also use the official Vapor Docker images for server side Swift development.
Packaging Swift code into an image
The first thing I’d like to teach you is how to create a custom Docker image & pack all your Swift source code into it. Just create a new Swift project swift package init --type=executable inside a folder and also make a new Dockerfile:
FROM swift
+ What the heck is Docker?
Operating-system-level virtualization is called containerization technology. It’s more lightweight than virtual machines, since all the containers are run by a single operating system kernel.
Docker used to run software packages in these self-contained isolated environments. These containers bundle their own tools, libraries and configuration files. They can communicate with each other through well-defined channels. Containers are being made from images that specify their precise contents. You can find plenty of Docker images on DockerHub.
Docker is extremely useful if you don’t want to spend hours to setup & configure your work environment. It helps the software deployment process, so patches, hotfixes and new code releases can be delivered more frequently. In other words it’s a DevOps tool.
NOTE: Guess what: you can use Swift right ahead through a single Docker container, you don’t even need to install anything else on your computer, but Docker. 🐳
Docker architecture in a nutshell
There is a nice get to know post about the Docker ecosystem, but if you want to get a detailed overview you should read the Docker glossary. In this tutorial I’m going to focus on images and containers. Maybe a little bit on the hub, engine & machines. 😅
Docker engine
Lightweight and powerful open source containerization technology combined with a work flow for building and containerizing your applications.
Docker image
Docker images are the basis (templates) of containers.
Docker container
A container is a runtime instance of a docker image.
Docker machine
A tool that lets you install Docker Engine on virtual hosts, and manage the hosts with docker-machine commands.
Docker hub
A centralized resource for working with Docker and its components.
So just a little clarification: Docker images can be created through Dockerfiles, these are the templates for running containers. Imagine them like “pre-built install disks” for your container environments. If we approach this from an object-oriented programming perspective, then an image is a class definition and the container is the instance created from it. 💾
How to run Swift in a Docker container?
Let me show you how to run Swift under Linux inside a Docker container. First of all, install Docker (fastest way is brew install docker), start the app itself (give it some permissions), and pull the official Swift Docker image from the cloud by using the docker pull swift command. 😎
NOTE: You can also use the official Vapor Docker images for server side Swift development.
Packaging Swift code into an image
The first thing I’d like to teach you is how to create a custom Docker image & pack all your Swift source code into it. Just create a new Swift project swift package init --type=executable inside a folder and also make a new Dockerfile:
FROM swift
WORKDIR /app
COPY . ./
CMD swift package clean
diff --git a/docs/sitemap.xml b/docs/sitemap.xml
index 980f182..412996b 100644
--- a/docs/sitemap.xml
+++ b/docs/sitemap.xml
@@ -309,7 +309,7 @@
https://theswiftdev.com/asynchronous-validation-for-vapor/
2024-10-15
https://theswiftdev.com/everything-about-public-and-private-swift-attributes/
- 2024-10-15
+ 2024-10-22
https://theswiftdev.com/how-to-create-reusable-views-for-modern-collection-views/
2024-10-15
https://theswiftdev.com/result-builders-in-swift/
diff --git a/docs/styling-by-subclassing/index.html b/docs/styling-by-subclassing/index.html
index 50dfc1e..322e116 100644
--- a/docs/styling-by-subclassing/index.html
+++ b/docs/styling-by-subclassing/index.html
@@ -290,7 +290,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/swift-actors-tutorial-a-beginners-guide-to-thread-safe-concurrency/index.html b/docs/swift-actors-tutorial-a-beginners-guide-to-thread-safe-concurrency/index.html
index c6865fa..41c8a9c 100644
--- a/docs/swift-actors-tutorial-a-beginners-guide-to-thread-safe-concurrency/index.html
+++ b/docs/swift-actors-tutorial-a-beginners-guide-to-thread-safe-concurrency/index.html
@@ -234,7 +234,7 @@ Thread safety & data races
Before we di
}
print(await storage.allValues)
}
-
First of all, actors are reference types, just like classes. They can have methods, properties, they can implement protocols, but they don’t support inheritance.
NOTE: Since actors are closely related to the newly introduced async/await concurrency APIs in Swift you should be familiar with that concept too if you want to understand how they work.
The very first big difference is that we don’t need to provide a lock mechanism anymore in order to provide read or write access to our private storage property. This means that we can safely access actor properties within the actor using a synchronous way. Members are isolated by default, so there is a guarantee (by the compiler) that we can only access them using the same context.
What’s going on with the new Task API and all the await keywords? 🤔
Well, the Dispatch.concurrentPerform call is part of a parallelism API and Swift 5.5 introduced concurrency instead of parallelism, we have to move away from regular queues and use structured concurrency to perform tasks in parallel. Also the concurrentPerform function is not an asynchronous operation, it’ll block the caller thread until all the work is done within the block.
Working with async/await means that the CPU can work on a different task when awaits for a given operation. Every await call is a potential suspension point, where the function can give up the thread and the CPU can perform other tasks until the awaited function resumes & returns with the necessary value. The new Swift concurrency APIs are built on top a cooperative thread pool, where each CPU core has just the right amount of threads and the suspension & continuation happens “virtually” with the help of the language runtime. This is far more efficient than actual context switching, and also means that when you interact with async functions and await for a function the CPU can work on other tasks instead of blocking the thread on the call side.
So back to the example code, since actors have to protect their internal states, they only allows us to access members asynchronously when you reference from async functions or outside the actor. This is very similar to the case when we had to use the lockQueue.sync to protect our read / write functions, but instead of giving the ability to the system to perform other tasks on the thread, we’ve entirely blocked it with the sync call. Now with await we can give up the thread and allow others to perform operations using it and when the time comes the function can resume.
Inside the task group we can perform our tasks asynchronously, but since we’re accessing the actor function (from an async context / outside the actor) we have to use the await keyword before the set call, even if the function is not marked with the async keyword.
The system knows that we’re referencing the actor’s property using a different context and we have to perform this operation always isolated to eliminate data races. By converting the function to an async call we give the system a chance to perform the operation on the actor’s executor. Later on we’ll be able to define custom executors for our actors, but this feature is not available yet.
Currently there is a global executor implementation (associated with each actor) that enqueues the tasks and runs them one-by-one, if a task is not running (no contention) it’ll be scheduled for execution (based on the priority) otherwise (if the task is already running / under contention) the system will just pick-up the message without blocking.
The funny thing is that this does not necessary means that the exact same thread… 😅
import Foundation
+
First of all, actors are reference types, just like classes. They can have methods, properties, they can implement protocols, but they don’t support inheritance.
NOTE: Since actors are closely related to the newly introduced async/await concurrency APIs in Swift you should be familiar with that concept too if you want to understand how they work.
The very first big difference is that we don’t need to provide a lock mechanism anymore in order to provide read or write access to our private storage property. This means that we can safely access actor properties within the actor using a synchronous way. Members are isolated by default, so there is a guarantee (by the compiler) that we can only access them using the same context.
What’s going on with the new Task API and all the await keywords? 🤔
Well, the Dispatch.concurrentPerform call is part of a parallelism API and Swift 5.5 introduced concurrency instead of parallelism, we have to move away from regular queues and use structured concurrency to perform tasks in parallel. Also the concurrentPerform function is not an asynchronous operation, it’ll block the caller thread until all the work is done within the block.
Working with async/await means that the CPU can work on a different task when awaits for a given operation. Every await call is a potential suspension point, where the function can give up the thread and the CPU can perform other tasks until the awaited function resumes & returns with the necessary value. The new Swift concurrency APIs are built on top a cooperative thread pool, where each CPU core has just the right amount of threads and the suspension & continuation happens “virtually” with the help of the language runtime. This is far more efficient than actual context switching, and also means that when you interact with async functions and await for a function the CPU can work on other tasks instead of blocking the thread on the call side.
So back to the example code, since actors have to protect their internal states, they only allows us to access members asynchronously when you reference from async functions or outside the actor. This is very similar to the case when we had to use the lockQueue.sync to protect our read / write functions, but instead of giving the ability to the system to perform other tasks on the thread, we’ve entirely blocked it with the sync call. Now with await we can give up the thread and allow others to perform operations using it and when the time comes the function can resume.
Inside the task group we can perform our tasks asynchronously, but since we’re accessing the actor function (from an async context / outside the actor) we have to use the await keyword before the set call, even if the function is not marked with the async keyword.
The system knows that we’re referencing the actor’s property using a different context and we have to perform this operation always isolated to eliminate data races. By converting the function to an async call we give the system a chance to perform the operation on the actor’s executor. Later on we’ll be able to define custom executors for our actors, but this feature is not available yet.
Currently there is a global executor implementation (associated with each actor) that enqueues the tasks and runs them one-by-one, if a task is not running (no contention) it’ll be scheduled for execution (based on the priority) otherwise (if the task is already running / under contention) the system will just pick-up the message without blocking.
The funny thing is that this does not necessary means that the exact same thread… 😅
import Foundation
extension Thread {
var number: String {
diff --git a/docs/swift-on-the-server-in-2020/index.html b/docs/swift-on-the-server-in-2020/index.html
index ad4bf08..5d8e282 100644
--- a/docs/swift-on-the-server-in-2020/index.html
+++ b/docs/swift-on-the-server-in-2020/index.html
@@ -108,7 +108,7 @@ Swift on the Server in 2020
Why choose Swift as a backend language in 2020? What are the available frameworks to build your server? Let me guide you.
- Swift is everywhere
Swift is a modern, interactive, type-safe programming language with performance in mind. It is one of the fastest growing programming languages in the industry. Swift has gained so much attraction over the last few years, some people love it, others might hate it, but one thing is for sure:
Swift is here to stay for a very long time.
Swift is as easy to use as a scripting language, without sacrificing any performance. This means C-like performance in most of the cases, which should be more than enough for most of the people.
In the beginning Swift was considered as a replacement for Objective-C for Apple platforms, but don’t get fooled. Swift is a generic purpose programming language, so you can build anything with it. It runs on embedded systems, of course you can make iOS apps and great desktop class applications using Swift, you can use it to write great Machine Learning algorithms (TensorFlow), build backend servers, even experimental operating systems, but let me just stop here. ✋🏻
Swift is everywhere, it has changed a lot, but now we can consider it as a mature programming language. There are still some missing / annoying things, it’d be great to have more (lightweight) tools (e.g. you still can’t run tests for packages without installing Xcode), but we are slowly getting there. Apple will build a new generation of hardware devices using Apple Silicon, they’ve put a lot of effort to rewrite the underlying software components (I bet there is plenty of Swift code already), so I’d say this is just the beginning of the story. 🚀
Swift Server Work Group (SSWG)
The SSWG is on the right track. In the beginning I think they dictated a very slow pace, but now it seems like they know how to work together in an efficient way. It is worth to mention that this group has some very talented people from big companies, such as Apple, Amazon, MongoDB or the Vapor community. They are responsible for priorizing “what needs to be done” for the server community, they run an incubation process for backend related packages and channel feedbacks to the Swift Core Team so they can quickly address the underlying issues in the language itself.
Unfortunately in the very end of last year, IBM announced that they are moving away from Swift on the server, but it turns out that the community is going to be able to save and maintain the Kitura web framework. Anyway, Vapor 4 is almost ready if you are looking for an alternative solution. 🙈
Later on this year Tom Doron, member of the Swift Core Team and the Swift Server Work Group, announced that more Linux distributions are going to be supported. This is a great news, you can now download official Swift releases for seven different platform. Nightly and official Docker images are also available for Swift, this was announced by Mishal Shah on the Swift Forums.
Language stability
As Swift evolved more and more great features were added to the language. Those implementations also pushed forward server side projects. When Swift was open sourced back in 2015 (it became available for Linux) the standard library, Foundation were quite buggy and many language features that we have today were completely missing. Fortunately this changed a lot. I’d say Swift 5 is the first version of the language that was stable enough to build a reliable backend server. 🤖
With Swift 5.0 ABI stability has arrived, so finally we were able to build an app without the entire standard library and runtime included in the binary. We still had to wait about half a year for module stability, that arrived with the release of Swift 5.1 in late 2019. If you are interested in developing a framework or a library, you should also read about Library Evolution in Swift.
Swift Package Manager
The SPM library is here with us for quite a long time now, but in the beginning we weren’t able to use it for AppleOS platforms. Xcode 11 finally brought us a complete integration and developers started to use SPM to integrate third party dependencies with iOS apps. Sorry that I have to say this, but currently SPM is half-baked. We will only be able to ship binary dependencies and resources when Swift 5.3 will be released. In the beginning SPM was clearly designed to help boosting open source Swift packages, libraries and tools mostly on the server side.
Honestly I think this approach was quite a success, the project clearly had some issues in the beginning, but eventually SPM will become a de-facto tool for most of us. I’m quite sure that the authors are putting tremendous effort to make this project amazing and they need time to solve the hard parts under the hood (dependency resolution, etc.), so we (regular Swift developers) can integrate our projects with external packages in a pleasant way. 🙏
What do I miss from SPM? Well, I’d like to be able to update just one package in Xcode instead of refreshing the entire dependency tree. When you work with multiple dependencies this could take a while (especially when a dependency is quite big). Ok, ok, this is more like an Xcode feature, but here is another one: I’d like to be able to build and distrubute dynamic libraries via SPM. This way framework authors could provide a dynamic version that could be reused in multiple packages. I’m not the only one with this particular issue. Please help us. 😢
Swift packages for backend developers
Anyway, SPM is a great way to distribute Swift packages and I’m really glad that we have so many options to build a backend. Let me show you some of the most inspiring open source projects that you can use to develop your server application. Most of these libraries are backed by Apple, so they won’t go anywhere, we can be sure that such a big organization will update and support them. Apple is using this stuff to build up the infrastructure for some cloud based platforms. ☁️
SwiftNIO
SwiftNIO is a cross-platform asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. In other words it’s an extremely performant low-level network framework that you can use to build your own server or client using a non-blocking approach.
It’s like Netty, but written for Swift.
You can find plenty of great tutorials, for example how to build a text modifying server or a practical guide for asynchronous problems even about how to make a clone called “microexpress” of the famous express web framework from the Node.js world.
You’ll also find great documentation about SwiftNIO, but I have to repeat myself, it is a very low level framework, so if don’t have prior network programming experience maybe it’s better to choose a high level framework such as Vapor or even a CMS written in Swift to begin with.
AsyncHTTPClient
If you are looking for a HTTP client library, the AsyncHTTPClient package can be a great candidate. The framework uses a non-blocking asynchronous model for request methods, it can also follow redirects, supports streaming body download, TLS and cookie parsing.
Swift AWS Lambda Runtime
A few months ago the Swift AWS Lambda Runtime package was introduced via the official Swift blog. If you want to develop serverless functions using the AWS Lambda service and the Swift programming language you have to take a closer look on this package. Fabian Fett wrote a great tutorial about getting started with Swift on AWS Lambda, also there is a WWDC20 session video about using Swift on AWS Lambda with Xcode. Honestly I had no time to play with this library, because I was mostly focusing on my CMS, but I can’t wait to go serverless using Swift. 🤔
AWS SDK Swift
The AWS SDK Swift library provides access to all AWS services. The 5th major version is almost feature complete, Adam Fowler recently made a blog post about the latest changes. Personally I was using this package to store images on AWS S3 and it worked like a charm. The only downside of having such a huge library is that it takes a pretty long time for SPM to fetch it as a dependency (I was only using S3, but still I had to load the entire package). Anyway, if your infrastructure highly depends on Amazon Web Services and you have to access most of the available solutions through Swift, this is the framework that you should pick. 😎
Swift Service Lifecycle
The Swift Service Lifecycle package is an elegant way to manage your server. It provides a basic mechanism to cleanly start up and shut down backend apps so you can free resources before exiting. It also provides a signal based shutdown hook, so you can listen to specific events.
For more info you should read the introduction blog post or the readme on GitHub.
Swift Cluster Membership
Apple recently introduced the Swift Cluster Membership repository. Honestly I don’t know much about the SWIM protocol, but it seems like it’s important of you want to build and manage a lifecycle of a distributed system. This library aims to help building clustered mutli-node environments with the help of Swift. For me, this is a completely new area, but I think it’s definitely an interesting stuff and I want to learn a lot about more this in the future. 🤓
Backtrace, Crypto, Metrics, Log and more…
Here are a few other libraries that you can utilize when you build a backend server using Swift.
The first one helps you to print a crash backtrace when your app fails.
Crypto is a cross-platform Swift implementation of Apple’s CryptoKit framework. It is quite a young project announced by Cory Benfield at the dotSwift conference, but it the project already features most of the functionalities from CryptoKit.
If you have a server side or cross platform Swift application you might want to measure some of your code. The Swift Metrics API package is a great way to emit such records.
There is an offical Logging API package for Swift that you can use to persist log messages in files or simply print out various messages to the console using a standardized way.
In the beginning of the article I mentioned that SSWG has an incubation process for server related packages. If you have a specific need, it is always a good idea to check the status of the currently available projects on the official Swift programming language website. 🔍
Vapor
Vapor is the most popular web framework written in Swift. If you want to get started with Vapor 4 you should definitely take a look at my Practical Server Side Swift book, or you can use all the FREE resources on my blog.
The future of Swift (on the server)
As you can see the server side Swift infrastructure is evolving real quick. Swift is available on more and more platforms (Windows support is coming next), plus the language itself is on a good way and it has the potential to “fulfill the prophecy”. 🌎 💪 😅
Apart from the missing parts, such as the long awaited (pun intended) async / await feature, on the long term Swift 6 is definitely going to be a huge milestone. Don’t expect that this will happen anytime soon, we still need a 5.3 release before and who knows, maybe Swift 5.4 and more.
So back to the original question…
Why choose Swift in 2020 as a backend language?
I know better: why choose Swift as your main language? Well, Swift is modern, fast and safe. It can run on many platforms and it has a great learning curve. Swift has a bright future not because of Apple, but because the huge community that loves (and sometimes hate) using it.
NOTE: You don’t need an expensive Apple device to start learning Swift. You can build your own apps using a PC with Linux. You can even get started using a small & cheap Raspberry PI, a SwiftIO machine or maybe this online Swift playground can do the job. 💡
I don’t want to compare Swift to another languages, let’s just say I think of it as a love child of JavaScript & C. I hope this analogy pretty much explains it (in a good way). 😂
+ Swift is everywhere
Swift is a modern, interactive, type-safe programming language with performance in mind. It is one of the fastest growing programming languages in the industry. Swift has gained so much attraction over the last few years, some people love it, others might hate it, but one thing is for sure:
Swift is here to stay for a very long time.
Swift is as easy to use as a scripting language, without sacrificing any performance. This means C-like performance in most of the cases, which should be more than enough for most of the people.
In the beginning Swift was considered as a replacement for Objective-C for Apple platforms, but don’t get fooled. Swift is a generic purpose programming language, so you can build anything with it. It runs on embedded systems, of course you can make iOS apps and great desktop class applications using Swift, you can use it to write great Machine Learning algorithms (TensorFlow), build backend servers, even experimental operating systems, but let me just stop here. ✋🏻
Swift is everywhere, it has changed a lot, but now we can consider it as a mature programming language. There are still some missing / annoying things, it’d be great to have more (lightweight) tools (e.g. you still can’t run tests for packages without installing Xcode), but we are slowly getting there. Apple will build a new generation of hardware devices using Apple Silicon, they’ve put a lot of effort to rewrite the underlying software components (I bet there is plenty of Swift code already), so I’d say this is just the beginning of the story. 🚀
Swift Server Work Group (SSWG)
The SSWG is on the right track. In the beginning I think they dictated a very slow pace, but now it seems like they know how to work together in an efficient way. It is worth to mention that this group has some very talented people from big companies, such as Apple, Amazon, MongoDB or the Vapor community. They are responsible for priorizing “what needs to be done” for the server community, they run an incubation process for backend related packages and channel feedbacks to the Swift Core Team so they can quickly address the underlying issues in the language itself.
Unfortunately in the very end of last year, IBM announced that they are moving away from Swift on the server, but it turns out that the community is going to be able to save and maintain the Kitura web framework. Anyway, Vapor 4 is almost ready if you are looking for an alternative solution. 🙈
Later on this year Tom Doron, member of the Swift Core Team and the Swift Server Work Group, announced that more Linux distributions are going to be supported. This is a great news, you can now download official Swift releases for seven different platform. Nightly and official Docker images are also available for Swift, this was announced by Mishal Shah on the Swift Forums.
Language stability
As Swift evolved more and more great features were added to the language. Those implementations also pushed forward server side projects. When Swift was open sourced back in 2015 (it became available for Linux) the standard library, Foundation were quite buggy and many language features that we have today were completely missing. Fortunately this changed a lot. I’d say Swift 5 is the first version of the language that was stable enough to build a reliable backend server. 🤖
With Swift 5.0 ABI stability has arrived, so finally we were able to build an app without the entire standard library and runtime included in the binary. We still had to wait about half a year for module stability, that arrived with the release of Swift 5.1 in late 2019. If you are interested in developing a framework or a library, you should also read about Library Evolution in Swift.
Swift Package Manager
The SPM library is here with us for quite a long time now, but in the beginning we weren’t able to use it for AppleOS platforms. Xcode 11 finally brought us a complete integration and developers started to use SPM to integrate third party dependencies with iOS apps. Sorry that I have to say this, but currently SPM is half-baked. We will only be able to ship binary dependencies and resources when Swift 5.3 will be released. In the beginning SPM was clearly designed to help boosting open source Swift packages, libraries and tools mostly on the server side.
Honestly I think this approach was quite a success, the project clearly had some issues in the beginning, but eventually SPM will become a de-facto tool for most of us. I’m quite sure that the authors are putting tremendous effort to make this project amazing and they need time to solve the hard parts under the hood (dependency resolution, etc.), so we (regular Swift developers) can integrate our projects with external packages in a pleasant way. 🙏
What do I miss from SPM? Well, I’d like to be able to update just one package in Xcode instead of refreshing the entire dependency tree. When you work with multiple dependencies this could take a while (especially when a dependency is quite big). Ok, ok, this is more like an Xcode feature, but here is another one: I’d like to be able to build and distrubute dynamic libraries via SPM. This way framework authors could provide a dynamic version that could be reused in multiple packages. I’m not the only one with this particular issue. Please help us. 😢
Swift packages for backend developers
Anyway, SPM is a great way to distribute Swift packages and I’m really glad that we have so many options to build a backend. Let me show you some of the most inspiring open source projects that you can use to develop your server application. Most of these libraries are backed by Apple, so they won’t go anywhere, we can be sure that such a big organization will update and support them. Apple is using this stuff to build up the infrastructure for some cloud based platforms. ☁️
SwiftNIO
SwiftNIO is a cross-platform asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. In other words it’s an extremely performant low-level network framework that you can use to build your own server or client using a non-blocking approach.
It’s like Netty, but written for Swift.
You can find plenty of great tutorials, for example how to build a text modifying server or a practical guide for asynchronous problems even about how to make a clone called “microexpress” of the famous express web framework from the Node.js world.
You’ll also find great documentation about SwiftNIO, but I have to repeat myself, it is a very low level framework, so if don’t have prior network programming experience maybe it’s better to choose a high level framework such as Vapor or even a CMS written in Swift to begin with.
AsyncHTTPClient
If you are looking for a HTTP client library, the AsyncHTTPClient package can be a great candidate. The framework uses a non-blocking asynchronous model for request methods, it can also follow redirects, supports streaming body download, TLS and cookie parsing.
Swift AWS Lambda Runtime
A few months ago the Swift AWS Lambda Runtime package was introduced via the official Swift blog. If you want to develop serverless functions using the AWS Lambda service and the Swift programming language you have to take a closer look on this package. Fabian Fett wrote a great tutorial about getting started with Swift on AWS Lambda, also there is a WWDC20 session video about using Swift on AWS Lambda with Xcode. Honestly I had no time to play with this library, because I was mostly focusing on my CMS, but I can’t wait to go serverless using Swift. 🤔
AWS SDK Swift
The AWS SDK Swift library provides access to all AWS services. The 5th major version is almost feature complete, Adam Fowler recently made a blog post about the latest changes. Personally I was using this package to store images on AWS S3 and it worked like a charm. The only downside of having such a huge library is that it takes a pretty long time for SPM to fetch it as a dependency (I was only using S3, but still I had to load the entire package). Anyway, if your infrastructure highly depends on Amazon Web Services and you have to access most of the available solutions through Swift, this is the framework that you should pick. 😎
Swift Service Lifecycle
The Swift Service Lifecycle package is an elegant way to manage your server. It provides a basic mechanism to cleanly start up and shut down backend apps so you can free resources before exiting. It also provides a signal based shutdown hook, so you can listen to specific events.
For more info you should read the introduction blog post or the readme on GitHub.
Swift Cluster Membership
Apple recently introduced the Swift Cluster Membership repository. Honestly I don’t know much about the SWIM protocol, but it seems like it’s important of you want to build and manage a lifecycle of a distributed system. This library aims to help building clustered mutli-node environments with the help of Swift. For me, this is a completely new area, but I think it’s definitely an interesting stuff and I want to learn a lot about more this in the future. 🤓
Backtrace, Crypto, Metrics, Log and more…
Here are a few other libraries that you can utilize when you build a backend server using Swift.
The first one helps you to print a crash backtrace when your app fails.
Crypto is a cross-platform Swift implementation of Apple’s CryptoKit framework. It is quite a young project announced by Cory Benfield at the dotSwift conference, but it the project already features most of the functionalities from CryptoKit.
If you have a server side or cross platform Swift application you might want to measure some of your code. The Swift Metrics API package is a great way to emit such records.
There is an offical Logging API package for Swift that you can use to persist log messages in files or simply print out various messages to the console using a standardized way.
In the beginning of the article I mentioned that SSWG has an incubation process for server related packages. If you have a specific need, it is always a good idea to check the status of the currently available projects on the official Swift programming language website. 🔍
Vapor
Vapor is the most popular web framework written in Swift. If you want to get started with Vapor 4 you should definitely take a look at my Practical Server Side Swift book, or you can use all the FREE resources on my blog.
The future of Swift (on the server)
As you can see the server side Swift infrastructure is evolving real quick. Swift is available on more and more platforms (Windows support is coming next), plus the language itself is on a good way and it has the potential to “fulfill the prophecy”. 🌎 💪 😅
Apart from the missing parts, such as the long awaited (pun intended) async / await feature, on the long term Swift 6 is definitely going to be a huge milestone. Don’t expect that this will happen anytime soon, we still need a 5.3 release before and who knows, maybe Swift 5.4 and more.
So back to the original question…
Why choose Swift in 2020 as a backend language?
I know better: why choose Swift as your main language? Well, Swift is modern, fast and safe. It can run on many platforms and it has a great learning curve. Swift has a bright future not because of Apple, but because the huge community that loves (and sometimes hate) using it.
NOTE: You don’t need an expensive Apple device to start learning Swift. You can build your own apps using a PC with Linux. You can even get started using a small & cheap Raspberry PI, a SwiftIO machine or maybe this online Swift playground can do the job. 💡
I don’t want to compare Swift to another languages, let’s just say I think of it as a love child of JavaScript & C. I hope this analogy pretty much explains it (in a good way). 😂
diff --git a/docs/swift-package-manager-tutorial/index.html b/docs/swift-package-manager-tutorial/index.html
index 6ac3c0f..75ec7d6 100644
--- a/docs/swift-package-manager-tutorial/index.html
+++ b/docs/swift-package-manager-tutorial/index.html
@@ -176,7 +176,7 @@ Swift Package Manager basics
First
main.run()
Build the project with swift build and run the newly created app with one extra name parameter. Hopefully you’ll see something like this.
swift run my-cmd guest
# Hello, Guest!
-
So we just made a brand new executable target, however if you’d like to expose your targets for other packages, you should define them as products as well. If you open the manifest file for the library, you’ll see that there is a product defined from the library target. This way the package manager can link the product dependencies based on the given product name.
NOTE: You can define static or dynamic libraries, however it is recommended to use automatic so the SPM can decide appropriate linkage.
// swift-tools-version:5.2
+
So we just made a brand new executable target, however if you’d like to expose your targets for other packages, you should define them as products as well. If you open the manifest file for the library, you’ll see that there is a product defined from the library target. This way the package manager can link the product dependencies based on the given product name.
NOTE: You can define static or dynamic libraries, however it is recommended to use automatic so the SPM can decide appropriate linkage.
// swift-tools-version:5.2
import PackageDescription
let package = Package(
diff --git a/docs/swift-visitor-design-pattern/index.html b/docs/swift-visitor-design-pattern/index.html
index a0cbf92..0a5dd9f 100644
--- a/docs/swift-visitor-design-pattern/index.html
+++ b/docs/swift-visitor-design-pattern/index.html
@@ -100,7 +100,7 @@
Swift visitor design pattern
diff --git a/docs/table-joins-in-fluent-4/index.html b/docs/table-joins-in-fluent-4/index.html
index 148fca5..640da6b 100644
--- a/docs/table-joins-in-fluent-4/index.html
+++ b/docs/table-joins-in-fluent-4/index.html
@@ -205,7 +205,7 @@ Database models
Fluent is a Joining database tables using Fluent 4
We have to run the InitialMigration script before we start using the database. This can be done by passing a command argument to the backend application or we can achieve the same thing by calling the autoMigrate() method on the application instance.
NOTE: For the sake of simplicity I’m going to use the wait method instead of async Futures & Promises, this is fine for demo purposes, but in a real-world server application you should never block the current event loop with the wait method.
This is one possible setup of our dummy database using an SQLite storage, but of course you can use PostgreSQL, MySQL or even MariaDB through the available Fluent SQL drivers. 🚙
public func configure(_ app: Application) throws {
+
If you want to avoid invalid data in the tables, you should always use the foreign key and unique constraints. A foreign key can be used to check if the referenced identifier exists in the related table and the unique constraint will make sure that only one row can exists from a given field.
Joining database tables using Fluent 4
We have to run the InitialMigration script before we start using the database. This can be done by passing a command argument to the backend application or we can achieve the same thing by calling the autoMigrate() method on the application instance.
NOTE: For the sake of simplicity I’m going to use the wait method instead of async Futures & Promises, this is fine for demo purposes, but in a real-world server application you should never block the current event loop with the wait method.
This is one possible setup of our dummy database using an SQLite storage, but of course you can use PostgreSQL, MySQL or even MariaDB through the available Fluent SQL drivers. 🚙
public func configure(_ app: Application) throws {
app.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite)
diff --git a/docs/tags/design-pattern/index.html b/docs/tags/design-pattern/index.html
index 9210539..29bb612 100644
--- a/docs/tags/design-pattern/index.html
+++ b/docs/tags/design-pattern/index.html
@@ -140,7 +140,7 @@
Swift visitor design pattern
@@ -519,7 +519,7 @@
- · 1 min read
+ · 2 min read
UIKit init patterns
diff --git a/docs/tags/ios/index.html b/docs/tags/ios/index.html
index 8d51438..14d2170 100644
--- a/docs/tags/ios/index.html
+++ b/docs/tags/ios/index.html
@@ -270,7 +270,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
@@ -471,15 +471,16 @@
- · 7 min read
+ · 2 min read
- The ultimate Combine framework tutorial in Swift
+ UIKit init patterns
- Get started with the brand new declarative Combine framework in practice using Swift. I'll teach you all the goodies from zero to hero.
+ Learn about the initialization process of the two well known classes in UIKit. Say hello to UIViewcontroller, and UIView init patterns.
@@ -515,16 +516,15 @@
- · 1 min read
+ · 7 min read
- UIKit init patterns
+ The ultimate Combine framework tutorial in Swift
- Learn about the initialization process of the two well known classes in UIKit. Say hello to UIViewcontroller, and UIView init patterns.
+ Get started with the brand new declarative Combine framework in practice using Swift. I'll teach you all the goodies from zero to hero.
diff --git a/docs/tags/server/index.html b/docs/tags/server/index.html
index afdbad3..9c0cca9 100644
--- a/docs/tags/server/index.html
+++ b/docs/tags/server/index.html
@@ -360,7 +360,7 @@
- · 7 min read
+ · 8 min read
Declarative unit tests for Vapor
@@ -559,7 +559,7 @@
Websockets for beginners using Vapor 4 and Vanilla JavaScript
@@ -779,7 +779,7 @@
- · 17 min read
+ · 18 min read
Beginner's guide to Server side Swift using Vapor 4
diff --git a/docs/tags/swift/index.html b/docs/tags/swift/index.html
index dd18213..0b32efa 100644
--- a/docs/tags/swift/index.html
+++ b/docs/tags/swift/index.html
@@ -224,7 +224,7 @@
- · 3 min read
+ · 4 min read
How to use a Swift library in C
@@ -245,7 +245,7 @@
- · 5 min read
+ · 6 min read
Building tree data structures in Swift
@@ -434,7 +434,7 @@
- · 7 min read
+ · 8 min read
Memory layout in Swift
@@ -625,7 +625,7 @@
- · 4 min read
+ · 5 min read
What's new in Swift 5.3?
@@ -836,7 +836,7 @@
- · 10 min read
+ · 11 min read
Deep dive into Swift frameworks
@@ -920,12 +920,12 @@
- Everything about public and private Swift attributes
+ Result builders in Swift
- Have you ever heard about Swift language attributes? In this article I'm trying to gather all the @ annotations and their meanings.
+ If you want to make a result builder in Swift, this article will help you to deal with the most common cases when creating a DSL.
- Result builders in Swift
+ Everything about public and private Swift attributes
- If you want to make a result builder in Swift, this article will help you to deal with the most common cases when creating a DSL.
+ Have you ever heard about Swift language attributes? In this article I'm trying to gather all the @ annotations and their meanings.
Custom UIView subclass from a xib file
@@ -529,15 +529,17 @@
- · 6 min read
+ · 2 min read
- How to create reusable views for modern collection views?
+ UIKit init patterns
- A quick intro to modern collection views using compositional layout, diffable data source and reusable view components.
+ Learn about the initialization process of the two well known classes in UIKit. Say hello to UIViewcontroller, and UIView init patterns.
@@ -550,12 +552,12 @@
- · 7 min read
+ · 2 min read
- The ultimate Combine framework tutorial in Swift
+ Top 20 iOS libraries written in Swift
- Get started with the brand new declarative Combine framework in practice using Swift. I'll teach you all the goodies from zero to hero.
+ I gathered the best open source Swift frameworks on github that will help you to speed up mobile application development in 2019.
- Top 20 iOS libraries written in Swift
+ The ultimate Combine framework tutorial in Swift
- I gathered the best open source Swift frameworks on github that will help you to speed up mobile application development in 2019.
+ Get started with the brand new declarative Combine framework in practice using Swift. I'll teach you all the goodies from zero to hero.
- UIKit init patterns
+ How to create reusable views for modern collection views?
- Learn about the initialization process of the two well known classes in UIKit. Say hello to UIViewcontroller, and UIView init patterns.
+ A quick intro to modern collection views using compositional layout, diffable data source and reusable view components.
diff --git a/docs/tags/vapor/index.html b/docs/tags/vapor/index.html
index f5bc2eb..341c06b 100644
--- a/docs/tags/vapor/index.html
+++ b/docs/tags/vapor/index.html
@@ -273,7 +273,7 @@
- · 7 min read
+ · 8 min read
Declarative unit tests for Vapor
@@ -472,7 +472,7 @@
Websockets for beginners using Vapor 4 and Vanilla JavaScript
@@ -692,7 +692,7 @@
- · 17 min read
+ · 18 min read
Beginner's guide to Server side Swift using Vapor 4
diff --git a/docs/the-anatomy-of-vapor-commands/index.html b/docs/the-anatomy-of-vapor-commands/index.html
index aad38c5..ecd2d0c 100644
--- a/docs/the-anatomy-of-vapor-commands/index.html
+++ b/docs/the-anatomy-of-vapor-commands/index.html
@@ -130,7 +130,7 @@ The Vapor toolbox
The very first thing I want
# revert last migration
swift run Run migrate --revert
-
The cli will show you what needs to be done in order to keep your DB up-to-date. You can double check everything one more time before you proceed, or you can skip the entire confirmation dialog by using the --auto-migrate option. Be extremely careful with auto migrations! ⚠️
Log levels
You might have noticed that there are a bunch of Vapor messages in your console. Well, the good news is that you can filter them by log level. There are two ways of doing this. The first option is to provide a log flag with one of the following values:
- trace
- debug
- info
- notice
- warning
- error
- critical
WARN: The --log flag has no short variant, don’t try to use -l.
If you want to trace, debug and info logs, you can run the app like this:
# set log level
+
The cli will show you what needs to be done in order to keep your DB up-to-date. You can double check everything one more time before you proceed, or you can skip the entire confirmation dialog by using the --auto-migrate option. Be extremely careful with auto migrations! ⚠️
Log levels
You might have noticed that there are a bunch of Vapor messages in your console. Well, the good news is that you can filter them by log level. There are two ways of doing this. The first option is to provide a log flag with one of the following values:
- trace
- debug
- info
- notice
- warning
- error
- critical
WARN: The --log flag has no short variant, don’t try to use -l.
If you want to trace, debug and info logs, you can run the app like this:
# set log level
swift run Run --log notice
The second option is to set a LOG_LEVEL variable before you run the app.
# set log level using a variable
LOG_LEVEL=notice swift run Run
@@ -153,7 +153,7 @@ The Vapor toolbox
The very first thing I want
# run in production mode using the .env file
swift run Run --env production
swift run Run -e prod
-
NOTE: It is possible to store environmental variables in a dot env file. The .env.development file will be loeaded in development mode and the .env file in production mode. You can also use the .env.testing file for the test environment.
You can also override environmental variables with a local variable, like the way we defined the LOG_LEVEL before. So let’s say if you have a DB_URL in your production .env file, but you still want to use the dev database, you can run Vapor like this:
DB_URL="postgres://myuser:mypass@localhost:5432/mydb" swift run Run --env production
+
NOTE: It is possible to store environmental variables in a dot env file. The .env.development file will be loeaded in development mode and the .env file in production mode. You can also use the .env.testing file for the test environment.
You can also override environmental variables with a local variable, like the way we defined the LOG_LEVEL before. So let’s say if you have a DB_URL in your production .env file, but you still want to use the dev database, you can run Vapor like this:
DB_URL="postgres://myuser:mypass@localhost:5432/mydb" swift run Run --env production
Environment variables are super cool, you should play around with them to get familiar.
Routes
This is very handy command to quickly display all the connected endpoints that your app has.
# prints all the routes information
swift run Run routes
diff --git a/docs/the-swift-compiler-for-beginners/index.html b/docs/the-swift-compiler-for-beginners/index.html
index a099158..153987e 100644
--- a/docs/the-swift-compiler-for-beginners/index.html
+++ b/docs/the-swift-compiler-for-beginners/index.html
@@ -203,7 +203,7 @@ Compiling Swift source files
The mo
-target-sdk-version 11.1 \
-module-name main \
-o main.o
-
As you can see we just tell Swift to turn our primary input file into an intermediate output file. Of course the whole story is way more complicated involving the LLVM compiler infrastructure, there is a great article about a brief overview of the Swift compiler, that you should read if you want more details about the phases and tools, such as the parser, analyzer etc. 🤔
NOTE: Compilers are complicated, for now it’s more than enough if you take away this one simple thing about the Swift compiler: it turns your source files into intermediate object files.
Before we could run our final program code, those temporary object files needs to be combined together into a single executable. This is what linkers can do, they verify object files and resolve underlying dependencies by linking together various dependencies.
Dependencies can be linked together in a static or dynamic way. For now lets just stay that static linking means that we literally copy & paste code into the final binary file, on the other hand dynamic linking means that libraries will be resolved at runtime. I have a pretty detailed article about Swift frameworks and related command line tools that you can use to examine them.
In our case the linker command is ld and we feed it with our object files.
ld \
+
As you can see we just tell Swift to turn our primary input file into an intermediate output file. Of course the whole story is way more complicated involving the LLVM compiler infrastructure, there is a great article about a brief overview of the Swift compiler, that you should read if you want more details about the phases and tools, such as the parser, analyzer etc. 🤔
NOTE: Compilers are complicated, for now it’s more than enough if you take away this one simple thing about the Swift compiler: it turns your source files into intermediate object files.
Before we could run our final program code, those temporary object files needs to be combined together into a single executable. This is what linkers can do, they verify object files and resolve underlying dependencies by linking together various dependencies.
Dependencies can be linked together in a static or dynamic way. For now lets just stay that static linking means that we literally copy & paste code into the final binary file, on the other hand dynamic linking means that libraries will be resolved at runtime. I have a pretty detailed article about Swift frameworks and related command line tools that you can use to examine them.
In our case the linker command is ld and we feed it with our object files.
ld \
point.o \
main.o \
libclang_rt.osx.a \
@@ -216,7 +216,7 @@ Compiling Swift source files
The mo
-platform_version macos 11.0.0 11.1.0 \
-no_objc_category_merging \
-o point-app
-
I know, there are plenty of unknown flags involved here as well, but in 99% of the cases you don’t have to directly interact with these things. This whole article is all about trying to understand the “dark magic” that produces games, apps and all sort of fun things for our computers, phones and other type of gadgets. These core components makes possible to build amazing software. ❤️
NOTE: Just remember this about the linker (ld command): it will use the object files (prepared by the compiler) and it’ll create the final product (library or executable) by combining every resource (object files and related libraries) together.
It can be real hard to understand these things at first sight, and you can live without them, build great programs without ever touching the compiler or the linker. Why bother? Well, I’m not saying that you’ll become a better developer if you start with the basics, but you can extend your knowledge with something that you use on a daily basis as a computer programmer. 💡
+
I know, there are plenty of unknown flags involved here as well, but in 99% of the cases you don’t have to directly interact with these things. This whole article is all about trying to understand the “dark magic” that produces games, apps and all sort of fun things for our computers, phones and other type of gadgets. These core components makes possible to build amazing software. ❤️
NOTE: Just remember this about the linker (ld command): it will use the object files (prepared by the compiler) and it’ll create the final product (library or executable) by combining every resource (object files and related libraries) together.
It can be real hard to understand these things at first sight, and you can live without them, build great programs without ever touching the compiler or the linker. Why bother? Well, I’m not saying that you’ll become a better developer if you start with the basics, but you can extend your knowledge with something that you use on a daily basis as a computer programmer. 💡
diff --git a/docs/the-swift-package-manifest-file/index.html b/docs/the-swift-package-manifest-file/index.html
index e546544..36f7b30 100644
--- a/docs/the-swift-package-manifest-file/index.html
+++ b/docs/the-swift-package-manifest-file/index.html
@@ -108,7 +108,7 @@ The Swift package manifest file
This article is a complete Swift Package Manager cheatsheet for the package manifest file, using the latest Swift 5.2 tools version.
- NOTE: If you want to learn how to use the Swift Package Manager you should read my other article, because that is more like an introduction for those who have never worked with SPM yet.
Package types
There are multiple package types that you can create with the swift package init command. You can specify the --type flag with the following values: empty, library, executable, system-module, manifest. You can also define a custom package name through the --name flag.
- The empty package will create the default file structure without the sample code files.
- The library type will create a reusable library product template.
- The executable type will create a Swift application with an executable product definition in the package and a
main.swift file as a starting point. - The system-module type will create a wrapper around a system provided package, such as libxml, we’ll talk about this later on.
- The manifest type will only create a
Package.swift file without anything else.
The Package manifest file
Every single SPM project has this special file inside of it called Package.swift. I already wrote a post about how the package manager and the Swift toolchain works behind the scenes, this time we’re going to focus only on the manifest file itself. Let’s get started. 📦
Every single Package.swift file begins with a special comment line where you have to define the version of the used Swift tools. The latest version is quite different from the older ones.
// swift-tools-version:5.2
+ NOTE: If you want to learn how to use the Swift Package Manager you should read my other article, because that is more like an introduction for those who have never worked with SPM yet.
Package types
There are multiple package types that you can create with the swift package init command. You can specify the --type flag with the following values: empty, library, executable, system-module, manifest. You can also define a custom package name through the --name flag.
- The empty package will create the default file structure without the sample code files.
- The library type will create a reusable library product template.
- The executable type will create a Swift application with an executable product definition in the package and a
main.swift file as a starting point. - The system-module type will create a wrapper around a system provided package, such as libxml, we’ll talk about this later on.
- The manifest type will only create a
Package.swift file without anything else.
The Package manifest file
Every single SPM project has this special file inside of it called Package.swift. I already wrote a post about how the package manager and the Swift toolchain works behind the scenes, this time we’re going to focus only on the manifest file itself. Let’s get started. 📦
Every single Package.swift file begins with a special comment line where you have to define the version of the used Swift tools. The latest version is quite different from the older ones.
// swift-tools-version:5.2
Next you have to import the PackageDescription framework in order to define your Swift package. This framework contains the package manifest structure as Swift objects.
import PackageDescription
That’s it now you are ready to describe the package itself. Oh by the way you can change the version of the used tools, you can read more about this in the Package Manager usage docs.
Package
A package is just a bunch of Swift (or other) files. The manifest file is the description of what and how to build from those sources. Every single package should have a name, but this is not enough to actually generate something from it. You can only have exactly one package definition inside the file. This is the shortest and most useless one that you can create. 🙈
let package = Package(name: "myPackage")
The package name is going to be used when you are importing packages as dependencies, so name your pacages carefully. If you choose a reserved name by a system framework there can be issues with linking. If there’s a conflict you have to use static linking instead of dynamic. If you generate a project via the swift package generate-xcodeproj command that project will try to link everything dynamically, but if you open the Package.swift file using Xcode 11, the dependencies will be linked statically if this was not set explicitly in the product definition section.
Platform
A platform is basically an operating system with a given version that you can support.
let package = Package(
diff --git a/docs/the-ultimate-combine-framework-tutorial-in-swift/index.html b/docs/the-ultimate-combine-framework-tutorial-in-swift/index.html
index bd5aee6..7004bec 100644
--- a/docs/the-ultimate-combine-framework-tutorial-in-swift/index.html
+++ b/docs/the-ultimate-combine-framework-tutorial-in-swift/index.html
@@ -143,7 +143,7 @@ What is Combine?
Customize handling
// cancel subscription
//cancellable?.cancel()
-
You can start & stop the publisher any time you need by using the connect method.
NOTE: Combine has built-in support for cancellation. Both the sink and the assign methods are returning an object that you can store for later and you can call the cancel method on that AnyCancellable object to stop execution.
NotificationCenter
You can also subscribe to notifications by using publishers.
extension Notification.Name {
+
You can start & stop the publisher any time you need by using the connect method.
NOTE: Combine has built-in support for cancellation. Both the sink and the assign methods are returning an object that you can store for later and you can call the cancel method on that AnyCancellable object to stop execution.
NotificationCenter
You can also subscribe to notifications by using publishers.
extension Notification.Name {
static let example = Notification.Name("example")
}
@@ -388,7 +388,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/top-20-ios-libraries-of-2019/index.html b/docs/top-20-ios-libraries-of-2019/index.html
index ba51edb..77d9e86 100644
--- a/docs/top-20-ios-libraries-of-2019/index.html
+++ b/docs/top-20-ios-libraries-of-2019/index.html
@@ -190,7 +190,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/uicollectionview-cells-with-circular-images-plus-rotation-support/index.html b/docs/uicollectionview-cells-with-circular-images-plus-rotation-support/index.html
index a30feea..c7c2601 100644
--- a/docs/uicollectionview-cells-with-circular-images-plus-rotation-support/index.html
+++ b/docs/uicollectionview-cells-with-circular-images-plus-rotation-support/index.html
@@ -330,7 +330,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/uicollectionview-data-source-and-delegates-programmatically/index.html b/docs/uicollectionview-data-source-and-delegates-programmatically/index.html
index 35f3407..2f671a9 100644
--- a/docs/uicollectionview-data-source-and-delegates-programmatically/index.html
+++ b/docs/uicollectionview-data-source-and-delegates-programmatically/index.html
@@ -327,7 +327,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/uicolor-best-practices-in-swift/index.html b/docs/uicolor-best-practices-in-swift/index.html
index 45ea47f..8c5a34b 100644
--- a/docs/uicolor-best-practices-in-swift/index.html
+++ b/docs/uicolor-best-practices-in-swift/index.html
@@ -337,7 +337,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/uikit-init-patterns/index.html b/docs/uikit-init-patterns/index.html
index 15d6fbb..7d92098 100644
--- a/docs/uikit-init-patterns/index.html
+++ b/docs/uikit-init-patterns/index.html
@@ -100,7 +100,7 @@
UIKit init patterns
@@ -308,7 +308,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/uikit-loadview-vs-viewdidload/index.html b/docs/uikit-loadview-vs-viewdidload/index.html
index 6c92ce8..56c1dcd 100644
--- a/docs/uikit-loadview-vs-viewdidload/index.html
+++ b/docs/uikit-loadview-vs-viewdidload/index.html
@@ -270,7 +270,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/uitableview-tutorial-in-swift/index.html b/docs/uitableview-tutorial-in-swift/index.html
index 9d116a4..4ddfac5 100644
--- a/docs/uitableview-tutorial-in-swift/index.html
+++ b/docs/uitableview-tutorial-in-swift/index.html
@@ -585,7 +585,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/ultimate-uicollectionview-guide-with-ios-examples-written-in-swift/index.html b/docs/ultimate-uicollectionview-guide-with-ios-examples-written-in-swift/index.html
index fdad70e..c16a19c 100644
--- a/docs/ultimate-uicollectionview-guide-with-ios-examples-written-in-swift/index.html
+++ b/docs/ultimate-uicollectionview-guide-with-ios-examples-written-in-swift/index.html
@@ -540,7 +540,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/uniquely-identifying-views/index.html b/docs/uniquely-identifying-views/index.html
index 5873026..6e62157 100644
--- a/docs/uniquely-identifying-views/index.html
+++ b/docs/uniquely-identifying-views/index.html
@@ -234,7 +234,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/docs/urlsession-and-the-combine-framework/index.html b/docs/urlsession-and-the-combine-framework/index.html
index 43b19bf..197214d 100644
--- a/docs/urlsession-and-the-combine-framework/index.html
+++ b/docs/urlsession-and-the-combine-framework/index.html
@@ -301,7 +301,7 @@ Related posts
Custom UIView subclass from a xib file
diff --git a/docs/viper-best-practices-for-ios-developers/index.html b/docs/viper-best-practices-for-ios-developers/index.html
index 089ecd0..caf117d 100644
--- a/docs/viper-best-practices-for-ios-developers/index.html
+++ b/docs/viper-best-practices-for-ios-developers/index.html
@@ -108,7 +108,7 @@ VIPER best practices for iOS developers
In this tutorial I'm going to show you a complete guide about how to build a VIPER based iOS application, written entirely in Swift.
- Getting started with VIPER
First of all, you should read my previous (more theoretical) article about the VIPER architecture itself. It’s a pretty decent writing explaining all the VIPER components and memory management. I’ve also polished it a little bit, last week. ⭐️
The problem with that article however was that I haven’t show you the real deal, aka. the Swift code for implementing VIPER. Now after a full year of projects using this architecture I can finally share all my best practices with you.
So, let’s start by creating a brand new Xcode project, use the single view app template, name the project (VIPER best practices), use Swift and now you’re ready to take the next step of making an awesome “enterprise grade” iOS app.
Generating VIPER modules
Lesson 1: never create a module by hand, always use a code generator, because it’s a repetative task, it’s fuckin’ boring plus you should focus on more important things than making boilerplate code. You can use my lightweight module generator called:
WARN: This section is outdated, you should use the swift template repository.
Just download or clone the repository from GitHub. You can install the binary tool by running swift run install –with-templates. This will install the vipera app under /usr/local/bin/ and the basic templates under the ~/.vipera directory. You can use your own templates too, but for now I’ll work with the default one. 🔨
I usually start with a module called Main that’s the root view of the application. You can generate it by calling vipera Main in the project directory, so the generator can use the proper project name for the header comments inside the template files.
Clean up the project structure a little bit, by applying my conventions for Xcode, this means that resources goes to an Assets folder, and all the Swift files into the Sources directory. Nowadays I also change the AppDelegate.swift file, and I make a separate extension for the UIApplicationDelegate protocol.
Create a Modules group (with a physical folder too) under the Sources directory and move the newly generated Main module under that group. Now fix the project issues, by selecting the Info.plist file from the Assets folder for the current target. Also do remove the Main Interface, and after that you can safely delete the Main.storyboard and the ViewController.swift files, because we’re not going to need them at all.
Inside the AppDelegate.swift file, you have to set the Main module’s view controller as the root view controller, so it should look somewhat like this:
import UIKit
+ Getting started with VIPER
First of all, you should read my previous (more theoretical) article about the VIPER architecture itself. It’s a pretty decent writing explaining all the VIPER components and memory management. I’ve also polished it a little bit, last week. ⭐️
The problem with that article however was that I haven’t show you the real deal, aka. the Swift code for implementing VIPER. Now after a full year of projects using this architecture I can finally share all my best practices with you.
So, let’s start by creating a brand new Xcode project, use the single view app template, name the project (VIPER best practices), use Swift and now you’re ready to take the next step of making an awesome “enterprise grade” iOS app.
Generating VIPER modules
Lesson 1: never create a module by hand, always use a code generator, because it’s a repetative task, it’s fuckin’ boring plus you should focus on more important things than making boilerplate code. You can use my lightweight module generator called:
WARN: This section is outdated, you should use the swift template repository.
Just download or clone the repository from GitHub. You can install the binary tool by running swift run install –with-templates. This will install the vipera app under /usr/local/bin/ and the basic templates under the ~/.vipera directory. You can use your own templates too, but for now I’ll work with the default one. 🔨
I usually start with a module called Main that’s the root view of the application. You can generate it by calling vipera Main in the project directory, so the generator can use the proper project name for the header comments inside the template files.
Clean up the project structure a little bit, by applying my conventions for Xcode, this means that resources goes to an Assets folder, and all the Swift files into the Sources directory. Nowadays I also change the AppDelegate.swift file, and I make a separate extension for the UIApplicationDelegate protocol.
Create a Modules group (with a physical folder too) under the Sources directory and move the newly generated Main module under that group. Now fix the project issues, by selecting the Info.plist file from the Assets folder for the current target. Also do remove the Main Interface, and after that you can safely delete the Main.storyboard and the ViewController.swift files, because we’re not going to need them at all.
Inside the AppDelegate.swift file, you have to set the Main module’s view controller as the root view controller, so it should look somewhat like this:
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder {
diff --git a/docs/websockets-for-beginners-using-vapor-4-and-vanilla-javascript/index.html b/docs/websockets-for-beginners-using-vapor-4-and-vanilla-javascript/index.html
index 3401210..80d691f 100644
--- a/docs/websockets-for-beginners-using-vapor-4-and-vanilla-javascript/index.html
+++ b/docs/websockets-for-beginners-using-vapor-4-and-vanilla-javascript/index.html
@@ -100,7 +100,7 @@
Websockets for beginners using Vapor 4 and Vanilla JavaScript
diff --git a/docs/what-are-the-best-practices-to-learn-ios-swift-in-2020/index.html b/docs/what-are-the-best-practices-to-learn-ios-swift-in-2020/index.html
index 994813d..e900564 100644
--- a/docs/what-are-the-best-practices-to-learn-ios-swift-in-2020/index.html
+++ b/docs/what-are-the-best-practices-to-learn-ios-swift-in-2020/index.html
@@ -108,7 +108,7 @@ What are the best practices to learn iOS / Swift in 2020?
Are you learning iOS development? Looking for Swift best practices? This is the right place to start your journey as a mobile application developer.
- Hello Swift!
Learning a programming language is hard. Even after more than a decade of software developer experience I feel like that I’m only scratching the surface. I don’t know much about low level assembly code, I don’t know how to create 3D games using shaders and many more. Still we all learn something new every single day. It’s a life-long journey and the path is full with obstacles, but if you keep going forward you’ll find that there’s gold at the end of the road. I still love to create new stuff from literally nothing but plain code. 😍
Everyone can code
In the beginning it’ll feel like that you have to learn a million things, but you shouldn’t be afraid because time is your friend. Day-by-day you’ll learn something new that’ll help you moving forward to achieve your next goal. I believe that the most important thing here is to have fun. If you feel frustrated because you can’t understand something just ask for help or take a break. The Swift community a group of amazing people, everybody is really helpful, so if you choose this programming language to bring your ideas to life you’ll meet some great people.
Now let me show you what you’ll need to start your career as a Swift application developer. 👨💻
Hardware
The first thing you’ll need to start your Apple developer career is a Mac. Unfortunately Mac’s are quite expensive machines nowadays, also the current series of MacBooks (both Air’s and Pro’s) have the completely broken butterfly keyboard mechanism. Hopefully this will change real soon.
I’d say that you should go with pre-butterfly models, you can look for the secondary market if you want to have a cheap deal. Otherwise you can go with a Mac mini, but if you buy one you should think about the extra expenses such as the monitor, keyboard & mouse.
If you have unlimited money, you should go with some high-end device like the new MacBook Pro 16”, iMac Pro or simply buy a Mac Pro. Nevertheless you should always choose a machine with an SSD. It’s kind of a shame that in 2020 a base iMac comes with a ridiculously slow HDD.
Another option is to build a hackintosh, but IMHO that’s the worst that you can do. You won’t get the same experience, plus you will struggle a lot fighting the system.
NOTE: You might heard rumors that you’re going to be just fine with an iPad & Swift playgrounds. Honestly that’s just not the case. You can play around and learn the Swift programming language even with a Linux machine, but if you want to make your own iOS / iPadOS / macOS / watchOS apps, you’ll need a Mac for sure.
Software
So you’ve got a decent Mac. Let’s see what kind of software will you need if you want to start developing iOS apps. You might heard that Apple’s operating system is macOS. First of all, if you never used a mac before, you should get familiar with the system itself. When I bought my very first MacBook Pro, it took me about a week to get used to all the apps, system shortcuts and everything else.
If you don’t want to figure out everything for yourself, you came to the right place. Let me walk you through of every single app, tool that I’m using to my work as a professional mobile / backend developer.
Terminal
The most important thing that you should get used to is the Terminal (console) application. If you never heard about terminals before you should simply look for a beginner’s guide tutorial, but I highly recommend to learn at least the really basic commands.
Brew & cask
The very first thing that you should install on your new Mac is Homebrew. If you have used Linux before, might find this tool familiar (it’s working on Linux too). According to Max Howell (the creator):
The Missing Package Manager for macOS (or Linux)
You can also install regular applications with brew, by using the cask subcommand. e.g:
brew cask install firefox
+ Hello Swift!
Learning a programming language is hard. Even after more than a decade of software developer experience I feel like that I’m only scratching the surface. I don’t know much about low level assembly code, I don’t know how to create 3D games using shaders and many more. Still we all learn something new every single day. It’s a life-long journey and the path is full with obstacles, but if you keep going forward you’ll find that there’s gold at the end of the road. I still love to create new stuff from literally nothing but plain code. 😍
Everyone can code
In the beginning it’ll feel like that you have to learn a million things, but you shouldn’t be afraid because time is your friend. Day-by-day you’ll learn something new that’ll help you moving forward to achieve your next goal. I believe that the most important thing here is to have fun. If you feel frustrated because you can’t understand something just ask for help or take a break. The Swift community a group of amazing people, everybody is really helpful, so if you choose this programming language to bring your ideas to life you’ll meet some great people.
Now let me show you what you’ll need to start your career as a Swift application developer. 👨💻
Hardware
The first thing you’ll need to start your Apple developer career is a Mac. Unfortunately Mac’s are quite expensive machines nowadays, also the current series of MacBooks (both Air’s and Pro’s) have the completely broken butterfly keyboard mechanism. Hopefully this will change real soon.
I’d say that you should go with pre-butterfly models, you can look for the secondary market if you want to have a cheap deal. Otherwise you can go with a Mac mini, but if you buy one you should think about the extra expenses such as the monitor, keyboard & mouse.
If you have unlimited money, you should go with some high-end device like the new MacBook Pro 16”, iMac Pro or simply buy a Mac Pro. Nevertheless you should always choose a machine with an SSD. It’s kind of a shame that in 2020 a base iMac comes with a ridiculously slow HDD.
Another option is to build a hackintosh, but IMHO that’s the worst that you can do. You won’t get the same experience, plus you will struggle a lot fighting the system.
NOTE: You might heard rumors that you’re going to be just fine with an iPad & Swift playgrounds. Honestly that’s just not the case. You can play around and learn the Swift programming language even with a Linux machine, but if you want to make your own iOS / iPadOS / macOS / watchOS apps, you’ll need a Mac for sure.
Software
So you’ve got a decent Mac. Let’s see what kind of software will you need if you want to start developing iOS apps. You might heard that Apple’s operating system is macOS. First of all, if you never used a mac before, you should get familiar with the system itself. When I bought my very first MacBook Pro, it took me about a week to get used to all the apps, system shortcuts and everything else.
If you don’t want to figure out everything for yourself, you came to the right place. Let me walk you through of every single app, tool that I’m using to my work as a professional mobile / backend developer.
Terminal
The most important thing that you should get used to is the Terminal (console) application. If you never heard about terminals before you should simply look for a beginner’s guide tutorial, but I highly recommend to learn at least the really basic commands.
Brew & cask
The very first thing that you should install on your new Mac is Homebrew. If you have used Linux before, might find this tool familiar (it’s working on Linux too). According to Max Howell (the creator):
The Missing Package Manager for macOS (or Linux)
You can also install regular applications with brew, by using the cask subcommand. e.g:
brew cask install firefox
I prefer to create a list of tools that I’m always using, so when I reinstall my machine I simply copy & paste those commands into terminal and I’m more or less ready with the restoration process. This is extremely convenient if you have to reinstall macOS from scratch.
MAS
You might noticed that I’ve got a thing for Terminal. If you don’t like the interface of the App Store, you can install MAS, a little helper tool. With the help of it you can install everything available in the store by using Terminal commands.
The readme on GitHub is really good, you should read it carefully. Anyway you don’t necessary need the mas-cli to do iOS development, but since it’s really convenient, I’d recommend to check it out.
Xcode
The number one tool that you’ll definitely need is Xcode. There is an alternative IDE tool called AppCode, but it’s always lagging behind and the vast majority of the community prefers Xcode. 🔨
A new Xcode version is released every single year with brand new features and functionalities. I’d recommend to go with the most recent one (also you should always upgrade your existing projects to support the latest version). You can get Xcode from the App Store, it’s completely free.
It’ll take a lot of time to install Xcode on your machine, but don’t worry after a few hours it’ll be ready to help you writing your very first iOS application. So be patient. :)
Git
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
Every single developer should use a proper version control system (aka. Git). Git is the de facto standard tool for version control and you can learn the basics in just about 15 minutes. Of course mastering it will take much longer, but it’s totally worth to start playing around with it.
GitHub
GitHub is a web-based hosting service for version control using git.
To be honest, GitHub it’s not just a repository hosting service anymore, it’s a complete platform with tools for issue management, project planning, continuous integration support and many more.
GitHub offers you a free tier both for public and private Git repositories for individuals. In 2019 it was acquired by Microsoft (everyone was afraid of this change, since MS has some history about ruining good services), but until for now they introduced lots of amazing new features. Go and get your free account now!
iOS app development using Swift
I believe that Swift has evolved to a stable & mature language during the past 5 years. If you think about it, it’s the only good option to write future proof iOS apps. You should clearly forget Objective-C, since Apple already made his choice. Eventually Swift will be the only programming language that Apple supports, there are already some frameworks that are Swift “only”. Just take a look at on SwiftUI. I mean you can’t write SwiftUI views in Objective-C, although the framework is 100% compatible with Objective-C based projects.
Dependency management
At some point in time you don’t want to write everything by yourself, because you’d like to make progress fast. This is where external packages are coming into the picture. Take my advice:
Never connect 3rd-party libraries by hand
The Swift Package Manager is natively integrated into Xcode. In the past CocoaPods was the ultimate dependency manager (some people preferred Carthage) for iOS projects, but nowadays it’s way better to use SPM. If you need to integrate external libraries SwiftPM is the right choice in 2020. If you don’t know how it works, you should read my comprehensive tutorial about how to use the Swift Package Manager.
I also made a quite popular article about the best / most popular iOS libraries written in Swift last year. It was featured on Sean Allen’s (Swift News) YouTube channel. Unfortunately he stopped that show, but he is still making some really good videos, so you should definitely check his channel if you have some time.
Anyway, if you don’t know where to start and what to integrate into your Swift project you should go and read my blog post, since it’s still up-to-date. Fortunately these things are not changing that often.
Application architecture
Picking the right architecture for your upcoming iOS project is one of the hardest things. The other one is building up your user interface, but let’s keep that topic for another day. You should never be afraid of architectures. Even if you choose MVC, MVP, MVVM or VIPER you can have a really well-written application strucutre. This is really important, because you don’t want to make your future self angry with some 2000+ lines sphagetti coded view controller with some nasty side effects.
So how you should pick an architecture? Since there a lots of them, you can even come up with a random one. Well, this is a real debate amongst iOS developers. My favorite one is VIPER, though I get a lot of criticism because of this. Honestly I really don’t give a damn about this, because it works for me (and my teams). Whether you go with plain old MVC it really doesn’t matters until it can solve your issue.
If you are a completely beginner please don’t start with VIPER, unless you can have someone by your side who can answer all your questions. My advice here is just to simply sit down and think through what do you want to achieve and make a basic plan. Of course it helps a lot if you are familiar with the patterns, but in the end of the day, you’ll realize that all of them are made by humans and none of them is perfect. 🤔
Conventions for Xcode
I made some really basic conventions for Xcode that you should check if you don’t know how to organize your projects. If you are not familiar with Xcode formats, targets, schemes, you should search the internet for such a tutorial, there are some well-explained examples about the entire thing.
Use folders to represent groups in Xcode
You know just like in real life, you don’t throw all your clothes into the shelf, right?. Being well organized is the only way to create a good project. Fortunately Apple realized this as well, and now groups are represented as physical folders on your hard drive by default.
Always try to fix every single warning
There is a reason that warnings exists, but you should never leave any of them in your production code. If you want to be more radical, there is a build flag in Xcode to treat warnings as errors. TURN IT ON! Kill all warnings! Haha, don’t do that, but you should always try to fix all your warnings.
Don’t let your code to grow on you
You know that awkward situation, when you open a source file, and you start scrolling, scrolling and you have to do even more scrolling. Yep, usually that’s a massive view controller problem and you already know that you are lost forever. If you get to this point, you can try to refactor your code by introducing a new object that can take over some of the functionality from your controller class.
Do not reinvent the wheel
If there is a best practice, use that. You should always look up the problem before you start coding. You should also think through the problem carefully before you start coding. Remember: you are not alone with your coding issues, I can almost guarantee that someone already had the exact same issue that you are working on. StackOverflow is the right place to look for solutions. Use the power of the community, don’t be afraid to ask questions on the internet, or from your co-workers, but don’t expect that others will solve your problem, that’s your job.
Swift advices for beginners
In this section I’m going to give you some real quick advices about how to write proper Swift code. I know I can’t have everything in this list, but in my opinion these are some really important ones.
Learn how to write proper async code
Look, if you know what is the “Great” Pyramid of Doom, you’ll know what I’m talking about. You’re going to write async code eventually, most of the API’s have async methods. Even a simple networking task is asynchrounous. It’s a smart move to learn how to write proper async code from the beginning.
There are a few approaches that you can choose from.
Of course you can go old-school by using completion blocks. That’s a good way of learning the concept and you can practice a lot, but there are way better options to write good async code in 2020.
Promises are high level abstractions over async tasks, they’ll make your life SO MUCH BETTER. You the real power comes from the fact that you can chain & transform them using functional methods. Promises are amazing, but they don’t really have built-in support for cancellation.
You can go with NSOperation tasks as well, but if you’d like to have some syntax sugar I’d recommend Promises. My problem is that if you have to pass data between operations you’ll have to create a new operation to do it, but in exchange of this little inconvenience they can run on queues, they can have priorities and dependencies.
I believe that the brand new Combine framework is the best way to deal with async code in 2020.
Only use singletons if necessary
They are the root of all evil. Honestly, avoid singletons as much as you can. If you want to deal with mixed-up states & untestable code, just go with them, but your life will be better if you take my advice. If you don’t know how to avoid the singleton pattern please do some research. There are lots of great articles on the net about this topic.
One exception: you can use a singleton if you are especially looking for shared states, like cache mechanisms or a local storage object like UserDefaults. Otherwise don’t use a singleton.
Do not create helpers (or managers)
If you need a helper class, you are doing things wrong! Every single object has it’s own place in your codebase, helpers are useless & not good for anything. Rethink, redefine, refactor if you need, but avoid helper classes at all cost. Learn about Swift design patterns or draw a chart about your models, but trust me there is no place for helpers in your code.
Avoid side effects & global state
Using globals is a really bad practice. Eventually some part of your code will override the global property and things are going to be pretty messed up. You can avoid side effects by simply eliminating those global variables. Also going functional is a neat way to improve your code.
Write some tests
You should always write tests, I’m not saying that you should go with TDD, but unit tests are good practice. They’ll help you to think through the possible mistakes and they validate your codebase. Also UI tests are good for validating the user interface, plus you can save countless hours if you don’t have to run manual tests.
Non-technical skills
I know it’s quite a list. Don’t be afraid, you don’t have to learn everything at once. Beginning your iOS career is not just all about learning new stuff, but you should have fun on the road. 😊
Time
Be patient & consistent. Always dedicate a fixed amount of time per day to code. It really doesn’t matters if it’s just half an hour, if you do it every day you’ll form a habit and the numbers will sum up as well. In this busy world, it’s really hard to find some time to really focus on something, but if you really want to learn how to write Swift code, this is the most important step that you need to take.
Motivation
Being motivated is easy if you have a “dream”. Do you want to build an app? Do you want to learn how to write something in Swift? Do you want to have a better job? Do you want to make a game for your kids? All of these things can be great motivators. The problem starts when you constantly hit the obstacles.
Don’t be afraid! Being a programmer means that sometimes you just try & fail. If you want to be a real good developer you should learn from those mistakes and do better on the second time. Of course you’ll learn a lot from other people as well, but sometimes you have to solve your own problems.
Goals
Don’t try to aim for one really big goal. Celebrate the little success stories and achievements. You should also be proud of what you’ve done “today”. It’s easy to forget to remember these little things, but making an app or learning a new programming language is a long-term project. If you don’t have your small moments that you can celebrate eventually you will lose motivation and interest for the “project”.
I think these three things are the most important non-technical skills if you want to learn Swift. Have your very own dedicated time to code every single day. Gain motivation from your dream (follow the big picture), but also celebrate every little success story that you achieved. Go step-by-step and you’ll find that there is nothing that you can’t learn. Anyway, technical skills are just secondary… 🤷♂️
The Swift community is amazing
It’s really good to see that there are still plenty of dedicated people who are keeping up writing about the good and bad parts of iOS / Swift development. Here are the best resources that you should know in 2020.
Best iOS / Swift tutorial sites
Best iOS / Swift blogs
- Paul Hudson
- John Sundell
- Antoine van der Lee
- Vadim Bulavin
- Keith Harrison
- Majid Jabrayilov
- Bart Jacobs
- Soroush Khanlou
- Erica Sadun
- Andrew Bancroft
Best iOS / Swift newsletters
Best iOS / Swift podcasts
Twitter accounts to follow
- Ankit Aggarwal
- Harlan Haskins
- Nate Cook
- Slava Pestov
- Ted Kremenek
- JP Simard
- Daniel Dunbar
- Doug Gregor
- Joe Groff
- Ben Cohen
- Tanner Wayne Nelson
- Ash Furrow
- Ole Begemann
- Bart Jacobs
- Dave Verwer
- Ray Wenderlich
- objc.io
- NSHipster
- Krzysztof Zabłocki
- Marcin Krzyzanowski
- Peter Steinberger
- Chris Eidhof
- soroush
- ericasadun
- Chris Lattner
- John Siracusa
- Sean Allen
- Marco Arment
- Paul Hudson
- John Sundell
Where to go next?
In the past year I’ve interviewed lots of iOS developer candidates. Absolute beginners are always asking me the same question again and again: where should I go next, what should I learn next?
There is no definite answer, but this year I’m trying help you a lot. This is the very first year when I’ll dedicate more time on my blog than on anything else. No more new client projects, no more excuses.
@@ -148,7 +148,7 @@ Related posts
Custom UIView subclass from a xib file
diff --git a/docs/whats-new-in-swift-5-3/index.html b/docs/whats-new-in-swift-5-3/index.html
index 68498cd..457d179 100644
--- a/docs/whats-new-in-swift-5-3/index.html
+++ b/docs/whats-new-in-swift-5-3/index.html
@@ -100,7 +100,7 @@
What's new in Swift 5.3?
diff --git a/docs/working-with-diffable-data-sources-and-table-views-using-uikit/index.html b/docs/working-with-diffable-data-sources-and-table-views-using-uikit/index.html
index 13c1d0c..26745d3 100644
--- a/docs/working-with-diffable-data-sources-and-table-views-using-uikit/index.html
+++ b/docs/working-with-diffable-data-sources-and-table-views-using-uikit/index.html
@@ -620,7 +620,7 @@
- · 4 min read
+ · 5 min read
Custom UIView subclass from a xib file
diff --git a/src/contents/blog/posts/2018/everything-about-public-and-private-swift-attributes/index.md b/src/contents/blog/posts/2018/everything-about-public-and-private-swift-attributes/index.md
index 9c4ac35..d9a460d 100644
--- a/src/contents/blog/posts/2018/everything-about-public-and-private-swift-attributes/index.md
+++ b/src/contents/blog/posts/2018/everything-about-public-and-private-swift-attributes/index.md
@@ -223,7 +223,7 @@ With the @inline attribute you explicitly tell the compiler the function inlinin
c()
```
-@inlinable is the future (@\_inlineable) by Marcin Krzyzanowskim 👏
+`@inlinable` is the future (@\_inlineable) by Marcin Krzyzanowskim 👏
### @effects
diff --git a/src/themes/default/blocks/column.yml b/src/themes/default/blocks/column.yml
new file mode 100644
index 0000000..891c3bb
--- /dev/null
+++ b/src/themes/default/blocks/column.yml
@@ -0,0 +1,10 @@
+name: column
+params:
+ - label: class
+ default: ""
+requiresParentDirective: grid
+
+tag: div
+attributes:
+ - name: class
+ value: "column {{class}}"
diff --git a/src/themes/default/blocks/grid.yml b/src/themes/default/blocks/grid.yml
new file mode 100644
index 0000000..dd194e7
--- /dev/null
+++ b/src/themes/default/blocks/grid.yml
@@ -0,0 +1,16 @@
+name: grid
+params:
+ - label: desktop
+ default: "2"
+ - label: tablet
+ default: "2"
+ - label: mobile
+ default: "1"
+ - label: class
+ default: ""
+#requiresParentDirective: faq
+#output: "{{contents}} - {{desktop}}"
+tag: div
+attributes:
+ - name: class
+ value: "grid grid-{{desktop}}{{tablet}}{{mobile}} {{class}}"