"We all love Paul Hegarty." Stanford IOS8 public class personal note 3 Xcode, Auto layout, and MVC

Source: Internet
Author: User
Tags dashed line square root

Continue with the calculator demo in the last word. The last word is that the class must be initialized. The properties in the class must also be initialized, so you can't just declare without giving it a disposition, so the question is, why is the @iboutlet that we dragged from storyboard to just have a declaration without the need to initialize it because its type is still a optional, It has been assigned nil before you initialize it, which is why you don't need to initialize it again.

@IBOutlet weak var display:uilabel!

But since it is a optional type, then why Uilabel back is "! "Rather than"? "Then. For the actual language. They are not different, they are probably meant for a uilabel. But the actual use of the method is different, this is the compiler to help you do, suppose we change the exclamation mark in the back to question marks? The following section will error, indicating that it does not have the text of this member:


Of course we can add one to display. To unpack the bag.

display!. Text = digit
The reason for the drag-and-drop generation. The Xib interface on the left is initialized with the Viewcontroller on the right, so these @iboutlet are initialized and permanently initialized, assuming we add one every time we use them!

”。 That's too much of a delay. So the drag-and-drop generated variable type is followed by the self-added ". "This variable is expressed in spite of being a optional, but it has been unpacked, and we can use this variable without adding it."

Now we need a returnbutton to indicate that we have entered a number to be manipulated, we copy a button and change its value.


All Unicode characters can be used by us, including Chinese characters and expressions.

This button is associated with the VC, it does not need to pass the number of parameters, so the type of the parameter can be Anyobject, the method named enter

@IBAction Func Enter () {    }

The function of enter is to put our label real number into the stack. For the operation to be done.

How do you write in the code? Click the Enter key, then we will be a new number of input, so we need to change the flag bit:

    @IBAction Func Enter () {        Userisinthemiddleoftypinganumber = False    }

Perform a look:


It clears the function of the display, but why does the carriage return appear in the label now? I believe you have guessed the relationship of the button since we copied it. The ENTER key is still associated with the Appenddigit method, we just need to right click on the button in the popup menu "X" to cancel this association is OK:


Now we create an array to store the value of the operation. You can see how to define and initialize an array

var appendstack:array<double> = array<double> ()
Because the swift language is a strong language type. So we can not declare the type:

var appendstack = array<double> ()

You want to add the value of the current label to the stack when you click Enter. Suppose you write like this:

Appendstack.append (display.text!)
You will find an error. Since Appendstack is a double type and display.text is still a string type after unpacking, what can I do about it?

Here to introduce a new thing, we call it to calculate the attribute:

  var displayvalue:double {        get{        }        set{        }    }

Add a pair of curly braces after the definition, and then in the get and set methods, the function of this property is to calculate the value of the Display.text into double, the complete Displayvalue code:

var displayvalue:double {        get{            return Nsnumberformatter (). numberfromstring (display.text!)!. Doublevalue        }        set{            display.text = "\ (newvalue)"            Userisinthemiddleoftypinganumber = False        }    }

Now we make changes in the Enter method:

@IBAction Func Enter () {        Userisinthemiddleoftypinganumber = False        appendstack.append (displayvalue)        println ("Appendstack = \ (appendstack)")    }

Execute to try:


Press ENTER no longer displayed, console info:



Now let's add the operator button. They still have an action method in common:

Same as the carriage return. We still have the ability to find mathematical operators in special symbols:




Drag and drop define a new method operate, remember sender type write UIButton, get the value of button:

@IBAction func operate (Sender:uibutton) {let        operation = sender.currenttitle!            }

Next we show the operation flow in Swift, the old man says Swift's operation flow is very powerful, much stronger than other languages, which I deeply understand, I knocked the swift code has tens of thousands of lines. Control flow is really useful and efficient. and very intuitive.

First show the multiplication:

@IBAction func operate (Sender:uibutton) {let        operation = sender.currenttitle!        Switch operation{case        "x":            if Appendstack.count >= 2 {            displayvalue = appendstack.removelast () * Appendstack.removelast ()                enter ()            }//case "        ÷"://Case        "+"://Case        "?":        Default:break        }    }

The Removelast () method deletes the last element of the array. At the same time return its value, we can execute it. Enter the order for each operand, click Enter, then this number will be added to the stack, enter two numbers and then click Multiplication Sign button to perform the operation. The results are as follows:


Switch operation{case        "x":            if Appendstack.count >= 2 {            displayvalue = appendstack.removelast () * Appendstack.removelast ()                Enter ()            } case        "÷":            if Appendstack.count >= 2 {                Displayvalue = Appendstack.removelast () * appendstack.removelast ()                Enter ()            } case        "+":            if Appendstack.count > = 2 {                displayvalue = appendstack.removelast () * appendstack.removelast ()                Enter ()            } case        "?":            if Appendstack.count >= 2 {                displayvalue = appendstack.removelast () * Appendstack.removelast ()                Enter ()            }        default:break        }

You can see that the last result of the operation is saved in the array, and then the code for the next few buttons is intact, and you will find that the code structure is similar when copying the past. Assuming this is so obviously not beautiful, we need to create a new method to write these repeated methods in:

    Func performoperation (Operation: (double,double), Double)    {        if Appendstack.count >= 2 {            Displayvalue = operation (Appendstack.removelast (), Appendstack.removelast ())            enter ()        }        }

To be able to see something interesting, the type of the operation of our method is a function, yes, the function is often passed as a parameter type in Swift. So how do we write in the case that might surprise you:

Case "x":            performoperation ({$              * $            })

The simplified form of closures is applied here, and we do not need to specify the type of the parameters. Since Swift is strongly typed, it can proactively identify the type, and if you do not have a reference name, then the $ and $ $ represent the first two parameters, and the structure in the closure is a method with two parameters. Its return value is the product of two parameters, which also conforms to the definition of performoperation.

There's more cool! Assuming you have a method similar to Performoperation, the last parameter in the method at the time of the call can be written outside the parentheses, for example:

Case "x":            performoperation () {$ * $}

Assuming that there are other parameters in front of you, you can continue to write in parentheses, assuming that there is only one, then the parentheses can be omitted:

Performoperation {$ * $}
The Complete method code:
    @IBAction func operate (Sender:uibutton) {let        operation = sender.currenttitle!        Switch operation{case        "x":            performoperation {$ * $} case                    "÷":                        performoperation {$/$} case        "+" :           performoperation {$ + $} case                    "?":           performoperation {$-$}        default:break        }    }

We can see that in-and/such an operation that does not satisfy the commutative law, we change position, which is that the last element in the stack is always able to be calculated. You can recall the earliest code. Today's writing is quite concise!

Now we add a row of buttons, the first square root:


We just need to add a case to the control flow, such as the following:

Case "√":            performoperation {sqrt ($)}

SQRT is Swift's own root-finding method, and you will find an error. The reason is that the closure in our previous performoperation has two parameters, and there is only one parameter in this case. So how to change it, we need to copy the Performoperation code and do the following changes, for example:

  Func performoperation (operation:double-> Double)    {        if Appendstack.count >= 1 {            Displayvalue = Operation (Appendstack.removelast ())            enter ()        }            }

You will find that the names of the two methods are all the same. But we don't have to worry, because Swift will invoke the method according to the different parameters of its own initiative, now let's experiment, enter 36, click the root button:


has been implemented. It's that simple.

Now you're doing some optimization on the interface, and you're wasting too much space on the screen now. And you can't drag each button to set the spacing between each other, which is a waste of time.



First, the lower left corner is a bit empty. We added an empty button to occupy the position. And make sure it doesn't trigger whatever action


We want these buttons to be active and sparse, depending on the size of the screen, to keep the button group at equal distances from each border. We apply the layout button. This row button is below the screen:


Click on the first button and we can see some of the options:


We can choose left, top, center, and so on, but this is not the option we want, we open the second button:



We select both of these to indicate that all buttons have the same width and height:


Now to set the spacing:


Remember when we saw the Blue line, this 8 pixel spacing is the Blue Line alignment of the default pixel spacing, in addition to ensure that the red line is a bright state rather than a dashed state, so that the binding ability is added. Add a constrained interface:


Wow, I'm not. is not dazzled. To open the view outline, you can see the small yellow circle here, assuming it is red to prove that we have joined the constraints of conflict.



Remember what we talked about in the last word? The yellow markings here are somewhat different from what we expected, so turn on the small yellow circle. Click on an entry at random. For example, the following settings:


Remember to tick the following apply to all views in container. All warnings will be applied in the same way.


Now the warning is gone. It looks pretty good, yo. Take a look at:


It looks very slender on the Iphone6.


To switch to a horizontal screen:


Great, right?

Suppose you want to clear the constraint using a third button:



The above section clears the constraint for the selected item. The following section clears all constraints.

But actually our calculator is problematic. Since this part of our processing engine is independent, this involves the problem of MVC design patterns, and then all of our code satisfies the MVC design pattern, and now we're going to look at MVC:


MVC is a basic mechanism for classifying. The model (model layer) on the left contains our models, in which calculations are models.

The control layer controls how the view is displayed, and the view is the normal interface element that controls the model to use in the view. We use the indicator line on the road to make a comparison:


Between the controller and the model is a dashed line indicating consent for a temporary leap. But you need to observe before the past. The controller (C) must be fully master of the Model (M), since the controller's responsibility is to show the model to the user. So the controller has full access, it's a one-way arrow.


The same controller (C) is also able to reach the view (V), because the controller to send commands to the view, due to the controller Design view, we added a one-way arrow on a line of green small, outlet. Because when we have a property in the controller pointing to the view, the name of this property is outlet.


What about the model (M) and the View (V)? The answer is never!

Because the model is completely independent of the UI. This is why they are separated by a double yellow line.


So the view (V) sends a message to the controller (C)? Between them is a kind of blind communication. Not random communication, the way in which they establish communication is that the controller generates a target. The view then uses the action to feedback the information to the controller. For example, we clicked on a button or other action on a page. The page does not know what controller a controller is, it just knows that the action is generated on the page. and feedback to the controller, which is a blind, simple, structured communication mode.


So what do you do with some complicated operations? For example, should, would and did. I drag the screen this is a did action, I hold the screen ready to drag it when it is a will action, encounter such a complex action to do. The view is that it throws these questions to its agents, which are still things in the controller that answer how will, did, and should do the problem.


Another very important point is that the view should not hold the data it presents. The data cannot be used as its property. For example, there are 10,000 songs in your iphone. You can't expect it to hold 10,000 songs to show you. First, this is very inefficient, and secondly, these 10,000 songs should be in the model layer. Some controllers are responsible for choosing which songs to show. It is then taken from the model and presented in the view layer.

So what do we need to do when we swipe the screen and expect to get a lot of other songs? This is the second kind of proxy, we call it the data source datasource. The data source does not deal with such things as would and should, he answers how many songs there are and returns the quantity to the view. The view now opens up space for these 10,000 songs. So the function of the controller (C) is to interpret and format the data provided by these models (M) for the View (V).


So the question comes again, can the model communicate with the controller? Obviously not. But suppose the data changes how to notify our controllers? It still uses this method of blind communication. We think of the model as a radio station, which informs others of their own changes by means of radio, which is called notification and key Value observing (KVO) by iOS. Once the controller receives a message about the model change, it uses the Green arrow to request its change information from the model.

So can the view accept the broadcast of the model? Maybe you can but don't do this, which goes against the MVC pattern.


We can use this knowledge to make small applications, assuming project is very complex? We need multiple MVC. Multiple MVC overlays allow for complex functionality.


"We all love Paul Hegarty." Stanford IOS8 public class personal note 3 Xcode, Auto layout, and MVC

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.