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 = 10switch 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 = 10switch 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 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.
