قالب وردپرس درنا توس
Home / IOS Development / Security statements in Swift

Security statements in Swift



guard and defer came with us in Swift 2.0 for a little fanfare. Both usage cases were somewhat obvious initially and many articles were written about how to use these features. guard seemed especially to solve some sticky issues that Swift programmers came in often, but there was a lack of a more thorough exploration of real world usage of these concepts. We cover guard today and possibly defer in the future.

Guard combines two powerful concepts that we are already used to in Swift: optional unpacking ] and where clauses . The former lets us avoid the pyramid of the verdict or its alternative, the very long whose la statement. The latter adds a simple but powerful expression with where the clause so that we can further know what the results we validate.

When Using Guard

If you have a display controller with a few UITextField items or another type of user input, you will notice immediately that you need to unpack textField.text optional to get to the text inside (if any!). erEmpty will not make you good here, without any input, the text field will simply return zero.

So you have some of these that you extract and eventually transfer to a function that adds them to a server endpoint. We do not want the server code to handle null values ​​or incorrectly send invalid values ​​to the server so we will pack the input values ​​with the guard first. func send [1

9659009] [19659000] [19659000] [19659000] [19659000] la name = nameField.text send ""
return
}

guard la address = addressField.text other {
show ([19659018] [19659000]] = phoneField.text else [19659000] {19659016]
show ( "No Phone To Submit" )
Return
}

SendToServer (Name, Address: Address, [19659000] 19659009] phone: ] phone:
}

FUNC sendToServer [19659000] (Name: String, Address: [19659009] String, Phone: ] String) {

}

You see that our server communication function does not take strict ] values ​​as parameters, thus guiding in advance. The packing is a little unintuitive because We are used to packing with if which unwanted values ​​to use inside contain a block. Here, the message's statement has an associated block, but it's actually a block else – that's what you do if unwrapping fails – the values ​​are extracted right into the same context as the actual sentence.

// Separation of Concerns

Without Guard

Without using Guard we would end up with a large pile of code that resembles a pyramid of demise. This does not work well to add new fields to our form or make for readable code. Entrance can be difficult to follow, especially with so many other statements at each fork. func nonguardSubmit [19659000] () {
if la ] name = nameField.text {
if ] address = addressField.text {
if la phone = phoneField.text {
sendToServer [19659000] [] [19659000] [[19659000]] Address: Address, Phone: Phone)
} [19659011] ] {19659023] show ( "no name to send" ] ]
] Other [19659000] Yes, we can even combine all these if let statements in a single sentence separated by commas, but we would lose the opportunity to find out which one
statement that failed and present a message to the user. [19659002] If you start to see this type of code appear in one of your viewers, it's time to start thinking about doing the same with .

Validation and Testing with Guard

An argument against using guard is that it urges large and less testable features by combining multiple value tests all in one place. If used, this may be true, but with proper use, [Guardian] guard may give us proper discernment so that the View Controller manages viewers while validating these items can be in a fully tested validation class or extension.

Let's take a look at this naivel constructed guard sentence with validation:

  guard    la    name    =    nameField.text   ] where    name.characters.count   >    3   &&    name.characters.count   <=    16     la    Area    ] =    name.rangeOfCharacterFromSet (NSCharacterSet.whitespaceAndNewlineCharacterSet ())    where    range.startIndex    ==    range.endIndex    otherwise    {
     show 19659030] "Name Failed Validation" ) 
      Back 
} 

  Submit (Name) 

You can probably say that we are filling out a lot of functionality in a single line here. Not only do we look for the existence of the name field, we also check that the name is between 3 and 16 characters in length and that it does not contain any new lines or white spaces. This is busy enough to be almost illegible and it is unlikely to be tested because we can not validate the name field without interacting with the user interface and sending the name of the server.

Realistic, this display controller could handle 5 inputs and each should be checked for validity before it is submitted. ()

  (19659006) 

  (19659006)] {
     guard    la    name    =    nameField .text    there    IsValid (name)    other    {
          show ([19659018] "name failed validation" ) 
          back 
    } 

      send 

 ] 

  func    isValid  (name:    String)   ] [>19659009] Bool    {
      // check name is between 4 and 16 sign 
      if  !   .   16   ~ =    name.characters.count)    {
          back    false 
    } 

      ] // check that the name does not contain white or new characters 
      la    vary    =    name.rangeOfCharacterFromSet (.whitespaceAndNewlineCharacterSet ()) 
      if    la    vary    ] =    vary    where    range.startIndex  ! =    range.endIndex    {[19659020] return    false 
    } 

      return    true 
} 

You will notice some differences in the updated version. Firstly, our name validation feature is separated into a testable validation function (placed either in the display control or in another, fully tested class depending on your preferences). isValid has clearly marked steps to validate a name: a length control and a character check.

Instead of rejecting all the validation in the Var clause, we only call the isValid function from where the clause, if not guard statement about the text is null or not approved.

Testing is great, but the best part of this implementation is the clarity of the code. tappedSubmitButton has very little responsibility, many of which are unlikely to fail. View controllers are difficult to test on iOS using standard MVC organization (which despite many new players remains the clearest organizational pattern) so minimizing their responsibility or likelihood of errors is an important part of the architecture of iOS- app.


guard has clear usage cases, but may be tempting to be used as part of a massive display control. By distinguishing between guard and validation features, you can maintain more complex display controllers without losing clarity or readability.


Questions or comments? Find us at twitter or send a problem on github




Source link