[Swift 1] Day 6-7 - App Challenge - Word Magnets


#45

Yeah, I checked there, for some reason mine is not there…


#46

Perhaps it disappears after a while. I grab the file directly after doing a build and run, with the simulator and XCode both still running.


#47

I figured it out :slight_smile: Thanks!


#48

Hi. I’m really impressed with Your app, it was an inspiration for me to develop my own. I’ve managed to snap labels in one line, but I don’t have any idea how did You managed to slide them over the x axis. Can you pass me some hints?
Regards


#49

You’re going to have to do some math calculations based on the size of the label and it’s position (center). You’ll need to use if/else statements to determine when you’re near/in-range of snapping.

Use the labels bounds property to get size and position or the center property.

label.center.x
label.center.y
label.bounds.origin.x (top left)
label.bounds.origin.y (top left)
label.bounds.size.width
label.bounds.size.height

Small Goals

Break it down into a set of steps that you can accomplish. Start small and work up to the fully working piece of code. I generally do this iteratively and it helps to start with something that works and you build upon it.

Day 17 will include more detail about working with views in code and moving them.

Pseudo-code

  1. Keep a list of all the labels on the line
  2. if the dragged label’s x coordinate is less than a line snapped label (array), move the label and any label after it (loop through rest of array) to the right by an amount (dragged label’s width + margin (0 - 10 pixels))
  3. Animate the transitions with UIView.animate... methods.
  4. Only do this when near the line’s y coordinate (~10-20 points up and down from line as a threshold)

#50

great! thanks for hints


#51

Hi Paul,
I have been trying to do this but I am lost. Any tips?


#52

Have you done anything ? If so , why not upload to GitHub.com, so we can take a look.
Also, did you you try to look at the code attached to the video - https://www.filepicker.io/api/file/xohBMdy8SCmptBGcmjXT ?


#53

Any insight into what part is holding you up?

Did you sketch out any ideas for what you wanted to do?

Did you watch the Day 5 videos?


#55

Post a screenshot too or a video so I can see what you’re talking about as a final product.


#56

I have removed the code because it was changed heavily.
I have altered the code now and it works.

I have a new question: I have a function that removes last item from an array but I cannot stop it from removing all the subview. How can I just remove the last label added?

// Remove word from array and remove from screen

func removeLabel(){
var label = UILabel()

    let removed = wordArray.removeLast()
    println(wordArray)

for v in view.subviews{
    if v is UILabel{
    v.removeFromSuperview()

}

}
}


#57

Many ways you can do it I guess. I think what I would do is create a variable lets say: var lastAddedLabel: UILabel!
And then store a reference of each label in it.
So at the end of your create Label func you’ll add something like:

lastAddedLabel = myLabel

Then lastAddedLabel will always contain your last added label :wink:


#58

I have done that and it works thanks but then how can I remove each next label from the array until they are all gone? I managed to make a loop to stop the removal when the array is empty so not to crash.


#59

Look here: https://developer.apple.com/library/ios/documentation/General/Reference/SwiftStandardLibraryReference/Array.html

var array = [1, 2, 3]
let removed = array.removeLast()
// array is [1, 2]
// removed is 3

Then refresh all labels.


#60

I have done it as two buttons one that removes a label and one that clears the screen but I can’t find how to refresh the labels anywhere. Sorry to be a pain.


#61

There are many ways to approach this project. I don’t know how you went about this, as that would change the methods as well. You can basically change the Array of labels and then refresh ( meaning delete all and add all from the screen )
If you have 2 functions: one to create all labels, based on the Array and another one to clear the screen - refresh would mean a third function that inside just calls the other 2 -> first CLEAR, then recreate.
Another approach ( that I prefer ) is to have the option of selecting a label and deleting the selected.
So create a variable to store a saelected label.
And then every time you have a tap or any gesture that involves a label store the label that was touched, dragged or whatever in that variable. ( might add a shadow, glow etc to the selected label ) When you hit delete it will delete the selected label.
So basically you can do something like:

var selectedLabel: UILabel!

and then do within each of the gesture functions:
for example: selectedLabel = tappedLabel

Then whenever you hit delete it will just delete that lastly selected label.
Cheers! :slight_smile:


#62

@sashaz

You’re best bet is to store a property inside the class to keep track of all labels added. Every time you add one, you add it to your list and then you can do what ever you want to remove items using this list.

Here’s a little code sample that should help you.

var labelArray: [UILabel]!

override func viewDidLoad() {
    super.viewDidLoad()
    var labelArray = [UILabel]()  // create the array        
}

@IBAction func addLabel(sender: AnyObject) {
    var label = createLabel("Some text that the user typed...")
    
    // add to array
    labelArray.append(label)  // adds label to the end of the list
    
    // add to view
    view.addSubview(label)
}

func createLabel(text: String) -> UILabel {
    var label = UILabel()
    label.text = text
    label.sizeToFit()

    return label
}

func removeLastLabel() {
    
    // Get the last element (if it exists)
    if let lastLabel = labelArray.last {
     
        // remove from superview
        lastLabel.removeFromSuperview()
        
        // remove from the array (book keeping)
        labelArray.removeLast()
    }
}

#63

Hi I have finished this app for now, I will upload it to the app store as its good to practice that part also.

So I tried to add the code for removing each label from the array as Paul advised but I couldn’t get it to work, it either had an error or returned nil. I tried the method of refreshing the labels after a clear but it due to the random location part it moved them all.
Other things I tried but couldn’t do, add shadow, make it so you can vary the text size, randomise the label colours so it would be very colourful ( I will add that later when I see how), share function (couldn’t get it to work).

What I did learn:
Labels and arrays
adding animation
some logic
calling other functions in different parts of the code.
much better at auto layout
started a GithubGist page to save handy bits of code.

Looking forward to the next course.

App Video demo


GithubGist file of the code


#64

Very cute :slight_smile:
Just one note, it seems that you can’t really see what you are typing, which
could be really annoying from a user side of things :wink:

You can make your whole view move up with the keyboard and then go back down as you dismiss it.
You can look up something like that:


#65

Looks awesome @sashaz !

Can you explain your problem with removing labels? Or send me the .zip of the project file at PaulSolt@iPhoneDev.tv

I’d like to sort out what the difficulty is.