Why does swift depend on Objective-C so much?

I've been avoiding the move to Swift because I've been very happy and content with Objective-C. I've recently, for various reasons, decided to make the move to learn Swift by writing a new app in it.

The first class I decided to write takes a delegate. Easy peasy, just write up a protocol using what I've just read in the reference.

And then I went to add 3 optional func's just like I had in the Objective-C version of this class and that when I discovered that if I want to define an optional func in a protocol, I have to make the whole protocol objective-c compliant!

Add to that the fact that the func's in question have a parameter which is an instance of the Swift class I was starting to write, and I then discover that I have to declare that class as being Objective-C compliant as well.

What gives? I thought this was a new, independent language that was open-source, allowing development of compilers for other platforms? How does this work when the language definition involves deep hooks into Apple's legacy language Objective-C? How, on another platform is that supposed to work?

Is the answer, not to use optional func's in Swift? I expected, and knew that there were ways to bridge Swift and Objective-C, but I didn't expect to find that Swift's language is tightly coupled with Objective-C's runtime.

So what do I do now? If I want to teach myself Swift so that my knowledge of the language is a saleable skill for my resume, what are companies that call themselves "Swift" doing for this sort of thing? Do they code in a way to avoid all of these Objective-C hooks? Is that possible? I've only just started on my first class file, so I wonder how many other hurdles like this I'm going to find. I thought Swift was supposed to be easy to learn for beginners. What is a 16yo going to do when they start learning about protocols and optional func's for example?

2 Likes

There are no optional functions in pure Swift protocols, by design. They exist only in @objc protocols for compatibility reasons.

If you're designing pure Swift types that use a delegate pattern, you can provide default implementations of the protocol requirements, so that a conforming type only has to implement the ones it wants to have different behavior.

8 Likes

The "Swift" you're talking about is more accurately described as "Swift for interacting with Objective-C APIs such as Cocoa Touch". I'm sure you're aware that most of Apple's frameworks for writing apps are written in Objective-C, still support Objective-C, and were designed around Objective-C. Swift was initially aimed as a replacement for Objective-C for app development, and in doing so had to obviously interoperate with older frameworks that were not designed for Swift. Objective-C, with its dynamic runtime, allows for some things that are not quite considered best practice in modern Swift today, and one of these are optional functions (in Objective-C, these are checked for at runtime to see if they exist; in Swift, it would be preferable to make this check at compile time). As a concession for these needs, we have things such as @objc and optional that signify that we're actually relying on the Objective-C runtime so that the correct switches are flipped to make this possible. While app development on Apple's platforms, which relies heavily on Objective-C (and these features), is probably the most common use case for Swift, this is not the only thing Swift is used for. As you've mentioned, Swift runs on other platforms as well, including those those that do not have an Objective-C runtime; in these cases these features are disabled. Thus, it's completely possible to learn Swift without knowing any of this; however, if you are working with Objective-C, say when writing an app, then it is useful information to have. If you're curious as to where you can find such information, Apple has a guide, titled Using Swift with Cocoa and Objective-C, that can help you learn more about this compatibility layer and how it was designed so you can use it effectively.

6 Likes

I guess your question was answered. However you can archive optional functions in protocols in Swift. You can define a protocol like this:

protocol SomeProtocol {
    func doSomething()
    func heightForElement(at index: Int) -> CGFloat
}
extension SomeProtocol {
    func doSomething() {}
    func heightForElement(at index: Int) {
        return 44.0
    }
}

When you define a default implementation for a protocol, you do not have to implement that specific function. So you can provide an empty body or a default return value, which should fit for most cases.


EDIT: Did't see @QuinceyMorris answer. How ever, it doesn't make sense to delete this answer now.

1 Like

Right. I’d wondered if it would be something like that. Thank you. It still seems odd to me though to have these “bridging” mechanisms baked into the language definition like this.

My preference it to do this pure swift if I can, or I’m not going to learn enough about the language.

My preference it to do this pure swift if I can, or I’m not going to learn enough about the language.

If you are writing Cocoa or Cocoa-Touch apps you ne3ed the objective=C run time to interface with the system frameworks. In my opinion that is also part of swift, i.e. learning how to use to to create usable applications for macos and ios devices.

1 Like

I guess when I think about it it's not much different to the JNI support mechanism in Java, just a little more intrusive.

It's a shame that an "extension" is needed which (to me) adds complexity when there are tokens/keywords in the language already that could have been used to achieve an (arguably) cleaner solution.

That's all good. Thanks all for your input. My extension is compiling now, especially now that I've worked out that I don't have to "import" the darn thing even though it's in a file of it's own.

I have to say that the Apple doc for Swift is not, IMO up to Apple's normal standard. They do a good job of explain 95% of everything, but don't actually explain 100% Trial and error programming is way too slow.

I'm not quite sure what you mean here. Are you suggesting that Swift itself (without the current Objective-C interoperability layer) can be made to work with Objective-C?

In Swift, files aren't imported, modules are.

The documentation was likely written by someone with knowledge of topic; as such, they may have skipped over things that they may have considered trivial. I'm sure they'd be glad to heard feedback about the guide from another perspective so they can improve it.

1 Like

No. At the moment, I'm aiming for pure-swift but I'm beginning to get the feeling from some of the replies that this might not be possible. I was suggesting that given the opportunity to define the syntax of the 'pure-swift' solution, they could have used the 'optional' keyword to define base or default implementations of func's instead of the 'extension' mechanism. e.g. to use @Maik639's code above:

protocol SomeProtocol {
func doSomething()
optional func heightForElement(at index: Int) -> CGFloat {
return 44.0
}
}

I guess in java I'd have my interface, a base, abstract implementation and that subclass that to provide concrete implementations.

The 'import' thing and the concept of a 'Module' is obviously something I skimmed. Back to read some more.

It's obvious to me now that I haven't read enough of the doc to appreciate the language as a whole. I thought, given I've worked with a lot of languages to date, that Swift would just be another C-like language and it would be easy enough to pick up with a read of the intro, and then a reasonable read of the main body of the language reference. I was wrong. Objective-C by comparison is far more straight forward from what I've seen so far.

Once I've read more and have a better understanding I'll be in a better position to make suggestions and feedback. It's clear that I'm not there now.

Thanks again for the answers; and I'm sorry if I'm coming across as critical.

tl;dr: Swift was born out of an Objective-C ecosystem, so it has things to make working in that system easier. But that's just how it's going to be on Apple platforms.

If you want to write pure-Swift, then you pretty much have to avoid doing any appleOS related stuff, which unfortunately is still a majority of Swift space. But the server-side (or just Linux in general) application of Swift is slowly reaching the point where you could start doing some actual useful stuff with it. And in those contexts, you only really have pure-Swift and C interop.

But I strongly disagree with the people who say Cocoa/CocoaTouch are part of Swift. They are not. They are part of the Apple ecosystem. Swift is just a language that was born from that ecosystem, so it was built with some things to make working with that ecosystem easier. As time has gone on and the language and Swift ecosystem have evolved it's become easier to do things in Swift-only fashion. But the fact remains that if you want to write Swift for Apple platforms, you'll be using Objective-C backed libraries for the foreseeable future.

That being said, there are some features that are @objc only atm like optional methods that could, in theory, be brought into the Swift runtime if they are put through the proposal process. It's been pointed out that this has already been rejected.

4 Likes

The lack of optional for Swift protocols is intentional and not temporary. See SE-0070:

Swift currently has support for "optional" requirements in Objective-C protocols, to match with the corresponding feature of Objective-C. We don't want to make optional requirements a feature of Swift protocols (for reasons described below), nor can we completely eliminate the notion of the language (for different reasons also described below).

3 Likes

Swift exposes protocol-oriented programming in a way that you won't find in Objective-C or Java. While Swift has "C family" roots like those other languages, there are some very deep areas of the language that you will not have experienced before, and this is one of them.

Swift certainly provides nice ways of calling Objective-C libraries, and a lot of work has gone into seamless interoperability between the two languages. With the right amount of @objc sprinkled about, you can indeed use Swift as "Objective-C with a nicer syntax." However, that is a deceptive façade. It's only one subset of a much larger and very different language, and it's the subset that includes perhaps the most exceptions for compatibility reasons.

"Optional requirements" are one such compatibility feature. The spelling "@objc optional" isn't for the compiler's benefit--it has no need of the "@objc" and (as far as I'm aware) its implementation in Swift actually has no dependency on Objective-C at all. Rather, this spelling is meant to communicate to you, the writer, that you're using a compatibility feature implemented only for the sake of Objective-C interoperability. Put another way, the reason you're required to write "@objc" isn't because Swift is so similar to Objective-C that it's borrowing its features, but because Swift is so different from Objective-C that, other than for interoperability purposes, certain Objective-C features wouldn't exist in Swift at all.

Swift's tentpole goals are safety (specifically, memory safety), performance, and expressiveness. To make the language a worthwhile contender, it adopts ideas that are either absent in other languages or much less emphasized because they've been bolted on later in their evolution. These would include features like optional types (introduced fairly early on to beginners), protocol-oriented programming (more difficult for beginners and a very deep feature with surprising results even for the experienced user), and (soon) ownership (intended to be an advanced feature). Even features that have counterparts in other languages can be quite different. Strings, for example, are Unicode-compliant by default and exposes an API for manipulation that explicitly discourages indexing into them. Mathematical operators have different orders of precedence than in Java or Objective-C (matching Go instead of C).

Chris Lattner likes to say that Swift is actually more complex than C++. The Swift Programming Language, by necessity, offers only a basic primer on each topic. After that, numerous books are now available for in-depth study. Personally, I've found Advanced Swift to be indispensable. Past that point, there are numerous resources to be found online for specific topics in Swift programming. WWDC videos and other talks can be helpful. The archives for these forums are also a good resource; they contain in-depth discussion both from the perspective of the end user (Using Swift) and the language designer (Evolution), and they're now easily searchable.

16 Likes

I have always simply had an optional reference to a closure in protocols where I felt I really need this

1 Like

Here's the way I would look at this: there are two things going on here.

  1. Swift itself is a stand alone language that is fully independent of Objective-C. You can see this today by using non-Apple platforms like Linux, which do not include or use the Objective-C ecosystem or runtime at all. There are still some minor missing pieces of the story, but it isn't fair to say that Swift "depends" on Objective-C.

  2. Swift on Apple platforms (which is what you're referring to) is a superset of the Swift language that includes a bunch of extensions for working with Objective-C APIs. This includes things like optional methods in protocols, bridging, @objc and other attributes for CoreData etc and other stuff that only makes sense to improve the interoperability with Objective-C. Much that complexity is not included in the base Swift language because it really is only there for interop with Objective-C. Careful factoring has been done to make sure that the core Swift language does not include any of that.

-Chris

1 Like

Wait wait, I don't think I've ever said that, and I would never enjoy saying that! :-)

I do agree that Swift is not a "simple language" - it definitely does have complicated bits and some other languages are simple. Its approach on this is to factor that complexity so it isn't in everyone's face unless they're deriving some value from it. This is the principle of "progressive disclosure of complexity".

-Chris

6 Likes

I stand corrected!

at lease swift doesn’t have T::T(T&& other);. also. it doesn’t have 3648170 different brace initializers

1 Like

Thanks @Chris_Lattner3 that is the way I was approaching the language at the start. The only reason I asked the question in the first place was that when I actually started to write my first class which is a port of one I have in an Objective-C project, I hit upon the 'need' for optional func's in a protocol. The documentation that I'd read thus far (the section titled "Optional Protocol Requirements" in the reference) gave me the impression that I had no choice but to include the @objc attribute. That led me to the mistaken impression that Swift could not exist without these "hooks".

Many have gone to pains to steer me the right direction. It seems that indeed, if I'm using Swift to write apps for iOS, I will at some point have to embrace some of these hooks. My hope is that I can keep that to a minimum; time will tell.

Well we have dark Lattner on the record here then. I love that talk btw, very informative.

1 Like

TBF, Chris and I were referring specifically to implementation complexity there. I think fairly uncontroversially, Swift shoulders a lot more implementation burden than C++ does, but it does so with the goal of hopefully reducing user burden in return.

4 Likes