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


happy to help.
That one was more obscure but interesting too :



The swift programming


So yeah, this challenge was a bit tough for me too. Mainly because of the lack of understanding of the UITextField and delegates. Even harder when I tried to just code it, instead of using the GUI. I kinda made it work with ripping portions of code here and there, I did 3 different apps, but I am still foggy on some things. In addition I can’t get the screen to look right on every device or on landscape. I just wish you could say - I have this View and it’s 30% of the total Height and 100% of all the width ( like web design ).

Don’t have enough time to make this presentable, but hopefully I might be able to do it next weekend and post something…


Here are two screenshots of my attempt. Features include:

  • add new word
  • drag word to trash bin (top right) to remove
  • background image change when rotating between landscape and portrait
  • when rotating, only words that fall off the screen are placed in new random positions

I really liked @Paradisiak’s sharing feature (amongst all the other cool features). I would like to figure out how to do that as well. It would also be great if the user could choose different background images, including from their camera roll.

I set view.backgroundColor = UIColor(patternImage: UIImage(named: “…”)) for the background image. I don’t think this is the best solution. Did everyone else use an UIImageView with auto layout to fill the screen?


Here is my share function :

func menuShare(sender: UIButton) {
    let myPoem:UIImage = getPoemScreenShot()
    let activityViewController : UIActivityViewController = UIActivityViewController(activityItems: [myPoem], applicationActivities: nil)
    let presentationController = activityViewController.popoverPresentationController
    presentationController?.sourceView = sender
    presentationController?.sourceRect = CGRect(origin: CGPointZero, size: CGSize(width: sender.frame.width, height: sender.frame.height))
    self.presentViewController(activityViewController, animated: true, completion: nil)

First you can create an UIActivityViewController with in the activityItems parameter what you want to share (here its a UIImage stored in the var myPoem).
then you prepare the popover that will display the sharing options with the popoverPresentationController property of your UIActivity controller.
To work on ipad too you need to set the source view and the source Rect (it is the view from witch the popover will be displayed).
and finally you present the the result with presentViewController and your UIActivityController as parameter.
Nothing else to do, the Apple API perform all the magic from here :slight_smile:

Word Magnet examples

Hi Bennie,
I used the UIImage View (drag n’ drop with the interface) and it’s kind of buggy. I tried your code on day 8 exercice and it’s much easier. I guess the best solution would be to select the background image based on resolution or orientation or to stretch it to fill the screen using code instead of the interface. How did you manage to change the image on rotation? This is a great idea!


I am SO excited to post my app!

I called it ABC Magnets

Code: https://www.dropbox.com/s/znuvddi51rydqhn/AlphabetMagnets.zip?dl=0

What it does:
Move the alphabets across the screen. ( I created images instead of array of words)

override func viewDidLoad() {
    // Do any additional setup after loading the view, typically from a nib.
    var alphabetArray : [UIImage] = [
            UIImage(named: "Alphabet_A.png"),
            UIImage(named: "Alphabet_B.png"),
            UIImage(named: "Alphabet_C.png"),
            UIImage(named: "Alphabet_D.png"),
            UIImage(named: "Alphabet_E.png"),
            UIImage(named: "Alphabet_F.png"),
            UIImage(named: "Alphabet_G.png"),
            UIImage(named: "Alphabet_H.png"),
            UIImage(named: "Alphabet_I.png"),
            UIImage(named: "Alphabet_J.png"),
            UIImage(named: "Alphabet_K.png"),
            UIImage(named: "Alphabet_L.png"),
            UIImage(named: "Alphabet_M.png"),
            UIImage(named: "Alphabet_N.png"),
            UIImage(named: "Alphabet_O.png"),
            UIImage(named: "Alphabet_P.png"),
            UIImage(named: "Alphabet_Q.png"),
            UIImage(named: "Alphabet_R.png"),
            UIImage(named: "Alphabet_S.png"),
            UIImage(named: "Alphabet_T.png"),
            UIImage(named: "Alphabet_U.png"),
            UIImage(named: "Alphabet_V.png"),
            UIImage(named: "Alphabet_W.png"),
            UIImage(named: "Alphabet_X.png"),
            UIImage(named: "Alphabet_Y.png"),
            UIImage(named: "Alphabet_Z.png")] //adds alphabet pictures into array
    //for each alphabet in the array
    for alphabet in alphabetArray{
        var letterImage = UIImageView(frame: CGRectMake(150, 200, 70, 45)) //  create a imageview with location x,y and width,height
        letterImage.image = alphabet //store the alphabet image into the imageview
        letterImage.contentMode = UIViewContentMode.ScaleAspectFit //make the image fit in the imageview containter
        var x = CGFloat(arc4random_uniform(300)) //random x from 0 - 300
        var y = CGFloat(arc4random_uniform(425)) //random y from 0 - 425
        letterImage.center = CGPoint(x: x, y: y) //center the image view with the random x and y
        view.addSubview(letterImage) //add the imageview with alphabet to the screen
        var panGesture = UIPanGestureRecognizer(target: self, action: Selector("handlePanGesture:")) //create variable of type UIPanGestureRecognizer with func handlePanGesture
        var rotateGesture = UIRotationGestureRecognizer(target: self, action: Selector("handleRotateGesture:"))
        letterImage.addGestureRecognizer(panGesture) //add action to the image
        letterImage.userInteractionEnabled = true //make image interationable
        existingAlphabets.append(letterImage) //add the imageview and image into an array

Throw them with velocity
Shake the phone and they will reset to a new position
Rotate them using gestures
Added app icons

Add a menu to add more than 1 letter, or let the user pick the letters
Make the alphabets bounce off each other so that all alphabets are on the same plane
Add a wiggle when you pick one up
Add a sound when you drop it
Add a button to let the user upload a background image
Add a button to let the user save the screen (to create backgrounds or something)

@PaulSolt are we going to learn some of these things? Ill just wait (:

I found some of it with google and tweaked it for my needs, I tried to comment a lot of the code to make since



@Paradisiak NICE!

Can you share some resources you used for the shadowing and snapshot feature you used?

I wanted to add some of that to my magnet app but couldn’t figure it out



Thank you.
I’ve got 2 functions for the shadow. The plainshadow is used when the label is on the board and the hover shadow when it’s moving :

func applyPlainShadow(label:UILabel) {
    var layer = label.layer
    label.layer.shadowOffset = CGSize(width: 3, height: 3)
    label.layer.shadowOpacity = 0.7
    label.layer.shadowRadius = 2

func applyHoverShadow(label:UILabel) {
    var layer = label.layer
    label.layer.shadowOffset = CGSize(width: 10, height: 20)
    label.layer.shadowOpacity = 0.3
    label.layer.shadowRadius = 6

I set the hover shadow in the .Began statement of the pan gesture and i set it back to plain shadow at the .Ended statement of the pan gesture.

Here is a very good ressource to understand shadows :

Mookid on shadows

Word Magnet examples

Thank you Eloise. The problem I had with setting the view.backgroundColor to an UIImage was that I could not scale and pan the image in code. I ended up sizing the image correctly before importing into Xcode.

I used the viewWillTransitionToSize method to determine whether the screen has been rotated. In addition to using a different image, I also shifted labels that might have fallen off the screen. Here is my code:

override func viewWillTransitionToSize(size: CGSize,
                withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    // Change background image when rotated
    if size.height > size.width {
        view.backgroundColor = UIColor(patternImage:
                                UIImage(named: "vdm-75-medium.jpg"))
    else {
        view.backgroundColor = UIColor(patternImage:
                                UIImage(named: "vdm-56-medium.jpg"))
    // Place labels that have fallen off screen after rotation in new random positions
    let viewHeight = self.view.bounds.height
    let viewWidth = self.view.bounds.width
    for view in self.view.subviews as [UIView] {
        if let lbl = view as? UILabel {

            if (lbl.center.y > viewWidth) || (lbl.center.x > viewHeight) {
                var y = CGFloat(arc4random_uniform(UInt32(viewWidth) - 100) + 50)
                var x = CGFloat(arc4random_uniform(UInt32(viewHeight) - 66) + 66)
                lbl.center = CGPoint(x: x, y: y)


@Bennie or @Eloise what size do you all use when creating background images?

I cant figure out what size images i should make in photoshop


@rajeejones, I simply exported from iPhoto using the Medium size and Maximum quality setting. The resulting photo was 640 x 425, which is slightly bigger than the iPhone 5 screen. I was just lucky that the image cropped ok in my example.

On devices from the iPhone 6 and larger, this image doesn’t work well as it starts repeating (hence patternImage). This is why I don’t think my solution is the best, specifically when you use an image that is not a pattern that can repeat. One should probably stick to UIImageView for these kinds of images. Do you agree?


Casual poet is submitted to the app store,waiting for approval
Thank you paul for your support.
Here is the AppReview done with imovie (thanks to fernando).


Hi @PaulSolt I really liked this day! (Sorry I’m behind… I’ve been sick :p)

One question I would have is how to make the assets snap so they all line up?


for the snap in casual poet i’ve divided the poem area in lines.
In a given line when you End your pan gesture you reposition the y axis of the label center in the middle of the line and you reposition the x axis of the label origin to the x axis origin + width of the previous label in the same line.


Look at that example: ( you would have to define threshold for this at the start )

 if let subview = selectedView {
                center = subview.center
                var distance = sqrt(pow((center.x - p.x), 2.0) + pow((center.y - p.y), 2.0))
                println("distance \(distance)")
                if subview is MyView {
                    if distance > threshold {
                        if shouldDragX {
                            subview.center.x = p.x - (p.x % snapX)
                        if shouldDragY {
                            subview.center.y = p.y - (p.y % snapY)


Here is my admittedly small upgrade to the Word Magnets app, featuring rounded corners, alpha transparency, and Emoji :horse:

But what’s more interesting is the appetize.io website, which let’s you show off your apps instantly online for free with an impressively fast, accurate web based iOS emulator!


Yeah, I keep forgetting to use it :smile:
Good job. How do you add new words ?


Btw, where do you find the .app ? I have the path to mine, but when I try and go there I can’t find it. And then my .app shows red in xCode…


It is inside the Build/Products/Debug-iphonesimulator folder.