Is Objective C still supported?

Swift, Apple's new programming language

In June, Apple surprised the world by introducing a new programming language: Swift. Version 1.0 of Swift has been available since the release of iOS 8 in September 2014 and is officially usable for iOS development, and since the release of Mac OS X 10.10 Yosemite in October 2014 it is also available for developing applications for Mac OS X usable. In the following I would like to introduce you to Apple's new programming language and highlight the advantages it promises.

Why Swift?

The programming language that was usually developed for Mac OS X and iOS is Objective-C. However, this is already over 30 years old and is based on the programming language C, which is ten years older. However, computer science has not stood still in the last 40 years and so many new concepts have been invented in programming languages ​​and many positive as well as negative experiences with existing ones Programming languages ​​made. Although Objective-C has also been further developed (for example, Apple introduced Objective-C 2.0 in 2006), some fundamental design decisions of C and Objective-C can no longer be changed afterwards. In addition, many of the more modern language features of Objective-C, such as blocks, seemed more like added afterwards and not like natural constructs of the language. Accordingly, John Siracusa warned Apple in 2005 that they would lose touch with modern programming languages ​​if they continued to rely on Objective-C.

A programming language must not only support modern programming concepts, it should also generate little overhead at the same time, i.e. ensure fast programs. Especially when apps for embedded devices such as smartphones or the announced Apple Watch are written with this programming language, which due to their size and requirements for low energy consumption can only use slower processors than desktop PCs. It is precisely this balancing act between performance and modern features and less susceptibility to errors in a programming language that Apple is trying to achieve with Swift. According to Apple's own statement, the core features of Swift are: "Modern", "Safe", "Fast and Powerful".

Modern

Swift contains a number of modern programming concepts that are already known from other languages ​​such as Ruby or C #. In typical Apple style, the company from Cupertino looked around the current technologies, picked out the well-functioning concepts and put together a convincing overall package in which many old braids are cut off. Swift has become a multi-paradigm programming language, in addition to the well-known object-oriented programming, Swift also supports many concepts of so-called functional programming.

Functional programming

In addition to anonymous functions, so-called lambda expressions, and the treatment of functions as first-class data types, so-called higher-order functions are also supported, i.e. functions whose parameters are in turn other functions. For example, to calculate the square numbers for a list of numbers, the following code could be used in Objective-C:

<br /> NSArray *numbers = @[@1, @2, @3, @4, @5, @6];<br /> NSMutableArray *squaredNumbers = [NSMutableArray array];<br /> for (NSNumber *number in numbers)<br /> {<br /> NSNumber *squaredResult = [NSNumber numberWithInt:[number intValue] * [number intValue]];<br /> [squaredNumbers addObject:squaredResult];<br /> }<br /> NSLog(@"squared numbers: %@", squaredNumbers);<br />

In contrast, the code in Swift looks much clearer and clearer and uses the higher-order map function.

<br /> let numbers = [1, 2, 3, 4, 5, 6]<br /> let squaredNumbers = numbers.map({x in x * x})<br /> println("square numbers: \(squaredNumbers)")<br />

Operations that used to require a loop construct are now often single-line operations. On the one hand, this is faster and, on the other hand, it usually expresses the programmer's intention much more clearly. For example, to add up all the numbers in a list, the following code could be used:

<br /> let sum = numbers.reduce(0, +)<br />
Generic programming

In addition to the functional and object-oriented programming approaches, Swift also supports so-called generic programming. With the help of generic programming, many algorithms can be abstracted to the extent that they are implemented on general data types and do not have to be rewritten for each data type. An example of this is a function that calculates the maximum of two numbers. In a non-generic language like C, this function would have to be implemented individually for each data type:

<br /> int maxInt(int a, int b) {<br /> if (a &gt; b) {<br /> return a;<br /> }<br /> return b;<br /> }</p> <p>float maxFloat(float a, float b) {<br /> if (a &gt; b) {<br /> return a;<br /> }<br /> return b;<br /> }<br />

As you can easily see, the implementation itself is very similar, so there is a lot of repetitive code. Languages ​​that support interfaces, such as Objective-C or Java, can simplify implementation by implementing the function once for all classes that implement a particular interface. It could look like this, for example:

<br /> id&lt;Comparable&gt; max(id&lt;Comparable&gt; a, id&lt;Comparable&gt; b) {<br /> if ([a compare:b] == NSOrderedDescending) {<br /> return a;<br /> }<br /> return b;<br /> }<br />

However, there are two problems with this approach. On the one hand, the exact type formation is lost. The comparison of two strings could look like this, for example:

<br /> id&lt;Comparable&gt; result = max(@"hallo", @"welt");<br />

In this case the result is of the type "Comparable", but the compiler cannot tell whether the result is an NSNumber or an NSString. An explicit cast has to be made here. Although this is annoying, it is not a particularly big problem. A much bigger problem is that this general max function can also be called with arguments that don't make sense:

<br /> id&lt;Comparable&gt; result = max(@"hallo", @1);<br />

The string “hello” is compared with the number 1 here. That makes no sense, but since both are "Comparable" the call is valid and the compiler cannot recognize this error.

Swift and other generic programming languages ​​such as Java or C ++ solve the problem by introducing a type variable:

<br /> func max&lt;T:Comparable&gt;(a:T, b:T) -&gt; T {<br /> if (a &gt; b) {<br /> return a<br /> }<br /> return b<br /> }<br />

So here it is stipulated that not only must both arguments be "Comparable", but also of the same type. This bypasses the problem from the previous example, since the function can no longer be called with two different types. The return type is now also specified via the type variable and the compiler knows that if two "int" values ​​are compared, the result is also an int.

safe

Swift is also a significantly more secure language than Objective-C in many ways. "Safe" means above all that the programmer is protected from making mistakes more often than in other languages ​​and, in particular, frequent mistakes that can lead to a program crash are prevented more often. However, it is precisely through such exceptional situations as occur in crashes that security gaps arise, which is why there is justified hope that programs written with Swift will also become more secure in the narrower “security” sense. This increased security is achieved through various aspects:

Static and strong typing

Swift is a statically typed programming language. This means that the types of the variables used are defined and checked at the time of compilation and not at runtime. This allows the compiler to recognize many errors directly and to point them out before the program is run for the first time. In addition, Swift is a very strongly typed language, which means only a few type conversions happen automatically, almost all type conversions have to be done explicitly. This also avoids many careless mistakes in programming.

No null pointer by default

One of the most serious changes in Swift is the removal of null pointers in many different places. A variable in Swift can still have the value zero or. Nile can be assigned, but only if this has been explicitly marked as "optional". A variable of type String thus cannot get the value Nile assume this is only possible if the variable is of type String? or. Optional is. Thus the fact whether becomes a value Nile can be made explicit and can be checked statically by the compiler, which in turn offers the possibility of recognizing many potential zero pointer errors at the time of compilation.

This change has the potential to eradicate a whole class of common programming errors. For example, the well-known British computer scientist Tony Hoare says about his decision to allow zero references in ALGOL W that it was a "billion dollar mistake", since it resulted in a lot of errors that would have cost billions. This picture is confirmed when looking at the errors that are fixed in security updates. For example, 2 of the 20 fixed bugs in the security update for Max OS X 10.9.4 are null pointer errors that would probably not have been possible with Swift or would have been found at compile time. Overall, up to 13 of the 20 security holes fixed in 10.9.4 could have been prevented by using Swift (2x null pointer errors, 2x integer over / underflow, 9x buffer overrun / bounds checking).

Non-changeability of data

The non-changeability or immutability of an object or a variable is another concept that was adopted from functional programming. Here all data are unchangeable by default, only new data with different values ​​can be generated. In many cases this makes it easier to draw conclusions about the behavior of the program code and is therefore also a concept that is often used to prevent programming errors. Although not all variables and objects are immutable in Swift, it is very easy to mark a data structure as immutable with the keyword "let". Here, too, the compiler can check whether the promise of immutability is kept and thus ensure that the program code is better checked.

Fast and Powerful

As already mentioned above, in addition to the expressiveness and security of a programming language, the performance of the resulting apps is also of great importance, especially in the context of Apple's products, which often rely on small, energy-saving processors. In addition, Apple has expressed the claim to develop a programming language with Swift that can also be used for internal programming of the operating system and here too, of course, performance is of the utmost importance for core functions that are called millions of times per minute. Therefore, the corresponding parts of the operating system are still often written in C or C ++ today. So it's clear that applications written in Swift need to run fast too. On closer inspection, it turns out that Swift also has great potential here, but it will probably take a while until this potential is fully exploited.

Virtual functions instead of message passing

One of the performance disadvantages of Objective-C is that method calls are not direct function calls at the level of the code generated by the compiler, but rather strings are sent as messages between objects. The receiving object then checks which message was actually received and calls the appropriate function. This enables some of the powerful uses of Objective-C, but looking up the appropriate function by string is potentially slower and is often not needed. In contrast to this, Swift, similar to C ++, uses so-called virtual methods in many cases to map the method call. The available methods are stored in a permanently indexed table, which makes determining the method to be called up significantly faster.

Structs

In Swift, composite data types, so-called structs, are much more powerful because they can have methods, for example, and can therefore be used in significantly more places. The advantage of composite data types over classes is that they are viewed as so-called value types, whereas classes are reference types. Instances of a value type are usually stored on the stack and are copied when passed to another function. Instances of a reference type, on the other hand, are stored on the heap and when passed to another function, only the reference to the same instance of the object is passed. This makes it necessary to develop complex memory management strategies for reference types in order to decide when the associated data will be released again. This is not necessary for value types, as soon as the corresponding function has ended, all data that were used in the function are released again.

Another advantage of federated data types is that they do not support inheritance. This means that a decision can already be made at the time of compilation which method is called, since in contrast to classes with inheritance hierarchies, no so-called dynamic binding of methods is possible. This makes function calls even faster. Thus, by using composite data types, in contrast to classes, astonishing performance improvements can often be achieved. For example, Joseph Lord found in some experiments with compound types and classes that replacing a class with a compound data type made the affected code 54x faster.

The sufficiently intelligent compiler

Whenever a modern programming language is compared with an older, low-level programming language, the argument of a “sufficiently intelligent compiler” will emerge at some point. The reasoning in this case is that although the low-level programming language is faster for individual programming constructs, a sufficiently intelligent compiler can use the additional information available in the modern programming language to design parts of the code significantly more efficiently and to apply optimization strategies that are similar to those of a primitive Programming language would not be possible. If this argument remains theoretical in many cases, it actually has practical relevance for Swift for two reasons: First, Swift contains many abstract constructs that limit the semantics of the language and thus make such optimizations theoretically possible. Second, one of the creators of Swift, Chris Lattner, is actually also the author of the LLVM project and the Clang compiler that are currently used to compile and optimize C, Objective-C, and C ++. One can therefore assume that many of the special constructs in Swift are not just academic dreams, but can actually also be optimized in a much better automated manner in practice.

Despite all this, it has to be said that as of this writing, there are still a lot of complaints about Swift being slow. However, there is a lot of potential in the language and it seems easy to imagine that Apple can optimize the language as promised and make it much more powerful than Objective-C by continuously developing the Swift compiler tools. Perhaps in a few years this development will even go so far that Swift will become a serious competitor to C. At the moment, no Objective-C programmer has to fear that he will have disadvantages from developing with Objective-C. Instead, his greater experience with the language will have a positive effect at this point in time. However, I assume that within the next two years the tide will turn and Objective-C will only be used for old projects or for specialty applications where the dynamic nature of Objective-C is useful.