Swift's responsive programming

Source: Internet
Author: User

Responsive programming of the original Https://github.com/bboyfeiyu/iOS-tech-frontier/blob/master/issue-3/Swift. MD

    • Original link: Reactive Swift
    • Original Author: Agnes Vasarhelyi
    • Development technology Front www.devtf.cn
    • Translator: Mr.simple
    • Reviewer: lollypo
    • Status: Complete

Let's go back to Apple's first objective-c successor,-swift, when it was an extraordinary moment. Siri has not yet opened the gates of Hell, Prezi has not subscribed yet, and North Korea hasn't hack anyone's email yet. The advent of a new language is very exciting for me, especially if it is a type-safe scripting language. Although Swift is still in rapid development, we don't have to worry about whether it is stable or not. When that moment comes, I should already know how to deliver neat, testable code. and a very flexible and fluid UI? If you're interested in something other than objective-c and MVC, read on.

MVC and MVVM

Let's start from scratch, and when we design an application, you might consider the architecture of the application first. The cocoa framework is based on Model-view-controller (also known as MVC), which is structured as shown in the architecture.

Although, you may find that this architecture does not make your design more effective, we can see that the role of controller is too complex. If you have experience using MVC on iOS or Mac, I bet you've learned that the view controller is taking on too much responsibility. The more you experience using MVC, the more you'll want to find another way to solve these problems with MVC. When using MVC to process network requests, you will find that this makes the controller extremely bloated, not only to handle requests for data, but also to render the data to the UI. What's more, do you ever try to do a unit test on a viewcontroller? You can't! This involves testing the view and business logic. As the complexity of the view grows, it becomes more and more difficult to maintain. This is why people do not test MVC.

Model-view-viewmodel (also known as MVVM) is a better choice for your application. This is a very powerful architecture pattern released by Microsoft for event-driven implementation. As you can see, unlike MVC, the view here holds the ViewModel character.

Of course, these depend on how you want to implement this pattern, however, eventually the MVVM pattern will bring you lower complexity and better testability. Can you achieve these effects at the same time? How can it be? I believe it anyway! It moves all the logic into the ViewModel role to reduce the responsibility of the view controller. (Translator Note: Please refer to this article for the differences between MVC, MVP, and MVVM.) )

Get out of the way, let brother use a project to demonstrate the usage of the MVVM pattern, a semi-automatic iOS client project to control the temperature of the cellar. If you want to learn more about this project, you can refer to this article. The key to this project is that we can see the temperature of each time period in the cellar through this app.

Let's go back to MVVM and the temperature of the cellar. To be able to read the temperature value, we need to use WebSocket on our server so that our MVC-based application can read it and display it on the iphone. First, we need to create a brew model class with a temperature field (temp) in this class.

ClassBrew {    0.  0}    

We also need to create a viewcontroller that displays the temperature of the cellar to the UI.

ClassBrewviewcontroller:uiviewcontroller {    @IBOutletvar templabel:uilabel!}  

In the way of MVC, we need to implement the logic of network request and the operation of updating UI in Viewcontroller.

socket.on (< Span class= "Pl-pds" > "temperature_changed" callback: {(anyobject data) -> span class= "constant" >void in  Self.brew.temp = data[ 0] as float Dispatch_async (Dispatch_get_main_queue (), {self.updatetemplabel ()})})      

Functions to update the UI:

Updatetemplabel () {self       . Brewlabelnsstring (format:"%.2f? C"self. Brew. Temp)}         

At this point, we successfully put the code in a viewcontroller, very good, right? Must not be!

Imagine this scenario when you need to verify the identity of the user, draw a real-time chart, or manipulate the fields of entry and exit. A complete example of the MVC architecture is here. But for now, let's look at the implementation of the MVVM-based architecture:

0.  0self. Brew= temp}}    

These are the variables stored in the ViewModel, and although they look a little strange, I don't know how to make them look less strange. Whatever it is, let's look at the socket first:

Socket. On ("temperature_changed"self= data[Float})      

In this way, the logic of the network request is moved to the ViewModel. But how do we modify the UI? KVO is our good friend, we use it to achieve, here is a code fragment in the Viewdidload:

Self. Brewviewmodel. Addobserver ("temp".  &brewcontext)      

We need to look at the temperature in the cellar, so I added a separate field for the view model. You might ask, why should we care if the brew model is in the view model? I would say that the brew model might have different fields, and you might need to serialize it, transmit it over the network, or something else. Therefore, we need its state.

override func observevalueforkeypath (keyPath: string, ofobject object:anyobject, change: [NSObject : Anyobject], Context:unsafemutablepointer<void>) { if context == &brewcontext { Self.updatetemplabel ((Change[nskeyvaluechangenewkey])  as float)} else {superobject, Change:change, Context:context)}}  span>                 

Wow, that's too much code? The KVO implementation produces a lot of boilerplate code, but it is much more lightweight than the MVC implementation, especially when we consider adding more and more features into our application, which are moved to the view model. Here is the full code snippet implemented by MVVM.

In short, MVVM is a lot better, but we still have the feeling that it can be optimized. Now that we know the key to showing the variable data model to MVVM's view is data binding, so what's better than responsive programming for this scenario?

Responsive Programming

"Reactive programming is programming with asynchronous data streams." "Responsive programming is programming in the form of asynchronous data streams. ”

If you are not familiar with this concept, I suggest you read this article (Chinese version here: In those years we missed the responsive programming), this is a very good introduction. In the world of responsive programming, anything is a stream. The following diagram shows the conversion of a button click or touch event to a stream.

If we use responsive programming in our project, this should be the case: the socket data is treated as a stream of temperature, and the stream is uilabel monitored. The process of converting them is also shown in functional programming, such as map, merge, filter, and other operations, which is great! Let's see how these concepts work with cocoa.

Reactivecocoa

When we plan to use responsive programming on cocoa, the best option is to use Reactivecocoa. Reactivecocoa is a data-binding framework inspired by functional programming.

It operates through signals that are defined as push-driven streams. This means that a signal represents an asynchronous workflow that will deliver data or arbitrary results to its observer in the future. In addition to the data model changes will produce a signal, Reactivecocoa also provides some built-in uikit/appkit bindings, such as rac_textsignal and other used things.

You may be slightly unsure when you plan to start your next Swift project, and you might also want to implement responsive programming in this project. Needless to say, developers on GitHub will help you implement these features. They are planning to release the Reactivecocoa 3.0 version named Great swiftening, but you can also use the 2.4.x version as they are stable enough.

Swift also has a number of functional operations built into the collection type, which makes it easy to perform certain operations that we do not need to work with repeatedly.

Let's look at how we create a reactiveviewmodel when using Reactivecocoa as the data-binding system for the MVVM pattern. Look at the code below, does our view controller look more elegant?

Self.brewviewmodel.tempchangedsignal. Map {(Temp:anyobject!) -> anyobject! in return nsstring (format:< Span class= "pl-s" >%.2f? C "as float)} ~> RAC (self.templabel,  "text" )}   

Because the complex C-type macros are not available in Swift, the RAC macros for OBJECTIVE-C are replaced. Thanks to Yusef Napora for providing a straightforward solution, there is a workaround in Colineberhardt's sample app.

Now we're back in the cellar temperature test project, we are ready to use responsive programming! Let's look at the rest of the code:

Socket. On ("temperature_changed"intempchangedsignal. Sendnext (data[0]). Deliveron (Racscheduler. Mainthreadscheduler ())})        

Here, we just create a temperature data signal and make sure that the Uilabel update is executed in the main thread. I have no resistance to Reactivecocoa! Now let's execute the HTTP request, processing the error that is thrown when trying to initialize a brew object on the server, the code is as follows:

Nsurlconnection. Sendasynchronousrequest (Request,QueueNsoperationqueue (),Completionhandler: {   (ResponseNsurlresponse!,DataNSData!,ErrorNserror!)-VoidInch    If error== nil {   Span class= "indent" >  Subscriber.sendnext (json ( Data)      Subscriber.sendcompleted ()    Span class= "indent" >} else {  Span class= "indent" >   Subscriber.senderror (Error) Span class= "indent" >   }})     

syncsignal . subscribeerror ({ (error:< Span class= "value" > Nserror!) -> Void in uialertview (title: < Span class= "Pl-pds" > "error creating Brew .localizeddescription, Delegate:nil, Cancelbuttontitle: ok" .               

We just need to implement error handling in Viewcontroller and wait for the magic of responsive programming to come to us, such as missing connections.

Cellar Temperature Monitoring project is a real example, at first I used the MVC in the OBJECTIVE-C implementation. The implementation is simple, but less surprising. Then Swift appeared, I naturally like this innovation. So I decided to rewrite the entire app. After a long struggle with the heavy controller and the UI refresh mechanism, I was not very proficient in these things, so I decided to try responsive programming. Because I already knew this was compatible with MVVM, So I decided to try. This experience clears half of my code. So, the value of the app that passes through Reactivecocoa is like twice times the value of the remaining code. From then on, make some adjustments (such as changing the state of the button based on some data) There is little cost to write a single line of code to send a signal-to-button command. Think about how much time it will take to use the original way!

There are many other factors that may make you want to try Reactivecocoa and Swift. If you want to be interested in how to brew beer, or just interested in the code, then you can see all the code here (brewmobile). If you have better technology to make this app even better, please let me know! Of course, we also welcome the contribution code.

Before concluding, share some of my thoughts about Brewmobile's future, and I'm planning to introduce react native to Brewmobile. If it's done, I'll share my experience again.

Swift's responsive programming

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.