Hugo, para já é pura curiosidade no Swift. Instalei o Xcode 6 beta e nem o abri. :( Vou vendo alguns exemplos para ir aprendendo alguma coisa e partilho com vocês os que acho importantes. Estou a terminar um projecto (MoneyEX Pro) e só no início do próximo ano começarei a trabalhar com o Swift.
Att, António Pinto No dia 04/09/2014, às 16:10, Hugo Ferreira <[email protected]> escreveu: > APintex, > > Acabei à pouco tempo de ler 2 bons livros de desenvolvimento Android. > Já desenvolvi diversas ANE's para Android e já me sinto suficientemente > confortável para desenvolver qualquer app para Android ou mesmo ANE. > > Em breve gostaria de entrar no desenvolvimento nativo para iOS (tanto apps > como ANE's) e aqui ficam algumas dúvidas: > 1. Não faz sentido nesta altura do campeonato investigar em Objective-C > (thank you god); > 2. Será que não vale a pena esperar por um bom livro que seja uma compilação > do desenvolvimento Swift (de preferência em PT). Ainda não vi nenhum na Fnac; > 3. Será que irá ser possível desenvolver ANE's com swift. Penso que aqui a > única coisa que falta é a lib que actualmente é para Objective-C (para alguém > transcrever tem de saber bem Objective-C) ou será possível usar a actual ? > > As minhas expectativas são: > - Dentro de 1 ano o iOS8 tenha mais de 80% de market share para valer a pena; > - Existam bons livros e exemplos; > - Exista um lib para Swift (a Adobe tem de fazer) ou ser possível usar a > actual (não sei); > - Exista uma framework para Bluetooth LE (para mim é importante) tal como já > existe com Objective-C ou se possa usar as actuais. > > > > 2014-09-04 15:58 GMT+01:00 APintex Gmail <[email protected]>: >> >> António Pinto >> [email protected] >> >> >> >> http://realm.io/news/swift-enums-pattern-matching-generics/ >> >> Sign up to be notified of future videos >> >> We won’t email you for any other reason, ever. >> >> Enums (0:40) >> >> Enums are a kind of abstraction that allow you to give a variable one value >> among several related values. For example, when building a state machine you >> could have an enum that describes the state of an object from a set number >> of states. There are three types of enums in Swift. >> >> Basic Enum (1:12) >> >> The most basic Swift enum simply has a bunch of cases and is declared using >> the enum key word. In this example, the enum is called Direction and can >> only be one of the four provided cases. To declare an enum, you use the enum >> name, followed by a dot and then one of the possible values. Unlike in >> Objective-C or C, enums are not typedefs of aliases for integers. >> >> enum Direction { >> case North >> case South >> case East >> case West >> } >> >> let myDirection = Direction.North >> Raw Value Enum (2:00) >> >> The second type of Swift enum is a “raw value” enum, which is the same as >> the basic enum but has additional raw values associated with each case. In >> this enum Title, each case has an associated string that is the name for the >> title. Important to note is that the raw value and the enum itself are not >> interchangeable. The toRaw and fromRaw methods help to go between the value >> and the enum. >> >> enum Title : String { >> case CEO = "Chief Executive Officer" >> case CTO = "Chief Technical Officer" >> case CFO = "Chief Financial Officer" >> } >> >> let myTitle = Title.CEO >> let myString : String = Title.CEO.toRaw() >> let anotherTitle : Title = >> Title.fromRaw("Chief Executive Officer")! >> For integer type raw enums, integer numbering remains implicit if you do not >> specify values. Swift automatically counts up from the last provided >> explicit value. This can be seen in the following example: >> >> enum Planet : Int { >> case Mercury = 1 >> case Venus, Earth, Mars // 2, 3, 4 >> case Jupiter = 100 >> case Saturn, Uranus, Neptune // 101, 102, 103 >> } >> Associated Value Enum (3:52) >> >> The third type of enum is one with associated values. Each case in the enum >> can carry associated data. In this example from the Swift book, the bar code >> enum allows you to associate different QR codes with different strings. >> >> enum Barcode { >> case UPCA(sys: Int, data: Int, check: Int) >> case QRCode(String) >> } >> >> let myUPC = >> Barcode.UPCA(sys: 0, data: 27917_01919, check: 2) >> let myQRCode = >> Barcode.QRCode("http://example.com") >> Associated values are especially useful in handling JSON, because arrays and >> dictionaries are actually types. Thus, you can create an enum to represent a >> JSON structure as a tree, with JSON nodes wrapping different types. >> >> enum JSONNode { >> case NullNode >> case StringNode(String) >> case NumberNode(Float) >> case BoolNode(Bool) >> case ArrayNode([JSONNode]) >> case ObjectNode([String:JSONNode]) >> } >> >> let x : JSONNode = .ArrayNode( >> [.NumberNode(10.0), >> .StringNode("hello"), >> .BoolNode(false)]) >> Switch Statements (Pattern Matching) (6:17) >> >> Switch statements is where most of the pattern matching functionality in >> Swift comes from. A basic switch statement looks very similar to an >> Objective-C switch statement, where there is a clause followed by cases. Two >> things to note: Swift switches don’t have breaks, so for old style >> fallthrough behaviour, your code must have an explicit use of the keyword >> fallthrough. Switch statements must also be comprehensive, so default cases >> are required, which may help prevent errors. >> >> let value = 10 >> switch value { >> case 10: println("ten") >> case 20: println("twenty") >> case 30: println("thirty") >> default: println("another number") >> } >> Ranges (8:35) >> >> In Swift, you can also pattern match on anything that’s comparable. You can >> even match strings now to a case (and printout emojis for a fun parlor >> trick!). Anything that can be compared with the double equals operator can >> be matched. Swift also allows matching on ranges, where ranges can be the >> pattern inside a switch state. >> >> let v: UInt = 10 >> switch v { >> case 0...9: println("Single digit") >> case 10...99: println("Double digits") >> case 100...999: println("Triple digits") >> default: println("4 or more digits") >> } >> Tuples (9:00) >> >> Tuples are composite data types - they contain multiple elements that can >> all be of different types. A tuple is then represented by the types of its >> elements. In this tuple-based switch statement, a tuple is the input. Each >> element in the pattern tuple is actually a sub-pattern, so you can match >> against patterns in each element. The underscore represents a “I don’t care” >> value. In this example, the last case functions as a default because the (_, >> _) says the same thing as a default - none of the other cases match, and we >> don’t care about other possible values. >> >> let person = ("Helen", 25) >> switch person { >> case ("Helen", let age): >> println("Your name is Helen, and you are \(age)" + " years old") >> case (_, 13...19): >> println("You are a teenager") >> case ("Bob", _): >> println("You are not a teenager, but your name" + " is Bob.") >> case (_, _): >> println("no comment") >> } >> Binding in Cases (10:56) >> >> If you have case statements, there may be associated data that needs to be >> used in the case statement body. The let binding is how you can do that. The >> first two cases in this example take the tuple elements and create the >> bindings X and Y to represent those elements. >> >> let myTuple = ("abcd", 1234) >> switch myTuple { >> case let (x, y): >> "The string in 'x' is \(x); " + "the integer in 'y' is \(y)" >> case (let x, let y): >> "Another way to do the exact same thing" >> case (_, let y): >> "We don't care about the string in 'x', " + "but the integer in 'y' is >> \(y)" >> } >> Enums (12:22) >> >> You can also switch on enums, but for enums with values wrapped inside, >> switch statements are the only way you can access those values. The >> following switch statement uses let to bind each case and use the value. >> >> enum ParseResult { >> case NumericValue(Int) >> case Error(String) >> } >> >> let a = ParseResult.NumericValue(1) >> switch a { >> case let .NumericValue(v): >> "Success; numeric value is \(v)" >> case .Error(let err): >> "Failed; error message is \(err)" >> } >> Types (13:20) >> >> The main type of switch is the type/sub-class pattern. If your switch >> conditional in this clause is a class, then class will have sub- or >> superclasses. In this example, the UIView is matched against the different >> possible types of views: UIImageView, UILabel, and UITableView. The “as” >> keyword differs from the “is” keyword in that “as” allows you to use the let >> binding and do something with myView, while “is” is used simply to check the >> type. >> >> let myView : UIView = getView() >> switch myView { >> case is UIImageView: >> println("It's an image view") >> case let lbl as UILabel: >> println("It's a label, with text \(lbl.text)") >> case let tv as UITableView: >> println("It's a table view, with"+ " \(tv.numberOfSections()) sections") >> default: >> println("It's some other type of view") >> } >> where clause (14:33) >> >> Another important thing about switch statements is the where cause. This >> clause can be added to any case and acts as a boolean expression that >> returns true or false. The case is then taken only if this where clause >> returns true. This switch example relies not on pattern matching but instead >> on these where clauses, following through with the case if myView is of a >> certain size or other characteristic. >> >> let myView : UIView = getView() >> switch myView { >> case _ where myView.frame.size.height < 50: >> println("Your view is shorter than 50 units") >> case _ where myView.frame.size.width > 20: >> println("Your view is at least 50 units tall," + " and is more than 20 >> units wide") >> case _ where >> myView.backgroundColor == UIColor.greenColor(): >> println("Your view is at least 50 units tall," + " at most 20 units wide, >> and is green.") >> default: >> println("I can't describe your view.") >> } >> Expression Operator (15:28) >> >> A final important feature in Swift is the expression operator. >> >> func ~=(pattern: Type1, value: Type2) -> Bool >> This operator takes the pattern and the value, and then uses pattern >> matching to return true or false. It can be overloaded as well to implement >> custom matching behaviour. The following piece of code is Swift pseudo-code >> to demonstrate what you could build. In an array four elements long, you >> could create cases that matched any combination of the elements. >> >> let myArray = [1, 2, 4, 3] >> switch myArray { >> case [..., 0, 0, 0]: >> doSomething() >> case [4, ...]: >> doSomething() >> case [_, 2, _, 4]: >> doSomething() >> case [_, _, 3, _]: >> doSomething() >> case [_, _, _, 3]: >> doSomething() >> default: >> doDefault() >> } >> Expression Patterns (17:42) >> >> The following extended example is a custom implementation of the pattern >> match operator. This custom operator turns the elements of an array into the >> enum values. >> >> enum WCEnum { >> case Wildcard >> case FromBeginning >> case ToEnd >> case Literal(Int) >> } >> >> func ~=(pattern: [WCEnum], value: [Int]) -> Bool { >> var ctr = 0 >> for currentPattern in pattern { >> if ctr >= value.count || ctr < 0 { return false } >> let currentValue = value[ctr] >> switch currentPattern { >> case .Wildcard: ctr++ >> case .FromBeginning where ctr == 0: >> ctr = (value.count - pattern.count + 1) >> case .FromBeginning: return false >> case .ToEnd: return true >> case .Literal(let v): >> if v != currentValue { return false } >> else { ctr++ } >> } >> } >> return true >> } >> Protocols (21:06) >> >> In order to understand generics, you have to understand protocols, which are >> something that existed in Objective-C as well. Protocols are basically a >> contract that can define nothing at all or any number of methods and >> properties. However, protocols can’t have any implementation details - they >> can only have method signatures and property names. MyProtocol in this code >> defines just one property as requiring a getter and setter, as well as one >> method. >> >> protocol MyProtocol { >> var someProperty : Int { get set } >> func barFunc (x: Int, y: Int) -> String >> } >> Types can conform to none, one, or multiple protocols. Protocols can also >> inherit from other protocols, thereby getting all the parent protocol’s >> methods and properties. >> >> Conformance (23:18) >> >> With protocols, you can make classes, structs, and enums conform to them. By >> making a type conform to a protocol, you are telling the compiler that your >> type will match the definitions set in the protocol. MyClass conforms to >> MyProtocol in providing implementations that match. >> >> class MyClass { >> // Nothing here... >> // This won't compile! >> } >> >> class MyClass : MyProtocol { >> var myProperty : Int = 0 >> // Property conformance >> func barFunc (x: Int, y: Int) -> String { >> return "\(x) + \(y) = \(x + y)" >> } >> var someProperty : Int { >> get { >> return myProperty >> } >> set { >> myProperty = newValue >> } >> } >> } >> Uses (24:06) >> >> There are a few reasons you may want to use protocols. The first reason is >> parent-child relationships, where you don’t want all the children to have a >> specific class of a parent. For example, UITableView comes with Cocoa and is >> a list of objects that specifies the number and content of cells. For the >> delegate to provide that information, it just has to implement the protocol >> which has methods for the cells. This way, you can avoid specifying the >> delegate as a sub-class of a class. >> >> A second major use for protocols can be seen in the Swift Standard Library, >> where they add functionality to a type, piece by piece. Equatable, >> LogicValue, and AbsoluteValuable are all protocols that are implemented by >> different types in the library. The LogicValue protocol has a method that >> takes an object and turns it into true or false, so if you create a custom >> type and implement this protocol, you can use that type in an if statement’s >> clause. >> >> One final use for protocols is to allow different types to be described by >> the same generic type parameter. For example, if you wanted to put different >> types into an array, you could give the objects a protocol and then declare >> the array with the protocol. You then have an array of equatables and >> anything that conforms to the equatable in that array can be added. >> >> protocol JSONType { } >> extension String : JSONType { } >> extension Float : JSONType { } >> extension Bool : JSONType { } >> extension Array : JSONType { } >> extension Dictionary : JSONType { } >> >> let b : Array<JSONType> = [10.1, 10.2, "foo"] >> let a : Array<JSONType> = [10.0, "bar", false, b] >> Generics (28:36) >> >> Generics did not exist in Objective-C. THey are basically the statically >> typed languages’ answer to the flexibility of dynamically typed languages. >> Generics are used to allow you to use the same code for different types. The >> type parameter allows you to do this generically. >> >> func swapItems<T>(inout this: T, inout that: T) { >> let tempThis = this >> this = that >> that = tempThis >> } >> With generics, you can also enforce more constraints, as in the following >> example. The “: Equatable” allows you to constrain T to any type that >> conforms to Equatable, or is valid with the double equals operator. >> >> func firstAndLastAreEqual<T : Equatable> >> (someArray: Array<T>) -> Bool { >> let first = someArray[0] >> let last = someArray[someArray.count - 1] >> return first == last >> } >> You can also use generics for either functions or type declarations. Type >> information is available at runtime, which is helpful. The compiler can >> optimize by creating specific versions for each type that’s being used (like >> C++ templates), but it can also fall back to the generic implementation. >> >> Extended Example (33:56) >> >> In the extended example, the goal was to create a function that was typesafe >> and could handle every case that involved the following types: Array, >> Dictionary, SquareMatrix, TreeNode. The function was to take a collection of >> one of the above types, take an array, and append the items in that >> collection to the array. >> >> A protocol was defined to specify that a type can give back all of the >> elements inside of it. You have containers that can implement “AllElements”. >> On a generic level, you might need to know the type of the elements inside >> the collection, and so a wildcard is called “ElementType”. And so, you >> specify the element type when you implement the function itself. >> >> protocol AllElements { >> typealias ElementType >> // Return an array containing all the objects >> // in the collection >> func allElements() -> Array<ElementType> >> } >> Another thing you can use is the NilLiteral protocol, the point of which is >> to take nil and turn it into something equivalent to nil in that type. For >> an int, it would return 0, or maybe for a string, it would return “”. In the >> following example, you would want it to return something of type self. >> >> protocol NilLiteralConvertible { >> class func convertFromNilLiteral() -> Self >> } >> Extensions then add methods, computed properties, and protocol conformance >> to existing types. Array and SquareMatrix are both fairly straightforward - >> you just return the arrays themselves. For the Dictionary, you iterate >> through all the elements, create a buffer, and return it with the elements >> inside. Finally, for the tree, you go through the tree in a recursive >> traversal and again add the elements to a buffer. >> >> Put together, the final function appendToArray calls AllElements and gives >> “a”, which is an array with all the elements on the source. Then each of >> those elements is just added to the array in “dest”. This works because the >> generic argument “T” has to implement AllElements, and U has been >> constrained to the same type as T. The where clause is included in case you >> want to do more than have this type implement one protocol. Before the >> where, you declare type arguments, which can conform to either one or none >> protocols. If you want T to conform to 2+ protocols, add a “where” clause to >> constrain. You can then constrain any free type arguments you declared >> earlier and any associated types associated with the type arguments via >> protocols (e.g. T.SomeType). >> >> func appendToArray >> <T: AllElements, U where U == T.ElementType> >> (source: T, inout dest: Array<U>) { >> >> let a = source.allElements() >> for element in a { >> dest.append(element) >> } >> } >> >> var buffer = ["a", "b", "c"] >> appendToArray([1: "foo", 2: "bar"], &buffer) >> Now you’ve created five methods for this one process. In actuality, you >> would have your containers implement Sequence and use a for-in loop to go >> through all the elements. This requires knowledge of Generators, >> EnumerateGenerators, and other material. >> >> Q&A (46:05) >> >> Q: In the extension example, are we extending all arrays of anything? >> Austin: Yes, which is why this is a bad idea in practice. You can’t actually >> say that you only want arrays with JSON type objects to also implement JSON >> array, which is needed to ensure that you have valid JSON. >> >> Q: Is the type T built-in? Where does it come from? >> Austin: T is actually coming from the declaration of array. If you >> command-click an array in XCode, the declaration of the array shows that it >> declares a generic argument T that has some constraints. >> >> Q: Is there any kind of trace for generics and the way it works? Is it >> traceable to an existing language or is it brand-new? >> Austin: I don’t know the answer, but I’m sure there are precedents. Generics >> in Swift kind of de-emphasize object oriented programming because they’re >> built more around protocols than around class hierarchies. You might get a >> closer procedent if you looked at Haskell. >> >> Q: What is the exclamation point used for? >> Austin: The exclamation mark is for optionals. Everything in Swift is >> non-nilable by default, so if you want to set something to nil, it must be >> declared as an optional. The question mark after the type signifies this. >> Then, the exclamation mark, or bang, takes the value out of the optional so >> you can use it. >> >> Q: Is there something like value template parameters in Swift? Or should we >> just type in, type template? >> Austin: I don’t think so, I don’t think Swift generics are as powerful. >> >> Q: Can you explain let? It seemed like it would sometimes check the case and >> othertimes it would set it to the constant. >> Austin: A let pattern kind of matches everything, but also takes a value and >> puts it in the constant for later use. When we use “as”, it both checks the >> type and also puts it in the constant. >> >> Sign up to be notified of future videos >> >> We won’t email you for any other reason, ever. >> >> >> -- >> Recebeu esta mensagem porque subscreveu ao grupo "Mailing List da Comunidade >> Portuguesa de Rich Internet Applications - www.riapt.org" do Grupos do >> Google. >> Para anular a subscrição deste grupo e parar de receber emails do mesmo, >> envie um email para [email protected]. >> Para publicar uma mensagem neste grupo, envie um email para >> [email protected]. >> Visite este grupo em http://groups.google.com/group/riapt. >> Para mais opções, visite https://groups.google.com/d/optout. > > -- > Recebeu esta mensagem porque subscreveu ao grupo "Mailing List da Comunidade > Portuguesa de Rich Internet Applications - www.riapt.org" do Grupos do Google. > Para anular a subscrição deste grupo e parar de receber emails do mesmo, > envie um email para [email protected]. > Para publicar uma mensagem neste grupo, envie um email para > [email protected]. > Visite este grupo em http://groups.google.com/group/riapt. > Para mais opções, visite https://groups.google.com/d/optout. -- Recebeu esta mensagem porque está inscrito no grupo "Mailing List da Comunidade Portuguesa de Rich Internet Applications - www.riapt.org" dos Grupos do Google. Para anular a subscrição deste grupo e parar de receber emails do mesmo, envie um email para [email protected]. Para publicar uma mensagem neste grupo, envie um e-mail para [email protected]. Visite este grupo em http://groups.google.com/group/riapt. Para mais opções, consulte https://groups.google.com/d/optout.
