Saturday, May 7, 2016

Notifications

Using NotificationCenter you can communicate from one class to another. For example, while executing code in one class you can notify the UI to update something.

Basic Setup

In a separate class you might "post" a notification. In this example I named the post "updateView". Notifications is a 3 step process:

Step 1 - Setup Post Names

 
extension Notification.Name {
    static let updateView = NSNotification.Name("updateView")
}
 

Step 2 - Post Notification

To pass data, you can send a dictionary to the userInfo parameter.
 
var userInfo: [String: String] = ["extraData": "Some extra data"]
userInfo["moreData"] = "Some more data"
NotificationCenter.default.post(name: .updateView, object: self, 
    userInfo: userInfo)
 

Step 3 - Observe Notification

Then in your ViewController you might be "observing" for that particular post called "updateView" in the notification center:
 
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver
            (forName: .updateView, object: nil, 
             queue: OperationQueue.main) {
        (notification) in
        // Get values from the class that sent the notification
        let poster = notification.object as! ClassThatPostedNotification
        let propertyValue = poster.property

        // Get values from userInfo
        let extraData = notification.userInfo?["extraData"] as! String
        let moreData = notification.userInfo?["moreData"] as! String
    }
}
 

So the ViewController will be observing any post called "updateView" and when it observes a post it calls updateView. I usually name my posts and functions the same name because...well, I am a simple guy. :)

(Swift 4)

Touch and Drag Objects

If you want to touch and drag an object around the screen you can do this by setting the object's center property to the location of your touch.
In this example I have an image (UIImageView) that I want to touch and drag.

Create New Class

import UIKit

class DraggableImage: UIImageView {
    
    override func touchesMoved(touches: Set, withEvent event: UIEvent?) {
        if let touch = touches.first {
            let position = touch.locationInView(superview)
            center = CGPointMake(position.x, position.y)
        }
    }
}
I override touchesMoved and am getting the position of my touch and making the center of my image the same position as my touch.


Setup Image in Xcode

In this example I am using a UIImageView. I dropped an image on my storyboard and I have to make 2 changes.
  1. Set the Custom Class
    Set the class to the class that overrides touchesMoved:
  2. Set Interaction
    Make sure "User Interaction Enabled" is checked. This allows your touchesMoved override to receive touch event messages.
    I also unchecked "Multiple Touch" because I'm only using one finger to move my object.
That is it! You should be able to run and move your image. (Written for Xcode 7.3, Swift 2.2)

Friday, May 6, 2016

Private - Scope

I just discovered this and thought I would share it. Look at this code:
class Vehicle {
    private var color: String = "red"
}

var car = Vehicle()

print(car.color)

How am I able to access the color property even though it is private?


It turns out it is file based. If you are in the same file as the class you can access the private variables. But if you put your class in one file and then instantiate it another file then you cannot access the private variables.

(Swift 2.2)

Thursday, May 5, 2016

Add And Play Sound In Your iOS Project


Tutorial on adding sounds to iOS projects.
  1. Drag and drop your sound file into your project.
    In this example the name of my sound file is "ButtonClickSound.wav".
  2. Code
    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController {
    
        var buttonClickSound: AVAudioPlayer!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            let path = NSBundle.mainBundle().pathForResource("ButtonClickSound", 
                ofType: "wav")
            let url = NSURL(fileURLWithPath: path!)
            
            do {
                try buttonClickSound = AVAudioPlayer(contentsOfURL: url)
                buttonClickSound.prepareToPlay()
            } catch let err as NSError {
                print(err.debugDescription)
            }
        }
    
        @IBAction func PlaySound_TouchUpInside(sender: UIButton) {
            if buttonClickSound.playing {
                buttonClickSound.stop()
            }
    
            buttonClickSound.play()
        }
    }
    
    

(Swift 2.2)

Wednesday, May 4, 2016

Add Custom Fonts To Your iOS App

Tutorial on using a custom font
  1. Get your font
    Go to your favorite font website and download a font. I will go to http://www.dafont.com/ and download one. Unzip the download and you should see a *.ttf file.
  2. Add to your project
    Drag and drop the *.ttf file directly into your Xcode project. A dialog will appear. Make sure you add checkmarks to Destination and your target application.
  3. Add to your info.plist
    Select the last item in your info.plist and click the "+" button. Select "Fonts provided by application" (start typing in "Fonts" and it will show up). Expand this item and in the empty space next to "Item 0" type in the full name of your font file. (I just copy and paste the file name.)
  4. Change the font on your label
    Add a label to your UI and change the font. You have to select "Custom" first. Then you can change the font's family to your custom font's name.

Thursday, March 10, 2016

Enums

Declaring

enum Direction {
    case Right
    case Left
}
// Or
enum Direction {
    case Right, Left
}
// Or
enum Direction: String {
    case Right = "Right turn only"
    case Left = "Left turn only"
}

Using

var turn = Direction.Right

if (turn == Direction.Right) {
    print("Turn \(turn)") // "Turn Right"
}

turn = .Left // Shorthand assignment

print("Turn \(turn)") // "Turn Left"

switch turn {
case .Right:
    print("You will be turning right.")
case .Left:
    print("You will be turning left.")
}
There is more to Enums than just this but to be honest, I will probably never use an Enum beyond this.

(Swift 2.2)

Monday, February 29, 2016

OAuthSwift Tutorial

I couldn't find a tutorial on this so this is my documented journey into trying to figure out how to implement OAuthSwift into an iOS project. I honestly don't know if I will fail or succeed. So far just from reading the GitHub page for OAuthSwift I can't even figure it out so it is time to just start trying to break it apart piece by piece and implementing it.

OK, let's look at the GitHub page for OAuthSwift and go with the "simplest way":

(From OAuthSwift's GitHub page)
OAuthSwift is packaged as a Swift framework. Currently this is the simplest way to add it to your app:
  • Drag OAuthSwift.xcodeproj to your project in the Project Navigator.
  • Select your project and then your app target. Open the Build Phases panel.
  • Expand the Target Dependencies group, and add OAuthSwift framework.
  • import OAuthSwift whenever you want to use OAuthSwift.

-------------------------------
Let's start with the first step:

Drag OAuthSwift.xcodeproj to your project in the Project Navigator.

Ok, first I clicked the "Download ZIP" button from the GitHub webpage. I went into my Downloads folder and unzipped the file "OAuthSwift-master.zip". I look in the newly unzipped folder and see "OAuthSwift.xcodeproj" in there.

So far so good. Now I'm going to create a new Single View Application project that will use this XCode Project file and call it "InstagramLogin" since this is what I'm interested in trying to do. I bring up my Downloads folder so I can drag the "OAuthSwift.xcodeproj" file into my XCode Project Navigator. I'm not sure where to drag the file to so I just try dropping it into the very top of my new project, "InstagramLogin".

XCode shows me a message:

I remember reading that if you combine more than one "xcodeproj" together than it has to be done in a "workspace". I click Save and name my new workspace the same as my initial project, "InstagramLogin".

After doing this I see the two projects in my Project Navigator in XCode. Looks like all the files were copied from the Downloads folder automatically. I try building and build succeeds.

OK, on to the next step!

Select your project and then your app target. Open the Build Phases panel.

Clicking around I found out what he means. When you click on your project, "InstagramLogin" in my case, it shows the project properties. On the left hand side of these project settings I see "PROJECT" and "TARGETS". So I clicked on my project name under "TARGETS". I'm honestly still kind of a newbie so I really don't know what this means. At the top of this window I found "Build Phases" and clicked on that:

Expand the Target Dependencies group, and add OAuthSwift framework.

I expanded "Target Dependencies" group. There is a "+" and "-" showing. So I click on the "+" button. This window shows:

Should "OAuthSwift" project be showing in there? From here I can't seem to figure out how to complete this step. Googling how to add a project dependency in XCode brought up a StackOverflow answer. Looks like the instructions are different.

So instead of going through "Target Dependencies" I'm going to go to the General tab and scroll to the bottom to "Linked Frameworks and Libraries" and click the plus ("+") button there. This is what I see:

I think I will select the first one. Although it does not say "iOS" on it the others do not say "iOS" so it is kind of a process of elimination.

Now for the final test...

import OAuthSwift whenever you want to use OAuthSwift.

Just to make sure what I have done so far works, I am just going to open up ViewController.swift in my "InstagramLogin" project and add import OAuthSwift and see if the project builds. Yes! It does build! Now on to using this framework!

Implementing OAuthSwift

OK, now that I can link to OAuthSwift it looks like I can move to the next step and start developing the actual Instagram login. So let's keep following the instructions on the GitHub page for OAuthSwift and see how to do this.

The first thing the page says to do is to set the URL scheme and shows a screenshot:

OK, I have no idea how to do this or even where that screenshot is from. I'm going to have to do some Googling once more and search for maybe "URL Types XCode".

I found a link to twitter development and they had a full screenshot of where the image above comes from. I had to select my project "InstagramLogin" in the Project Navigator, selected my project again under TARGETS, then select Info up top. I scrolled to the bottom and there it was. I clicked the "+" icon to add a new item.

I added my application name but I seriously don't even know what this does. I'm just trusting that it is needed.

OK, continuing on, let's look at the Examples section on the OAuthSwift GitHub page.

I am just going to copy and paste the code example under "Handle URL in AppDelegate" into my AppDelegate:

func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
  if (url.host == "oauth-callback") {
    OAuthSwift.handleOpenURL(url)
  }
  return true
}

I try to build but it fails. Looks like I need to add:

import OAuthSwift

Now it builds. Do I need to use a different string where it says "oauth-callback"? I do not know. Maybe I will find out later.

Now on the GitHub page they have some code examples. I'm going to go with the OAuth2.0 example:

let oauthswift = OAuth2Swift(
    consumerKey:    "********",
    consumerSecret: "********",
    authorizeUrl:   "https://api.instagram.com/oauth/authorize",
    responseType:   "token"
)
oauthswift.authorizeWithCallbackURL(
    NSURL(string: "oauth-swift://oauth-callback/instagram")!,
    scope: "likes+comments", state:"INSTAGRAM",
    success: { credential, response, parameters in
      print(credential.oauth_token)
    },
    failure: { error in
      print(error.localizedDescription)
    }
)

Looks like an Instagram example, which is good for me. Hmm...let's see. What do I do with this? It looks like I first have to create a variable (oathswift) that will hold my Instagram account info. I have already setup my Instagram account so I have all of this information.

I am a little confused actually as far as what is going on so I will have to do a little more research on what typically happens with Open Authentication.

To be continued...
















SwiftUI Search & Filter with Combine - Part 3 (iOS, Xcode 13, SwiftUI, 2...

In part 3 of the Searchable video series, I show you how to use Combine in #SwiftUI for the search and filter logic connected to the searcha...