How does iOS Swift Runtime work - ios

In ObjC, it is using Messaging, static binding, dynamic typing, dynamic binding, dynamic method resolution, dynamic loading, introspector and so on.
Importantly, the core method objc_msgSend is responsible for taking the selector you're sending and the object you're sending it to, and looking that up in the class method tables to figure out exactly which piece of code is supposed to handle it.
My concerns here are:
Is Swift doing something similar like ObjC on runtime?
How does Swift runtime find the implementation code for some object/class method?
In ObjC, classes and objects are compiled to some runtime types such as C struct on runtime. Then what are such classes and objects compiled to on runtime in Swift?
Does Swift runtime have something like class / meta class / isa pointer / super pointer?

In short there are Dynamic and Static types of method call dispatching.
Static - the function address to be called is determined in the compilation time, so that expense of such call is similar to C-function calling. This mechanism is used for private methods or final classes methods call dispatching.
Dynamic dispatching is mechinism which allows to implement polymorphism concept of OOP - the function address to be called is determined in running time. Swift has two subtypes of it:
2.1. Obj-C - you already described in the question. This mechanism is used when object inherits from NSObject or calling method has #objc prefix.
2.2. Virtual table based (like in C++) - there is similar witness tables. What it does during method call dispatching is just single arithmetic operation - calculation of actual function address based on function offset in the base class witness table and the object class witness table location. So that's a relatively cheap operation comparing to Obj-C. It explains why "pure" Swift approximates to C++ performance.
If you don't mark you method with private keyword or your class is not final and same time you class is "pure" Swift (it does not inherit NSObject) then this virtual table based mechanism is used. It means that all the methods by default are virtual.
P.S.
Helpful link for proving my vision regarding "Types":
https://developer.apple.com/swift/blog/?id=27
"Subtypes" explanation is based on my understanding.

Related

iOS - In Swift, do we "send a message" or "call method/function"?

Does Swift keep the the method lookup list when compiled or does it call a function in a specific memory location?
Best regards.
Regarding this: http://davedelong.tumblr.com/post/58428190187/an-observation-on-objective-c
I would recommend you have a look at the below links, especially the first one because it explains the concepts with examples from C++ and Objective-C, in order to have a better understanding of the difference between static, late and dynamic dispatch (for methods).
In a nutshell:
Static dispatch
The function and its implementation is determined at compile time and thus can’t fail at runtime (because the compiler will not continue the compilation process unless the binding is successful).
Late dispatch
The function is determined at compile time, but the actual implementation depends on the type of the object at runtime. Important for inheritance. The compiler will check if the the class or any of its parents have the function declared, but its up to the runtime to choose which implementation to use. The late binding can be implemented using virtual tables like in the case of C++.
Dynamic dispatch
The function is determined at runtime, which in the case of Objective-C can be called by name and thus can fail at runtime if the receiver (object) doesn't implement or inherit a method that can respond to a specified message.
References
What is the difference between Dynamic, Static and Late binding?
What is early and late binding?
What is the difference between dynamic dispatch and late binding in C++?

dynamic modifier in functions in Swift

According to Apple :
When you mark a member declaration with the dynamic modifier, access to that member is always dynamically dispatched. Because declarations marked with the dynamic modifier are dispatched using the Objective-C runtime, they’re implicitly marked with the #objc attribute.
According to Wikipedia:
dynamic dispatch is the process of selecting which implementation of a polymorphic operation (method or function) to call at run time.
Dynamic dispatch is often used in object-oriented languages when different classes contain different implementations of the same method due to common inheritance. For example, suppose you have classes A, B, and C, where B and C both inherit the method foo() from A. Now suppose x is a variable of class A. At run time, x may actually have a value of type B or C and in general you can't know what it is at compile time.
Right now, I'm studying the dependency injection framework : Typhoon and when I open the sample project for Swift in all the classes that inherit from the Objective-C class TyphoonAssembly all the methods relatives to inject dependencies have the dynamic modifier included in the following way :
public dynamic func weatherReportDao() -> AnyObject {
return TyphoonDefinition.withClass(WeatherReportDaoFileSystemImpl.self)
}
I thought that I'm missing something, but I don't understand where is the polymorphic operation (method or function) to call at run time here.
What's is the purpose of the dynamic dispatch here?
The answer to your question is addressed in this post:
https://github.com/appsquickly/typhoon/wiki/TyphoonAssembly
Basically at runtime the Typhoon Framework is going to replace your method with its own routine that implements the features of the framework and calls your method to do whatever work you've defined for it.
In order for the framework to be able to replace the method, the method must be dynamically dispatched.

Prefix extension functions

In Swift it's not necessary to prefix classes anymore as their module acts as the namespace.
What about prefixing extension functions? For example:
extension UIImage {
public func hnk_hasAlpha() -> Bool { ... }
}
On one hand Swift is not dynamic so collisions would generate compiler errors.
But what happens if compiled code runs in a future iOS/OS X version in which one of my extension methods is added? Would methods in different modules be considered different symbols even if they have the same signature?
Does it make a difference if the extended class is a NSObject subclass or a pure Swift class?
There's some subtlety here:
Extensions of Objective-C types are implemented as Objective-C categories, with all that implies.
Extensions of Swift types, however, are only in effect where visible due to imports. This means that you can't accidentally stomp on a private system method (whether now or one introduced in the future), and if the system introduces a public method with the same name as yours, you'll get a compile-time failure when you rebuild, but your existing app won't break.
You should check those threads also:
Name collisions for extension methods from different frameworks - quote from thread:
regardless the application code imports which Framework, it seems, the actual called implementation depends on the order in Linked Frameworks and Libraries in "First come, first served" manner. But, as far as I know, this behavior is not guaranteed.
and Swift Extension: same extension function in two Modules which also confirms the same problem.
So based on that for Objective-C objects such as UIImage from your example name collisions are possible and you might see unexpected behaviour if there will be two methods with the same name in two different extensions for Objective-C object.

What does external mean in Dart?

What does external mean in Dart? For example: external DateTime._now();
I'm new to Dart, I can't find documentation for external, so can you give an example to help explain?
9.4 External Functions
An external function is a function whose body is provided separately from its
declaration. An external function may be a top-level function (17), a method
The body of the function is defined somewhere else.
As far as I know this is used to fix different implementations for Dart VM in the browser and Dart VM on the Server.
When we make an external function inside a class like toString()
external String toString();
means this method is abstract and the child of the parent class will add the function body, that's because in Dart we only can make an abstract class.
Summary:
external function = abstract function in not abstract classes
I don't think external keyword is meant to be used to mark methods as abstract, even if that's possible
It's enough to leave a method with no implementation to set it abstract, inside an abstract class
It's the equivalent of declare in TypeScript, and extern in C#, those are used for interoperability with other runtimes, which means you're telling the compiler "Don't worry about this method's implementation, I promise it will exist at runtime", the runtime may be in C or Javascript or whatever
In case, if you are wondering why or where should I even use external keyword, here is a one more example for Flutter.
class MyStruct extends Struct {
#Int32()
external int a;
#Float()
external double b;
external Pointer<Void> c;
}
Sometimes, but not often when you play with native libraries, in this case with Struct to access native struct's field in memory. Under Struct We must declare all fields as external because it will be external fields from dart:ffi (C / C++).
So, external is more than just way to declare "abstract method".
9.4 External Functions
An external function is a function whose
body is provided separately from its
declaration.
What this does mean is that you define the function, but without implementation. It's exactly how you define the abstract method, but the only difference is that with external you don't implement the method in dart but in C or something else.
Something like String class it can be considered as external functions except that the String class it marked with #pragma('vm:entry-point') which make the entire class use native code.
See the following example to understand:
This dart's side.
https://github.com/dart-lang/sdk/blob/main/sdk/lib/core/string.dart#L711
This the implementation in C++.
https://github.com/dart-lang/sdk/blob/main/runtime/lib/string.cc#L467-#L472
In my opinion it is an equivalent of Java native keyword. For example, since current time milliseconds is implemented differently on Android, iOS, Linux etc, DateTime.now().millisecondsSinceEpoch will be linked to different implementations at runtime. So it is not initially known how this method will look like. For this reason it is marked as external meaning it is platform dependent.

OpenAL Opaque Type

I'm working on writing my own Objective C wrapper around a minimal set of OpenAL functionality. One use case I'm trying to enable is transport controls after telling a sound to play like pause/stop/resume operations. I'm interested in trying to do this using what has been described to me as an "opaque type" or an id that conforms to a protocol in Objective C lingo. Does returning one of these make sense in this case, or would it be easier to just directly return an object and tie myself to that implementation?
And assuming the opaque type is the right approach, what would be a good name for the protocol? Right now I'm following this paradigm and calling the protocol OpenALPlaybackDelegate. I feel as if delegate doesn't really quite fit the model since the communication is happening the other way around.
An opaque type in this case is basically just a pointer that's used in Apple's C APIs in place of an object. Unlike a normal pointer to a struct full of stuff in C, the opacity in 'opaque types' comes from the fact that the header files don't expose the struct definition. The only way to deal with them is through the C functions that are exported. You see this in two places:
C APIs: Core Graphics, Core Audio, Core Foundation, Grand Central Dispatch. C has no objects. Apple has a bunch of types like CGFoobarRef that represent pointers to some sort of thing made with a function like CFFoobarMake();
Bridged APIs. Cocoa functionality is made available to C code through "the toll-free bridge", so you can generally get a handle on a say an instance of a Cocoa class in C world as an opaque type. Again, these generally end with Ref. All the Cocoa container classes, for instance, are available to C consumers through the Core Foundation toll-free bridge.
Relevant Apple documentation
If the consumers of your protocol are Objective-C libraries, which I'm going to assume they are, because that's the only way to use protocols, then no, it doesn't really make sense to expose access to any of your stuff as an pointer to a C struct filled with data and function pointers that are hidden from client code and exposed through a set of C functions.
Also, the reason to do this, for Apple, is encapsulation, data-hiding, etc. All it does is keep people from being able to muck about directly with the internal state of an object from C land, or write code that depends on it, because C lacks features like classes and ivars (well, Objective-C doesn't really have private ivars either but it at least has secret ones).
I would think writing an Objective-C wrapper around OpenAL, exactly what you would not want to do is return opaque types. You should return Objective-C objects that hold opaque type references with accessors/mutators that call the relevant functions on those references.

Resources