piątek, 19 czerwca 2015

What's new in iOS9 and Xcode 7 - WWDC 2015

Objective C Nullability

This was actually introduced in XCode 6.3, but it's a failry new feature presented at WWDC 2015. You can set your parameter to be nonnull or nullable:



This code will produce a warning while building, and crash in runtime if the code that passes nil to name is executed.

It looks a lot nicer with property declarations.

You can use NS_ASSUME_NONNULL_BEGIN and NS_ASSUME_NONNULL_END macros to mark blocks of code where you want your parameters/properties to be nonnull at default.

There's also null_resetable that will mark your variable to be nullable, but will never return null.

Objective C Generics!

At last! The Apple gods have listened to us. I don't mind the fact that you can hold different object types in a collection. The worst thing about NSArray was that you never knew what it held, unless you... remembered. Now you can define a NSArray to hold a specific object and get a compiler warning if you try to put there something else.
That's not all! You can use generics in your own classes too!

UIStackView

It's a small great view. If you've ever programmed in some other frameworks with a WSIWYG you're probably already familiar with it: you put views inside this layout, and it places all the elements next to each other horizontally or vertically. It'll save us developers a lot of time. A great example is a form with 10 boxes: you've had to create so many constraints to keep all of them the way you wanted. Now you just put it in a UIStackView and that's it!

Here's a quick tutorial on UIStackView.

App Thining

If you have an iOS device with 8 GB of memory, you know the pain of disk management. That's why Apple introduced app thining. It's a group of operations that are supposed to make the bundle you download from the app store smaller.

Sliicing is used to make sure you only download assets needed for your particular device. It's that simple.

On-Demand Resources lets your assets to be downloaded dynamically, not initially with the bundle. It all works smoothly in the background so you get faster initial start, without any downsides.

BitCode is a powerful but invisible feature. You upload the intermediate LLVM code to Apple Store so they can recompile your code to machine code if they make some changes or add some new architecture.

Address Sanitizer


What do you do ? Sit down, and cry... Then sit down and cry some more trying to figure it out. That's the curse of unmanaged languages - low level memory errors are very hard to debug.

But in XCode 7 you can use the Address Sanitizer tool!


  • "You enable the address sanitizer in the build scheme. Once enabled, added instrumentation is built into the app to catch memory violations immediately, enabling you to inspect the problem right at the place where it occurs. Other diagnostic information is provided as well, such as the relationship between the faulty address and a valid object on the heap and allocation/deallocation information, which helps you pinpoint and fix the problem quickly. Address sanitizer is efficient—fast enough to be used regularly, as well as with interactive applications. It is supported on OS X, in the Simulator, and on iOS devices."




Cocoa Touch Best Practices - WWDC 2015

Launch quickly

The first thing you learn is that you shouldn't do process extensive tasks on UI thread. People sometimes forget that if you do the same in the delegate callbacks you'll freeze UI.
  • Always return quickly from applicationDidFinishLaunching to launch the app as quickly as possible. Your app even might be killed if it takes too long!

Use Background Queues

Loading data from database or server on a main queue through dispatch_async is a basic thing. The problem is that if there are many operations on the main_queue it still may make the UI not responsive. The less time you spend wasting CPU cycles on the main thread, the more responsive your UI will be.
  • When dispatching use a background queue when possible

RAM Usage while suspended

When you go back to an app you instantly resume at the point where you've left it. It's a great thing in mobile devices, that lets us save our time and make the apps more responsive.

The sad truth is that your app might get killed from the suspension state. We want to make sure it lives as long as possible, right ? iOS kills the apps that use the most RAM first!


Don't bet that app!

  • When you get the applicationDidEnterBackground callback make sure you release as much data as possible. Use a background task if you need more time to clean after yourself.

Keep Your Code Unrelated To Time

Sometimes you want to do something after a certain animation finishes. You can predict how long will that animation last and just use a NSTimer and launch a block of code to happen after that time. What if in future iOS updates the time of the animation changes ? Try to keep your code relative to events and callbcks, not time. For example by using UIViewControllerTransitionCoordinator.

Clang compiler under the hood


When you build an iOS application you're not really interested with how does it all work under the hood most of the times. You just place some layout, hit "Run" or "Archive" and that's it. It just works.

It's when you start building your own library you start wondering: how does it all work?

Static Library

Clang is no different than GCC when it comes to compiling and linking. When you compile a static library you create a .a file. The so called archive file is nothing more than just a package of compiled object files. The .o files, which are in ELF format contain not only code, but also the roadmap of the file: symbols and data. This data is needed for the linker to resolve symbols at executable linking time.

When you include a static library to your executable, symbols and code are copied into the file. With -dead_strip flag enabled only the symbols used in your executable are used - it helps in reducing the executable file size.


example of "nm" and "file" programs
You can use nm to list all symbols in a file. As you can see, there are no symbols for functions, because of of Objective-C`s dynamic nature. Function symbols are internal (-g flag of nm shows only external symbols). Because of this, if you have any categories in your static library, you have to put a -ObjC or some other flag like -force_load to your linker flags, or you'll get a crash at runtime, because the functions of the category will not be copied at all, as they are not referenced anywhere. Unfortunately it makes the executable file larger*.

Symbols with U are "unresolved" meaning that they are to be resolved during the executable link time (in case of static libraries).

During the final executable link time, the linker creates a table and searches for all the needed symbols in defined search paths. If it doesn't find a needed symbol it stops the linking process with something you might be familiar with:


oops

Duplicate Symbols Problem

Objective-C doesn't have namespaces. That's why you see every library with a two or three letter prefix. It helps avoids collisions. If someone creates a class XXXModel and links his program with a static library that uses YYYModel he doesn't get a collision.

What if your static library uses AFNetworking and your library's users want to use AFNetworking too ? They'll get a collision. The most common way of solving that is to add a prefix to AFNetworking.

The other way is: using dynamic libraries.

Dynamic Libraries

A dynamic library unlike the static library isn't just a collection of code to be linked. It's a collection of code ready to be executed.

When you link your executable the dynamic library has to be present so the linker know what to reference, but the code doesn't get copied to your executable.
source


When a system loads an executable, and that executable has references to dynamic libraries, the dynamic linker searches for these libraries, loads them to RAM fills the code jump pointers for the executable.

Dynamic libraries can drastically reduce the size of an executable, not only because the code doesn't get copied, but also because you get to dynamically load AFNetworking once, not get it precompiled in every library you use.

iOS8 enabled using shared libraries, but they still get copied into the bundle. The only difference is that you can share a library between all your iOS extensions.

CocoaPods

One of CocoaPods' jobs is to manage dependencies. If you include 100 dependencies that depend on AFNetworking it'll only include the code once, not one hundred times. But that's the case for open-source software, not pre-compiled libraries.

-ObjC flag*

As I mentioned earlier -ObjC makes your executable larger, because it forces to load all files containing Objective-C code.

As I mentioned earlier categories are not loaded, because they are not referenced anywhere. What if we were to force reference them ?

Just declare any symbol in the file:


declare an extern int variable

declare the variable
Now you have to use that symbol somewhere so it gets link referenced:

That's it! Now you don't have to force your static library users to link with -ObjC flag.