Pokazywanie postów oznaczonych etykietą swift. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą swift. Pokaż wszystkie posty

piątek, 11 grudnia 2015

Things you need to know about Swift's runtime

When learning advanced features of Objective-C I learned how much power does knowing about it's runtime give you. I've decided to start my adventure with Swift with studying it's runtime. This way you know exactly what you're telling the computer to do. 


Class vs Struct

Ahh, the famous "class vs struct" Google search. 

Październik 2014 - October 2014 - Release of Swift

Of course, structs are less complicated, thread safe and helpful when designing immutable models. What we're interested in this post though, is the runtime. 

A lot of people will say "structs are safe, but slow, because their value has to be copied every time it's passed", and won't even imagine how wrong they are.

Structs are way faster to allocate and deallocate, because they're values, so they're stored on the stack. Operations on the stack are much faster, than complicated operations on the heap. Here's some dedicated guy that actually tested it (swift 1.2, though).

Ok, but copying structs is an operation that you're going to do often - obviously it has to be slower than just copying references ? It also should take much more memory than simple references? It doesn't have to be true. Here's what apple has to say about it:

"... “copying” of strings, arrays, and dictionaries. The behavior you see in your code will always be as if a copy took place. However, Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so. Swift manages all value copying to ensure optimal performance, and you should not avoid assignment to try to preempt this optimization."


That means that when you copy structs, it doesn't have to mean that the memory copy will be executed and doubled. Swift uses copy-on-write, that makes sure that the memory will be copied only when changed.

Let vs Var

Of course you know the difference by now, but did you know that setting your variables as constants can affect the performance of your program ? Setting your variables as let tells the compiler that it can apply the value as inline in code. This means that it doesn't involve allocating any memory.

It's something that's been with us since C, but it's worth mentioning that it works the same with class, inline and instance methods. Inline, and class methods are much faster. For the same reason as above.

Is Swift dynamic or static ?


The best part for last. Swift's class methods are sometimes resolved dynamically, and sometimes statically. What this means is that the compiler knows exactly which method to call, and sometimes runtime has to lookup a vtable to find the correct method. Try to make sure that it's always static by:

• Using final and private keywords - the compiler will know that the methods won't be overriden, so it can statically assign the method, otherwise it'll use a virtual table lookup to resolve.

• Avoiding subclassing NSObject - this will make the class use Objective-C dynamic dispatch

• Avoid using @dynamic keyword - same

One good thing about having dynamic dispatch is method swizzling.


It's funny that good performance in Swift = clean code :)

Want to know more ? Swift has been open sourced so it's an open book now :)






czwartek, 3 grudnia 2015

Dependency Carrying in Swift (with storyboards)


Every programmer must've struggled with Dependency Carrying, even though he might've not known that it has it's own name. Dependency Carrying is extremely uncomfortable, when you have a lot of dependencies and you have to pass them deeper through the object tree. You have to define the same code for each class in the hierarchy - there must be a different way, right ?

View Controllers are actually a great example. Let's say that you have a Navigation Controller that navigates between 20 different View Controllers. If you have a database context, a networking context, you have to inject it manually into all of the controllers. What if you have 6 or 8 dependencies ? That's a lot of copy and paste injection code. What I usually did was refactor the dependencies into an aggregate and create different interfaces for that aggregate, but there must be an easier way to manage your dependencies, right ?

Swinject

I usually avoid using any dependency frameworks, because it just seems too extreme for me to have a library in your project just for a design pattern, but maybe I was wrong ? Let's try and use a dependency injection framework and see how it solves our problem.

The only reason I decided to test this approach is because Swinject is so easy and lightweight. You don't need any configuration files and it supports storyboards, which is awesome!

Let's create a new project with a storyboard and two view controllers.


Now let's create an separate file, an extension for Swinject that will run when setting up the storyboard.


That's it! Your view controllers will now be injected with the objects you've registered. I must say that I really liked it. It's very easy, you configure everything in one file and in Swift and it works great with storyboards. The code isn't very elegant, but if you have 20 view controllers you can just use a function that will inject needed dependencies depending on the view controllers protocol.

One more awesome thing: your view controllers are ready to unit test! Well, not really in my example, because I didn't obscure concrete classes with protocols, so I can't mock, but if you do, you can register a different class configuration in your unit tests and you're ready to go!

Swinject has a lot of different features that you can leverage, so you should definitely check it out!

There's very little code (that's good!), but if you want to check out how it's all connected here's the repo.