preface

Every developer who sees SwiftUI will immediately associate the new UI framework with the Flutter. Yes, there are a lot of similarities — similar declaration syntax, real-time hot updates, cross-platform (SwiftUI is only across Apple platforms), and so on — that have made the mobile development community envious of the explosion of front-end technology exciting. So what are the similarities and differences between SwiftUI and Flutter? What are their advantages and disadvantages? And finally, in terms of technology direction alone, who are the winners of future cross-platform solutions?

language

It is true that modern computer languages are increasingly similar, because the basic goals of each language are fairly consistent: simplicity, flexibility, security, and high performance. At the same time, the excellent features of each language are being borrowed from each other, further reducing the gap between languages.

Swift and Dart, as the only official languages of the two UI frameworks, differ grammatically very little, and there are plenty of articles online comparing the pros and cons of the two languages. My experience is similar to most people’s, and for now, Swift and Dart have their pros and cons.

  1. Swift is more concise than Dart. Swift itself is already grammatically much simpler than Dart, with no need to add at the end of the sentence; The semicolon, etc. This is particularly evident when writing SwiftUI and Flutter directly. However, the problem is not entirely a linguistic one, but also related to the design of both UI frameworks.

    ForEach(userData.landmarks) { landmark in
    	NavigationButton( destination: LandmarkDetail(landmark: landmark)) {
        LandmarkRow(landmark: landmark)
      }
    }
    Copy the code
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (context, index) {
          final landmark = landmarks[index];
          returnLandmarkCell( landmark: landmark, onTap: () { Navigator.push( context, CupertinoPageRoute( builder: (context) => LandmarkDetail( landmark: landmark, ), ), ); }); }, childCount: landmarks.length, ), ),Copy the code

    Both implement a clickable list page, and both invoke a custom Cell.

  2. Swift is more stringent than Dart, which in some ways makes it safer, though security is ultimately a matter of people.

  3. Swift has no await/async in its 5th year of release, although it has been proposed but never implemented. Dart doesn’t have a selection either. It is not enough to say that the two absorb each other.

  4. Dart’s dark Technology: Both AOT and JIT support gives the Flutter a web-class hot overload feature, which is a powerful weapon against SwiftUI.

  5. Swift and Dart are both open source languages. Apple’s opening of Swift is unprecedented. Swift can now run outside of macOS. At the same time, a series of interesting things like back-end framework Vapor have appeared in the community, and it has become one of the official languages of Tensorflow. All this greatly expands the use scenarios for Swift. However, the Dart is noticeably faster in terms of gameplay than the Swift. Back-end frameworks developed with it have been put into production by several companies, and Google’s Web framework, AngularDart (non-Flutter Web), has been running reliably on a number of services for a long time. Not to mention running across iOS, Android, macOS, Windows Web with the Flutter.

How well a language is designed does affect the popularity of a framework, and I have heard numerous Flutter developers joke about the Dark’s endless nesting problems. While Dark is more playable, I personally think Swift is significantly better than Dart when it comes to a single UI framework.

grammar

Both SwiftUI and Flutter use declarative syntax and their own DSLS to describe the UI. The good thing about SwiftUI and Flutter is that you can see the structure of the actual UI from the structure of the code at a glance and avoid repetitive logical code. SwiftUI replaces complex control logic with data binding and state management, and DSLS make the code structure highly consistent with the HIERARCHY of the UI.

VStack {
    MapView()
        .edgesIgnoringSafeArea(.top)
        .frame(height: 300)

    CircleImage()
        .offset(y: -130)
        .padding(.bottom, -130)

    VStack(alignment: .leading) {
        Text("Turtle Rock")
            .font(.title)
        HStack(alignment: .top) {
            Text("Joshua Tree National Park")
                .font(.subheadline)
            Spacer(a)Text("California")
                .font(.subheadline)
        }
    }
    .padding()

    Spacer()}Copy the code

Above is a SwiftUI Demo LandMark on WWDC. Even if you haven’t studied The grammar of SwiftUI, a little reading of the code above will tell you that it matches the UI in the image one by one. This is the advantage of declarative syntax. But when it comes to writing code, Flutter and Swift feel very different. The most obvious thing is that Flutter is much more complicated than SwiftUI. How much code does it take to implement the above effect with Flutter? So much that I can’t even paste it in, otherwise half of my article would be Dart code. But here’s a person who wrote a version of the Flutter that you can take a look at.

Why is Fluter so much more complex than SwiftUI with the same declarative syntax? This is a reflection of the different ways in which Apple and Google design these two UI frameworks, and even the different cultures of the two companies. Developers who know anything about iOS and Android know that developing for iOS is much easier than developing for Android. In terms of configuring the development environment alone, iOS can start writing code up to a day earlier than Android. Not to mention complex frameworks, confusing platform compatibility, and unreadable documentation.

Apple treats developers like novices, doing everything in its power to simplify the process, reduce the workload, and even make development elegant, from the look and feel of Xcode to the system API to Swift. Google, on the other hand, treats developers more like geeks, giving them a lot of work and creativity, leaving them free to create interesting things. But correspondingly, the barriers to entry are high, and the fragmentation and uncontrollability that freedom brings leads to less efficient development.

In designing the SwiftUI API, Apple has hidden a lot of the internal details so that developers can use as little code as possible to achieve the effect. Developers don’t need to override initialization methods, they don’t need to use returns, they don’t need to care about context, they don’t need to care whether it’s a StatefulWidget or a StatelessWidget, Don’t even care if you’re using Material Design or iOS Style. All you have to do is tell the compiler what controls you need, what they look like, where they should be, and that’s it. If the declarative grammar that Flutter brought to mobile development was a surprise to everyone, SwiftUI shows everyone (including The Flutter) what declarative grammar really is.

Updated in real time

The most important feature of SwiftUI is the much anticipated hot loading, or real-time updates. High development efficiency on the Web has long been a coveted skill for mobile, and RN is the first mobile developer to see this possibility, although it has its own problems. With Flutter being an extension of Web technology and inheriting a number of Web technology features, hot loading seemed like a handy skill to have. SwiftUI faces a much more complex challenge in achieving a web-like real-time refresh. From my actual experience down, also fully illustrates this point.

SwiftUI live preview is divided into static preview and dynamic preview. Static previews are shown by default, which are fast and can be written both in code and visually. But it doesn’t respond to any events and can’t scroll or jump to the page. If you need dynamic debugging, you need to switch to dynamic preview. Dynamic previews take a compile time, and then respond to UI changes in a fully dynamic manner in real time, and can be debutted in real time on the real machine. However, the limitations of dynamic previewing are quite large. It is not possible to compile the App once, as with Flutter, and then update the entire App dynamically.

Why static and dynamic previews? I’m sure Apple wouldn’t have complicated this issue if it hadn’t been for some issues (performance issues, intractable bugs). Let’s just say that the current disabled version of hot loading is the best Apple can do for us. For this reason, SwiftUI’s real-time refresh, which is far from the Web and Flutter, is still in its infancy. Static UI debugging can be done entirely through storyboards, but real dynamic previews have some limitations. SwiftUI, however, is still in beta, and it’s too early to make definitive statements about its performance.

performance

Google claims that one of the goals of the Flutter is fluency (60Hz), and so far it has achieved that in most scenarios. However, in my tests (which are in beta), there is some pressure to get to 60 Hz for things like page transitions and control animations. I’ve been following the Project with the Flutter and internally we’ve been trying to rewrite some of the modules using the Flutter. But what I’ve experienced so far, the current Flutter, is very close to the fluency of the native platform. But even if the Flutter was able to achieve the system’s native fluency, there was always a performance penalty. The native UI framework of iOS (including SwiftUI) is built on top of Metal, which is much more efficient for GPU use than OpenGL. The results also showed in my tests that Flutter had higher CPU and GPU utilization than the iOS native UI framework for the same page rendering and animation. And high performance consumption, for equipment means high heat and low endurance. This is especially true on mobile devices.

With SwiftIU, Apple seems to have copied all of the system’s native controls. In principle, there will be no performance improvement, but don’t be fooled by your eyes. Apple is playing a big game where you can’t see.

The two images above are SwiftUI and the Label for iOS native rendering. They both run on iOS and look exactly the same, but behind them are two completely different things. We found that the Text in SwiftUI is no longer a native iOS control, but a new type called Text. It is a new control, inherited from the UIView full name is DisplayList ViewUpdater. Platform. CGDrawingView. If you look at the properties window on the right, you see that the two controls have completely different properties. UILabel has complex properties to control styles, interactions, and so on. Text is much more compact.

Rumor has it that some of SwiftUI’s controls have abandoned the system’s native UI framework in favor of more low-level, more generic rendering of Core Animation, Core Graphics, and Core Text within the Apple ecosystem. I don’t know if the underlying framework is directly used to render SwiftUI efficiently, but for now it’s clear that Apple is taking SwiftUI out of its UI framework and losing its historical baggage. There are many benefits to this, such as greater freedom, better performance, and the real thing: cross-platform.

Cross-platform?

A lot of people will probably say that SwiftUI and Flutter are not comparable and SwiftUI is not really cross-platform. True, SwiftUI currently crosses Apple’s own ecosystem, which includes iOS (iPadOS), macOS, watchOS, and tvOS, while Flutter is getting tired of mobile and moving to Windows, macOS, and the Web. However, you can’t deny that SwiftUI does achieve Write Once, Use Anywhere on a completely different platform. And the thinking behind it is completely different.

SwiftUI doesn’t build uIs fundamentally, it describes them. What’s the difference between the two? When you build the UI, you specify the type of each control, even down to the platform. For example, in the native UI framework, you need an input field, and depending on the platform, you have to choose between UITextFiled (iOS) and NSTextFiled (macOS), which have different properties, looks and features. With Flutter, you don’t need to think about the control type of different platforms, but you do need to think about the Style of the control. There are some Android controls with Material Design and iOS controls with iOS Style, and many of their features are not consistent. All of this adds more logic and effort to the UI build.

SwiftUI is more like a template for the Web. It only describes the UI, but what the controls look like and what features they have are implemented automatically, depending on the platform on which they are compiled. It’s like putting a template, a theme on the Web.

The code on the left describes a form that contains some simple controls, including Picker, Toggle, Stepper, and Button. If we put the code intact in the macOS project, it will look like this.

You’ll notice that the same code is presented with a completely different UI, but what the UI says is exactly the same. To add to the horror, Picker, a “single list selection” control, is translated as a selection page on iOS. Clicking a cell pushes out all available options, and clicking the option returns to the previous page and displays the selected contents to the corresponding cell. On macOS, the Picker is translated into the drop-down list that is common on our desktop operating systems. The transformation is incredible. I can only describe it as Wow, Awesome and Amazing. Because it fully conforms to the platform design language and user usage habits, and greatly reduces the difficulty of development and adaptation. But SwiftUI can do more than that.

That’s right, not only for iOS and macOS, but also for tvOS and watchOS, SwiftUI will present each control in a way that best suits the design language and interaction of the platform. In addition, you will automatically gain a number of system features, such as Dynamic Type, Dark Model, reading direction adaptation, and so on.

In this regard, SwiftUI has a much more similar mindset and technology to React Native. It’s just that Facebook has almost no say in either iOS or Android, so compatibility and consistency are problematic. In order to achieve this compatibility, React Native requires a lot of work on its own and developers have to deal with various issues, making it an awkward intermediate technology.

SwiftUI and React Native are fundamentally different from the cross-UI platform thinking of Flutter. Flutter completely rejects the platform’s native UI framework, similar to “drawing” each control pixel by pixel on a canvas, similar to a 2D game engine. Its purpose is also clear: to ensure that the same code shows exactly the same UI across different operating systems, hardware devices, and screen sizes. This seems to be what developers want, as we’re fed up with the uncontrollable differences RN shows across platforms. But even leaving aside the differences in operating system design languages, the UI should at least look very different under different screen sizes. The UI on the desktop and the UI on the mobile platform, and even the UI on the watch, should have completely different UIs and interactions depending on the user’s habits and controls. Trying to implement multi-platform adaptation on the Flutter can be a nightmare for any programmer. You need to make a lot of judgments, and you may need to use multiple controls to implement a single function, and you may end up with a lot of tests and bugs.

But there are pros and cons. SwiftUI’s near-perfect cross-platform solution is built on a lower degree of freedom. As you can see from the above examples, the Demo uses the system’s native control styles. That’s not to say we can’t customize it, it’s just:

  1. There aren’t enough projects we can customize
  2. The more we customize content, the more features the system automatically adds for us are lost

For example, if we want to change the color of the list background, then we will lose some of the Dark Model features that the system automatically added for us. You will need to do some extra work to tell the App what color the background should show in black/white mode.

But the good news is that Apple has been trying to move away from the system’s original UI framework, which makes it easier for us to customize parts of the UI. In the past, to implement the following Button style, we had to make a lot of adjustments to the UIButton parameters, because the default UIButton is text on the left and image on the right. Today, with SwiftUI built out of the system UI framework, we can implement complex UI styles with extremely simple code.

That’s not quite as accurate to the pixel as Flutter prides itself on being, and we probably don’t have complete control over all the details of the UI controls. But like painting, you lose a certain amount of freedom in exchange for faster and more efficient development, which is exactly the Apple corporate style.

But is the cross-platform story for SwiftUI finished? I think this is just the beginning. SwiftUI’s completely platform and device agnostic, purely descriptive UI framework is exactly the right direction for cross-platform solutions. SwiftUI can be used to describe iOS, macOS, tvOS, and even watchOS UI. Why can’t it be used to describe Android, or the Web? SwiftUI already has Flex layout, Combine data binding, hot loading, etc. We just need to follow this idea and apply the Android or Web template to SwiftUI to get the same UI that conforms to the platform design language and specifications. Of course, this isn’t nearly as simple as I’d like to suggest, but don’t forget that Swift is open source and cross-platform isn’t an issue either. As long as the conditions exist, everything is possible.

But what will Flutter look like then? Flutter will be one of the first cross-platform initiatives for most companies, at least for now, while SwiftUI is at least 2-3 years away from widespread use.