[Swift 1] Day 1 - Code Exercise Solutions


#43

There is a scale factor that is multiplied by your point resolution. There’s a difference between “logical points” and pixels. This is because of the retina screens and higher resolutions.

println("view bounds: \(self.view.bounds)")
println("scale: \(UIScreen.mainScreen().scale)")

output

iPhone 6
view bounds: (0.0,0.0,375.0,667.0) // (x, y, width, height)
scale: 2.0

iPhone 6 Plus
view bounds: (0.0,0.0,414.0,736.0)
scale: 3.0

375 * 2 = 750 = width
667 * 2 = 1334 = height

414 * 3 = 1,242 = width
736 * 3 = 2,208 = height

The iPhone 6 Plus has an exception, because there is a scale factor that scales down the output to 1920x1080 pixels.


#44

Hi,

my solution for Code Exercise 1/2:

    myFirstLabel.center = CGPoint(x: UIScreen.mainScreen().bounds.width - (myFirstLabel.bounds.width / 2), y: 100)
    view.addSubview(myFirstLabel)
    
    UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.0, options: nil, animations: {
        
        self.myFirstLabel.center = CGPoint(x: (self.myFirstLabel.bounds.width / 2), y:100)
        
        }, completion: nil)

and for the second label:

    iPhoneLabel.center = CGPoint(x: UIScreen.mainScreen().bounds.width - (iPhoneLabel.bounds.width / 2), y: 150)
    view.addSubview(iPhoneLabel)
    
    iPhoneLabel.alpha = 0 // Hidden = 0
    
    UIView.animateWithDuration(3.0, delay: 0.5, usingSpringWithDamping: 0.1, initialSpringVelocity: 0.5, options: nil, animations: {
        
        self.iPhoneLabel.center = CGPoint(x: (self.iPhoneLabel.bounds.width / 2), y:150)
        self.iPhoneLabel.alpha = 1 // Visable = 1
        }, completion: nil)

thx,
Joachim


#45

Here’s my code exercise for Day 1. When looking at the basic animation I thought it would be more interesting if the first three words came in individually, then followed by a bouncier “iPhone App” label.

// 1. Declare ivars
var myLabel: UILabel!
var firstLabel: UILabel!
var labelLabel: UILabel!
var iPhoneLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    
    // 2. Create the labels
    myLabel = UILabel()
    firstLabel = UILabel()
    labelLabel = UILabel()
    iPhoneLabel = UILabel()
    
    addLabels()
    
    var tapGesture = UITapGestureRecognizer(target: self, action: Selector ("handleTapGesture:"))
    view.addGestureRecognizer(tapGesture)
}

func handleTapGesture(tapGesture: UITapGestureRecognizer) {
    println("tap")
    
    addLabels()
}

func addLabels() {
    
    myLabel.text = "My"
    myLabel.font = UIFont.systemFontOfSize(36)
    myLabel.sizeToFit()
    myLabel.center = CGPoint(x: 175, y: 40)
    view.addSubview(myLabel)
    
    UIView.animateWithDuration(0.5, delay: 0.5, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.0, options: nil, animations: {
        
        self.myLabel.center = CGPoint(x: 110, y: 40 + 200)
        
        }, completion: nil)
    
    firstLabel.text = "First"
    firstLabel.font = UIFont.systemFontOfSize(36)
    firstLabel.sizeToFit()
    firstLabel.center = CGPoint(x: 175, y: 40)
    view.addSubview(firstLabel)
    
    UIView.animateWithDuration(0.5, delay: 0.7, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.0, options: nil, animations: {
        
        self.firstLabel.center = CGPoint(x: 175, y: 40 + 200)
        
        }, completion: nil)
    
    labelLabel.text = "Label"
    labelLabel.font = UIFont.systemFontOfSize(36)
    labelLabel.sizeToFit()
    labelLabel.center = CGPoint(x: 175, y: 40)
    view.addSubview(labelLabel)
    
    UIView.animateWithDuration(0.5, delay: 1.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.0, options: nil, animations: {
        
        self.labelLabel.center = CGPoint(x: 260, y: 40 + 200)
        
        }, completion: nil)
    
    iPhoneLabel.text = "iPhone app"
    iPhoneLabel.font = UIFont.boldSystemFontOfSize(54)
    iPhoneLabel.sizeToFit()
    iPhoneLabel.center = CGPoint(x: 190, y: 90)
    view.addSubview(iPhoneLabel)
    
    iPhoneLabel.alpha = 0 // Hidden = 0
    
    UIView.animateWithDuration(2.0, delay: 1.9, usingSpringWithDamping: 0.2, initialSpringVelocity: 0.0, options: nil, animations: {
        
        self.iPhoneLabel.center = CGPoint(x: 190, y: 90 + 190)
        self.iPhoneLabel.alpha = 1 // Visible = 1
        
        }, completion: nil)


    
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

The questions were answered by everyone else on the thread.

I have a ton of notes after this first lesson but one of the questions I had was about the alpha property – can elements have a value between 0 (invisible) and 1 (visible), or is it just a toggle on or off? I found the answer here: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/index.html#//apple_ref/occ/instp/UIView/alpha – the value can be anything between 0.0 and 1.0

I just want to thank you, Paul, for teaching us code right from the start. For me at least it helps me get over the terror of confronting huge quantities of a language I don’t yet speak or understand. I tried another series of tutorials on Xcode and it started with the easy, drag and drop stuff, but when it added code I was floored. This is the right way round to go, at least for me.


#46

Hey, Paul.

I just started Day 1’s lessons and bumped into a problem that I believe is a crash. It started out as a breakpoint 1.1, so I deleted it as other devs suggested on Stack Overflow. After doing that, the app shows the spring animation, but tapping it causes it to crash.

Please take a look at my code and let me know what the problem is and how can I fix it. Thank you!

// 1. Declare ivars
var myFirstLabel: UILabel!
var iPhoneLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    
    // 2. Create the labels
    myFirstLabel = UILabel()
    iPhoneLabel = UILabel ()
    
    addlabels()
    
var tapGesture = UITapGestureRecognizer(target: self, action:Selector("handleTapGesture:"))
    view.addGestureRecognizer(tapGesture)
    
    func handleTapGesture(tapGesture: UITapGestureRecognizer) {
        println("tap")
        
        addlabels()
    
}
}

    func addlabels (){

        myFirstLabel.text = "Welcome to"
        myFirstLabel.font = UIFont.systemFontOfSize(40)
        myFirstLabel.sizeToFit()
        myFirstLabel.center = CGPoint(x: 195, y: 70)
        
        view.addSubview(myFirstLabel)
        
        UIView.animateWithDuration(0.5, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.0, options: nil, animations: {
            
            self.myFirstLabel.center = CGPoint (x: 190, y: 70+200)
            
            }, completion: nil)
        
        iPhoneLabel.text = "Decide"
        iPhoneLabel.font = UIFont.boldSystemFontOfSize(48)
        iPhoneLabel.sizeToFit()
        iPhoneLabel.center = CGPoint (x: 197, y: 120)
        
        view.addSubview(iPhoneLabel)
        
        iPhoneLabel.alpha = 0
        
        UIView.animateWithDuration(2.0, delay: 0.5, usingSpringWithDamping: 0.2, initialSpringVelocity: 0.0, options: nil, animations: {
            
            self.iPhoneLabel.center = CGPoint (x: 197, y: 120+197)
            self.iPhoneLabel.alpha = 1
            }, completion: nil)
    }

#47

@stefgonzaga

This one is tricky, you’ve declared the func handleTapGesture inside the viewDidLoad method. It needs to be outside the { }. Otherwise it’s hidden and you get the following error:

2015-01-15 18:34:26.541 StefApp[3915:808598] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[StefApp.ViewController handleTapGesture:]: unrecognized selector sent to instance 0x13660d8c0'

If you change it, you see it work.

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    
    // 2. Create the labels
    myFirstLabel = UILabel()
    iPhoneLabel = UILabel ()
    
    addlabels()
    
    var tapGesture = UITapGestureRecognizer(target: self, action:Selector("handleTapGesture:"))
    view.addGestureRecognizer(tapGesture)
    
}
func handleTapGesture(tapGesture: UITapGestureRecognizer) {
    println("tap")
    
    addlabels()
    
}

#48

Looks great! Nice work Nina.

I would move the 3 labels offscreen initially (use a negative y coordinate i.e. -100).

We’ll do a mix of both code and UI, so you get an understanding of how it works, and where the code goes to work with the UI.


#49

It worked! Whew. Thank you so much, Paul. I can finally move on to Day 2. :smile:


#50

#51

Code Exercise :

  1. just change, on addLabels : myFirstLabel.center = CGPoint(x: 500, y: 40), and on animations blocks remove “+ 200”
  2. change usingSpringWithDamping value between 0 and 1

Questions

  1. top left corner
  2. diferent size, i found this

#52

I got this following code:

func addLabels() {
        myFirstLabel.text = "My First"
        myFirstLabel.font = UIFont.systemFontOfSize(36)
        myFirstLabel.sizeToFit()
        myFirstLabel.center = CGPoint(x: 100, y: 40)
        view.addSubview(myFirstLabel)
        
        myFirstLabel.alpha = 0 // Hidden = 0
        
        UIView.animateWithDuration(8.0, delay: 0.0, usingSpringWithDamping: 0.6, initialSpringVelocity: 2.0, options: nil, animations: {
            
            self.myFirstLabel.center = CGPoint(x: 100, y: 40 + 250)
            self.myFirstLabel.alpha = 1 // Visible = 1
            
            }, completion: nil)
        
        iPhoneLabel.text = "iPhone App"
        iPhoneLabel.font = UIFont.boldSystemFontOfSize(48)
        iPhoneLabel.sizeToFit()
        iPhoneLabel.center = CGPoint(x: 400, y:340)
        view.addSubview(iPhoneLabel)
        
        iPhoneLabel.alpha = 0 // Hidden = 0
        
        UIView.animateWithDuration(8.0, delay: 0.5, usingSpringWithDamping: 0.6, initialSpringVelocity: 2.0, options: nil,  animations: {
        
            self.iPhoneLabel.center = CGPoint(x: 200, y: 340)
            self.iPhoneLabel.alpha = 1 // Visible = 1
            
        }, completion: nil)
    }

Question:


#53

Hi there

I was able to add another label animating with a fade-in in centre. However, in horizontal view on iPhone 6 the animation is totally messed up. I think it must be related to the auto layout…

Here are some links with the answers to the questions:

Question 1:
http://learnios.appdev.vn/user-interface-part-3-view-frames-and-bounds/
Question 2:

// 1. Declare create ivars
var myFirstLabel: UILabel!
var animLabel: UILabel!
var everLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    // 2. Create the labels
    
    myFirstLabel = UILabel()
    animLabel = UILabel()
    everLabel = UILabel()
    addLabels()
    
    var tapGesture = UITapGestureRecognizer(target: self, action: Selector("handleTapGesture:"))
    view.addGestureRecognizer(tapGesture)

}

func handleTapGesture(tapGesture: UITapGestureRecognizer) {
    addLabels()
}

func addLabels() {

myFirstLabel.text = "My first"
myFirstLabel.font = UIFont.systemFontOfSize(36)
myFirstLabel.sizeToFit()
myFirstLabel.center = CGPoint(x: 100, y: 150)
view.addSubview(myFirstLabel)
myFirstLabel.alpha = 0

UIView.animateWithDuration(0.5, delay: 0.2, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.0, options: nil, animations:
    {

self.myFirstLabel.center = CGPoint(x: 0 + 200, y: 150)
self.myFirstLabel.alpha = 1


}, completion: nil)
    
    
animLabel.text = "ANIMATION"
animLabel.font = UIFont.boldSystemFontOfSize(48)
animLabel.sizeToFit()
animLabel.center = CGPoint(x: 400, y: 200)
view.addSubview(animLabel)
animLabel.alpha = 0

UIView.animateWithDuration(1.0, delay: 0.3, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.0, options: nil, animations: {
        
self.animLabel.center = CGPoint(x: 400 - 200, y: 200)
self.animLabel.alpha = 1

}, completion: nil)
    

everLabel.text = "EVER"
everLabel.font = UIFont.systemFontOfSize(60)
everLabel.sizeToFit()
everLabel.center = CGPoint(x: 200, y: 400)
view.addSubview(everLabel)
everLabel.alpha = 0
    
    UIView.animateWithDuration(2.0, delay: 1.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.0, options: nil, animations: {
        self.everLabel.alpha = 0.5

        
    }, completion: nil)
    
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

#54

Check these two:

https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/WindowsandViews/WindowsandViews.html

http://www.idev101.com/code/User_Interface/view_frames_bounds.html


#55

@lucasrezende It’s actually points for the size, not pixels.

When we work with retina screens we talk about it in terms of points. The screen has a scaleFactor, which makes it retina. So a iPhone 6 might have 750x1334 points, but it has a scale of 2 – so it really has 1500x2668 pixels.

The iPhone 6+ has a 3x scale factor, so you take it’s point and multiply by 3 to get final pixel size. But there’s some additional black magic, since Apple then down samples (reduces) to 1920x1080 pixels – the native resolution of the iPhone 6+.

2x and 3x pixel density is why it’s so crisp on iOS.


#56

@Alta Auto Layout is a bit complex – don’t worry about rotations just yet.

First focus on getting the apps working in portrait. Further into the course you’ll get more exposure for how to work with Auto Layout.

I’m planning to do a mini-course on it, but I have’t had time yet.


#57

Great job! I did the same thing and it worked for me re: changing the X axis!


#58

Hi
How can I repeat the same animation for 10 times?
Thanks


#59

This worked :smile:

UIView .setAnimationRepeatCount(10)


#60

I share my code but doesn’t seems to work quite well, what I tried to do is that the label appear then on tap disappear, perhaps with a toggle function but i don´t know.

var lbl1 = UILabel()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    
    agregaLabel("")
    
    var gestoTap = UITapGestureRecognizer(target: self, action: Selector("animaEnTap:"))
    view.addGestureRecognizer(gestoTap)
    
}

func animaEnTap(tapGesture: UITapGestureRecognizer){
    agregaLabel("tap")
}

func agregaLabel(seccion: String){
    lbl1.text = "Ola ke ace?"
    lbl1.font = UIFont.boldSystemFontOfSize(40)
    lbl1.sizeToFit()
    if(seccion != "tap"){
        lbl1.center = CGPoint(x: -200, y: 300)
        UIView.animateWithDuration(0.9, delay: 0.2, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.2, options: nil, animations: {
        self.lbl1.center = CGPoint(x: 260, y: 300)
    }, completion: nil)
    }else{
        lbl1.center = CGPoint(x: 260, y: 300)
        UIView.animateWithDuration(0.9, delay: 0.3, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.4, options: nil, animations: {
            self.lbl1.center = CGPoint(x: -200, y: 300)
        }, completion: nil)
    }
    view.addSubview(lbl1)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

#61

Omg, so confusing with the spanish names… :smile:
Probably best to stick with EN in the future, so it will be easier for others to help you out.

It seems to me that you are always having : seccion = tap, so not sure why you are checking ( != tap )
I mean, you could pass a different value, but you are not as far as I can see.

Easiest way would be to add a flag right after 'var lbl1 = UILabel()'
Something like:

var haveYouTapped: Bool = false

Then you can do:

if haveYouTapped == false {
lbl1 = "blabla"
haveYouTapped = true
} else {
lbl1 = ""
haveYouTapped = false
}

Of course there are many ways to do it :smile:
Personally I prefer flags :smiley: ( You could just use and INT flat , var tapped: Int = 0 , or = 1 …)

Gluck :slight_smile:


#62

Answers

  1. Top left corner os 0,0
  2. 375 x 667 (points) or 730 x 1334 (pixels)

Code
The only way I could get the “iPhone App” text to slide in from the left was by putting a very large negative number into this equation:

iPhoneLabel.center = CGPoint(x: -4000, y: 90)

It doesn’t make sense to me why this negative number (line 85) should have to be so large. The screen size is only 375 pts wide plus the width of the text frame. Please advise if I have done this correctly.

If I have done it correctly, please advise why the negative number has to be so large.

If I haven’t done it correctly, please advise how to do so.

//
// ViewController.swift
// Bouncing Labels
//
// Created by Brian Armstrong on 2015-05-05.
// Copyright © 2015 Brian Armstrong. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

// 1. Declare ivars
var myFirstLabel: UILabel!
var iPhoneLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    
    // 2. Create the labels
    myFirstLabel = UILabel()
    iPhoneLabel = UILabel()
    
    addLabels()
    
    // Add gestures for tapping
    var tapGesture = UITapGestureRecognizer(target: self, action: Selector("handleTapGesture:"))
    view.addGestureRecognizer(tapGesture)
    
}
    // Print gesture
func handleTapGesture(tapGesture: UITapGestureRecognizer) {
    println("tap")
    
    addLabels()
}

func addLabels() {
    
    // Create label "iPhone App"
    // Specify default font size
    // Adjusts font size to fit string into label's bounding rectangle
    
    myFirstLabel.text = "My First"
    myFirstLabel.font = UIFont.systemFontOfSize(36)
    myFirstLabel.sizeToFit()
    
    
    // CGPoint = A structure that contains a point in a two-dimensional coordinate system.
    // x = label center will become visible 100 points from left side of screen
    // y = label center will become visible 50 points down from top of screen

    myFirstLabel.center = CGPoint(x: 100, y: 50)
    view.addSubview(myFirstLabel)
    
    // UIView.animateWithDuration = Animate changes to one or more views using the specified duration.
    // 2.5 = Total animation length
    // delay: 0.0 = Delay before animation begins
    // usingSpringWithDamping: 0.35 = How quickly the animation runs
    // initialSpringVelocity: 0.3 = Rate of change between initial and final positions
    
    UIView.animateWithDuration(2.5, delay: 0.0, usingSpringWithDamping: 0.35, initialSpringVelocity: 0.3, options: nil, animations: {
        
        // CGPoint = A structure that contains a point in a two-dimensional coordinate system.
        // x = label will end up centered 100 points from left side of screen
        // y = label will end up centered 40 + 200 points down from top of screen
        
        self.myFirstLabel.center = CGPoint(x: 100, y:40 + 200)
        
        }, completion: nil)
    
    // Create label "iPhone App"
    // Specify font, bold, and size
    // Adjusts font size to fit string into label's bounding rectangle
    
    iPhoneLabel.text = "iPhone App"
    iPhoneLabel.font = UIFont.boldSystemFontOfSize(48)
    iPhoneLabel.sizeToFit()
    
    // CGPoint = A structure that contains a point in a two-dimensional coordinate system.
    // x = label center will become visible -4000 points from left side of screen
    // y = label center will become visible 90 points down from top of screen
    
    iPhoneLabel.center = CGPoint(x: -4000, y: 90)
    view.addSubview(iPhoneLabel)
    
    iPhoneLabel.alpha = 0 // Hidden = 0
    
    // UIView.animateWithDuration = Animate changes to one or more views using the specified duration.
    // 2.0 = Total animation length
    // delay: 0.5 = Delay before animation begins
    // usingSpringWithDamping: 0.8 = How quickly the animation runs
    // initialSpringVelocity: 0.0 = Rate of change between initial and final positions
    
    UIView.animateWithDuration(2.0, delay: 0.5, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.0, options: nil, animations: {
        
        // CGPoint = A structure that contains a point in a two-dimensional coordinate system.
        // x = label will end up centered 200 points from left side of screen
        // y = label will end up centered 90 + 200 points down from top of screen
        
        self.iPhoneLabel.center = CGPoint(x: 200, y: 90 + 200)
        
        self.iPhoneLabel.alpha = 1 // Visible = 1
        
        }, completion: nil)
}

// Dispose of any resources that can be recreated.
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}

}