//

//  Question.swift

//  DISCTest

//

//  Created by stayfoolish on 08/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


struct Question: Codable {

    let d: String

    let i: String

    let s: String

    let c: String

}


extension Question {

    static var all: [Question] = {

        guard let dataAsset: NSDataAsset = NSDataAsset(name: "Questions") else {

            return []

        }

        

        let jsonDecoder: JSONDecoder = JSONDecoder()

        do {

            return try jsonDecoder.decode([Question].self, from: dataAsset.data)

        } catch {

            return[]

        }

    }()

}


//

//  Result.swift

//  DISCTest

//

//  Created by stayfoolish on 08/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


struct Result: Codable {

    static let shared: Result? = Result()

    

    let d: Info

    let i: Info

    let s: Info

    let c: Info

    

    private init?() {

        guard let dataAsset: NSDataAsset = NSDataAsset(name: "Result") else {

            return nil

        }

        

        do {

            let result: Result = try JSONDecoder().decode(Result.self , from: dataAsset.data)

            self = result

        } catch {

            return nil

        }

    }

}


extension Result {

    struct Info: Codable {

        let title: String

        let typeDescription: String

    }

}





//

//  UserInfo.swift

//  DISCTest

//

//  Created by stayfoolish on 08/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import Foundation


class UserInfo {

    static let shared: UserInfo = UserInfo()

    

    var name: String!

    var score: Score = Score()

    

    var hightestScoreResult: Result.Info? {

        let hightest: Int = max(self.score.d, self.score.i, self.score.s, self.score.c)

        switch hightest{

        case self.score.d:

            return Result.shared?.d

        case self.score.i:

            return Result.shared?.i

        case self.score.s:

            return Result.shared?.s

        default:

            return Result.shared?.c

        }

    }

    

    var scorePercentageText: String {

        

        let sum: Double = Double(self.score.d + self.score.i + self.score.s + self.score.c)

        let percentageD = Double(self.score.d) / sum * 100

        let percentageI = Double(self.score.i) / sum * 100

        let percentageS = Double(self.score.s) / sum * 100

        let percentageC = Double(self.score.c) / sum * 100

        

        return String(format: "D: %.0lf%%, I : %.0lf%%, S : %.0lf%%, C : %.0lf%%",

                    percentageD,

                    percentageI,

                    percentageS,

                    percentageC)

    }

    

}


extension UserInfo {

    class Score {

        var d: Int = 0

        var i: Int = 0

        var s: Int = 0

        var c: Int = 0

    }

    

    func reset() {

        self.score.d = 0

        self.score.i = 0

        self.score.s = 0

        self.score.c = 0

        self.name = nil

    }

    

    enum ScoreType {

        case d, i, s, c

    }

}


//

//  ResultViewController.swift

//  DISCTest

//

//  Created by stayfoolish on 08/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit



class ResultViewController: UIViewController {


    @IBOutlet weak var nameLabel: UILabel!

    @IBOutlet weak var percentageLabel: UILabel!

    @IBOutlet weak var titleLabel: UILabel!

    @IBOutlet weak var descriptionTextView: UITextView!

    

    override func viewWillAppear(_ animated: Bool) {

        super.viewWillAppear(animated)

        

        self.nameLabel.text = UserInfo.shared.name

        self.percentageLabel.text = UserInfo.shared.scorePercentageText

        

        guard let result: Result.Info = UserInfo.shared.hightestScoreResult else { return }

        

        self.titleLabel.text = result.title

        self.descriptionTextView.text = result.typeDescription

    }

    

    

    @IBAction func touchUpDismissButton(_ sender: UIButton) {

        self.navigationController?.presentingViewController?.dismiss(animated: true, completion: nil)

    }



    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

    


    /*

    // MARK: - Navigation


    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destinationViewController.

        // Pass the selected object to the new view controller.

    }

    */


}


//

//  QuestionViewController.swift

//  DISCTest

//

//  Created by stayfoolish on 08/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class QuestionViewController: UIViewController {

    

    // 인터페이스 빌더에서 설정한 버튼의 tag

    enum ButtonTag: Int {

        case d = 101

        case i, s, c

    }

    // 몇번째 질문인지 확인하기 위해 변수 설정

    var questionIndex: Int!

    

    @IBOutlet weak var backButton: UIButton!

    


    

    @IBAction func touchUpBackButton(_ sender: UIButton) {

        self.navigationController?.popViewController(animated: true)

    }

    

    @IBAction func touchUpAnswerButton(_ sender: UIButton) {

        

        guard let tag: ButtonTag = ButtonTag(rawValue: sender.tag) else {

            return

        }

        

        switch tag {

        case .d:

            UserInfo.shared.score.d += 1

        case .i:

            UserInfo.shared.score.i += 1

        case .s:

            UserInfo.shared.score.s += 1

        case .c:

            UserInfo.shared.score.c += 1

        }

        

        let nextIndex: Int = self.questionIndex + 1

        

        if Question.all.count > nextIndex,

            let nextViewController: QuestionViewController = self.storyboard?.instantiateViewController(withIdentifier: "QuestionViewController") as? QuestionViewController { nextViewController.questionIndex = nextIndex

            self.navigationController?.pushViewController(nextViewController, animated: true)

        } else {

            self.performSegue(withIdentifier: "ShowResult", sender: nil)

        }

        

    }

    

    override func viewWillAppear(_ animated: Bool) {

        super.viewWillAppear(animated)

        

        self.questionIndex = self.questionIndex ?? 0

        

        if self.questionIndex < 1 {

            self.backButton.isHidden = true

        }

        

        let question: Question = Question.all[questionIndex]

        

        guard let dButton: UIButton = self.view.viewWithTag(ButtonTag.d.rawValue) as? UIButton else { return }

        dButton.setTitle(question.d, for: UIControlState.normal)

        

        guard let iButton: UIButton = self.view.viewWithTag(ButtonTag.i.rawValue) as? UIButton else { return}

        iButton.setTitle(question.i, for: UIControlState.normal)

        

        guard let sButton: UIButton = self.view.viewWithTag(ButtonTag.s.rawValue) as? UIButton  else { return }

        sButton.setTitle(question.s, for: UIControlState.normal)

        

        guard let cButton: UIButton = self.view.viewWithTag(ButtonTag.c.rawValue) as? UIButton else { return }

        cButton.setTitle(question.c, for: UIControlState.normal)

    }

    

    override func viewDidLoad() {

        super.viewDidLoad()


        // Do any additional setup after loading the view.

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

    


    /*

    // MARK: - Navigation


    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destinationViewController.

        // Pass the selected object to the new view controller.

    }

    */


}


//

//  ViewController.swift

//  DISCTest

//

//  Created by stayfoolish on 08/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class ViewController: UIViewController {


    @IBOutlet weak var nameField: UITextField!

    @IBAction func touchUpStartButton(_ sender: UIButton) {

        guard let name: String = self.nameField.text,

        name.isEmpty == false else {

            let alert: UIAlertController

            alert = UIAlertController(title: "알림", message: "이름을 입력해주세요", preferredStyle: .alert)

            

            let okAction: UIAlertAction

            okAction = UIAlertAction(title: "확인", style: .cancel, handler: nil)

            

            alert.addAction(okAction)

            self.present(alert, animated: true, completion: nil)

            return

        }

        UserInfo.shared.name = self.nameField.text

        

        self.performSegue(withIdentifier: "PresentTest", sender: nil)

    }

    

    override func viewDidLoad() {

        super.viewDidLoad()

        // Do any additional setup after loading the view, typically from a nib.

    }

    

    override func viewWillAppear(_ animated: Bool) {

        super.viewWillAppear(animated)

        

        self.nameField.text = nil

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }



}












//

//  AppDelegate.swift

//  LoginFlow

//

//  Created by stayfoolish on 06/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {


    var window: UIWindow?



    func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions:

        [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool {

        print("애플리케이션이 실행되기 직전")

        return true

    }

    

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        print("애플리케이션이 실행된 직후")

        return true

    }

    


    func applicationWillResignActive(_ application: UIApplication) {

        print("애플리케이션이 비활성화 될 예정")

    }


    func applicationDidEnterBackground(_ application: UIApplication) {

        print("애플리케이션이 백그라운드로 진입함")


    }


    func applicationWillEnterForeground(_ application: UIApplication) {

        print("애플리케이션이 백그라운드에서 벗어날 예정")


    }


    func applicationDidBecomeActive(_ application: UIApplication) {

        print("애플리케이션이 활성화 됨")


    }


    func applicationWillTerminate(_ application: UIApplication) {

        print("애플리케이션이 종료되기 직전 ")


    }



}



//

//  LoginViewController.swift

//  LoginFlow

//

//  Created by stayfoolish on 07/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class LoginViewController: UIViewController {


    @IBOutlet weak var emailField: UITextField!

    @IBOutlet weak var passwordField: UITextField!

    

    @IBAction func touchUpLoginButton(_ sender: UIButton){

        

        guard let email: String = self.emailField.text,

            email.isEmpty == false else {

                self.showAlert(message: "이메일을 입력해주세요", control: self.emailField)

                return

        }

        

        guard let password: String = self.passwordField.text,

            password.isEmpty == false else {

                self.showAlert(message: "패스워드를 입력해주세요", control: self.passwordField)

                return

        }

        self.performSegue(withIdentifier: "ShowInfo", sender: sender)

    }

    

    override func viewDidLoad() {

        super.viewDidLoad()

        

        self.navigationItem.title = "로그인"

        

        print("LogingViewController 객체의 뷰가 메모리에 로드됨")

        // Do any additional setup after loading the view.

    }

    

    override func viewWillAppear(_ animated: Bool) {

        super.viewWillAppear(animated)

        

        self.navigationController?.setNavigationBarHidden(true, animated: true)

        

        print("LoginViewController 객체의 뷰가 나타날 예정")

    }

    

    override func viewDidAppear(_ animated: Bool) {

        super.viewDidAppear(animated)

        

        print("LoginViewController 객체의 뷰가 나타남")

    }

    

    override func viewWillDisappear(_ animated: Bool) {

        super.viewWillDisappear(animated)

        

        print("LoginViewController 객체의 뷰가 사라질 예정")

    }


    override func viewDidDisappear(_ animated: Bool) {

        super.viewDidDisappear(animated)

        

        print("LoginViewController 객체의 뷰가 사라짐")

    }

    

    private func showAlert(message: String, control toBeFirstResponder: UIControl?){

        let alert: UIAlertController = UIAlertController(title: "알림", message: message, preferredStyle: UIAlertControllerStyle.alert)

        

        let okAction: UIAlertAction = UIAlertAction(title: "입력하기", style: UIAlertActionStyle.default){ [weak toBeFirstResponder] (action: UIAlertAction) in toBeFirstResponder?.becomeFirstResponder()

            

        }

        

        let cancelAction: UIAlertAction = UIAlertAction(title: "취소", style: UIAlertActionStyle.cancel, handler: nil)

        

        alert.addAction(okAction)

        alert.addAction(cancelAction)

        

        self.present(alert, animated: true){

            print("얼럿 화면에 보여짐")

        }

    }


    

    // MARK: - Navigation


    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destinationViewController.

        // Pass the selected object to the new view controller.

        

        guard let email: String = self.emailField.text,

            let password: String = self.passwordField.text else {

                return

        }

        

        guard let id: String = segue.identifier else { return }

        guard id == "ShowInfo"  else { return }

        

        guard let infoViewController = segue.destination as? InfoViewController else {

            return

        }

        

        infoViewController.loginInfo = LoginInfo(email: email, password: password)

    }

    


}


//

//  InfoViewController.swift

//  LoginFlow

//

//  Created by stayfoolish on 07/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class InfoViewController: UIViewController {


    var loginInfo: LoginInfo?

    

    override func viewDidLoad() {

        super.viewDidLoad()


        print("InfoViewController 객체의 뷰가 메모리에 로드됨")

        // Do any additional setup after loading the view.

        

        self.navigationItem.title = "로그인 정보"

    }


    

    override func viewWillAppear(_ animated: Bool) {

        super.viewWillAppear(animated)

        

        print("InfoViewController 객체의 뷰가 나타날 예정")

        

        self.navigationController?.setNavigationBarHidden(false, animated: true)

        

        guard let info = self.loginInfo else {

            return

        }

        

        print(info)

    }

    

    override func viewDidAppear(_ animated: Bool) {

        super.viewDidAppear(animated)

        

        print("InfoViewController 객체의 뷰가 나타남")

    }

    

    override func viewWillDisappear(_ animated: Bool) {

        super.viewWillDisappear(animated)

        

        print("InfoViewController 객체의 뷰가 사라질 예정")

    }

    

    override func viewDidDisappear(_ animated: Bool) {

        super.viewDidDisappear(animated)

        

        print("InfoViewController 객체의 뷰가 사라짐")

    }



}


//

//  LoginInfo.swift

//  LoginFlow

//

//  Created by stayfoolish on 07/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import Foundation


struct LoginInfo {

    let email: String

    let password: String

}

















화면 전환 segue 


//

//  MainViewController.swift

//  CompanionAnimals

//

//  Created by stayfoolish on 02/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class MainViewController: UIViewController {


    private enum ButtonTag: Int {

        case dog = 101

        case cat, rabbit, hedgehog

    }

    

    override func viewDidLoad() {

        super.viewDidLoad()


        // Do any additional setup after loading the view.

    }


    private func animalInfo(for tag: ButtonTag) -> AnimalInfo? {

        let assetName: String

        

        switch tag{

        case ButtonTag.dog:

            assetName = "Dog"

        case ButtonTag.cat:

            assetName = "Cat"

        case ButtonTag.rabbit:

            assetName = "Rabbit"

        case ButtonTag.hedgehog:

            assetName = "Hedgehog"

        }

        

        return AnimalInfo.decode(from: assetName)

    }

    


    

    // MARK: - Navigation


    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destinationViewController.

        // Pass the selected object to the new view controller.

        

        guard let button: UIButton = sender as? UIButton else { return }

        

        guard let nextViewController: DescriptionViewController = segue.destination as? DescriptionViewController else { return }

        

        guard let tag: ButtonTag = ButtonTag(rawValue: button.tag) else {


            print("버튼의 태그를 enum으로 변경불가")

            return

        }

        

        guard let info: AnimalInfo = self.animalInfo(for: tag) else { return }

        

        nextViewController.animalInfo = info

    }

    


}


//

//  DescriptionViewController.swift

//  CompanionAnimals

//

//  Created by stayfoolish on 02/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class DescriptionViewController: UIViewController {


    var animalInfo: AnimalInfo!

    

    @IBOutlet var animalImageView: UIImageView!

    @IBOutlet var nameLabel: UILabel!

    @IBOutlet var descriptionTextView: UITextView!

    

    

    

    override func viewDidLoad() {

        super.viewDidLoad()


        // Do any additional setup after loading the view.

        self.navigationItem.title = self.animalInfo.name

        self.animalImageView.image = UIImage(named: self.animalInfo.imageName)

        self.nameLabel.text = self.animalInfo.name

        self.descriptionTextView.text = self.animalInfo.animalDescription

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

    


    /*

    // MARK: - Navigation


    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destinationViewController.

        // Pass the selected object to the new view controller.

    }

    */


}


//

//  MakerViewController.swift

//  CompanionAnimals

//

//  Created by stayfoolish on 02/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class MakerViewController: UIViewController {


    @IBOutlet var descriptionTextView: UITextView!

    

    override func viewDidLoad() {

        super.viewDidLoad()


        self.descriptionTextView.text = """

        안녕하세요 반갑습니다.

        애플리케이션을 이용해주셔서 고맙습니다.

        https://developer.apple.com/kr/swift/


        """

        // Do any additional setup after loading the view.

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

    

    @IBAction func touchUpInsideDismissButton(_ sender: UIButton){

        self.presentingViewController?.dismiss(animated: true, completion: nil)

    }


    /*

    // MARK: - Navigation


    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destinationViewController.

        // Pass the selected object to the new view controller.

    }

    */


}



//

//  AnimalInfo.swift

//  CompanionAnimals

//

//  Created by stayfoolish on 06/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


struct AnimalInfo: Codable {

    let name: String

    let animalDescription: String

    var imageName: String

    

    static func decode(from assetName: String) -> AnimalInfo? {

        guard let asset: NSDataAsset = NSDataAsset(name: assetName) else {

            print( "에셋 로드 실패")

            return nil

        }

        

        do {

            let decoder: PropertyListDecoder = PropertyListDecoder()

            return try decoder.decode(AnimalInfo.self, from: asset.data)

        } catch {

            print("데이터 디코딩 실패")

            print(error.localizedDescription)

            return nil

        }

    }

}

























swift colorpicker 스위프트 컬러피커



//

//  ViewController.swift

//  ColorPicker

//

//  Created by stayfoolish on 29/09/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class ViewController: UIViewController {


    private struct ColorComponent {

        

        typealias SliderTag = Int

        typealias Component = Int

        

        static let count: Int = 4

        

        static let red: Int = 0

        static let green: Int = 1

        static let blue: Int = 2

        static let alpha: Int = 3

        

        static func tag(`for`: Component) -> Int {

            return `for` + 100

        }

        

        static func component(from: SliderTag) -> Component {

            return from - 100

        }

    }

    

    private struct ViewTag {

        static let sliderRed: Int = 100

        static let sliderGreen: Int = 101

        static let sliderBlue: Int = 102

        static let sliderAlpha: Int = 103

    }

    

    

    

    @IBOutlet weak var colorView: UIView!

    @IBOutlet weak var pickerView: UIPickerView!

    

    private let rgbStep: Float = 255.0

    private let numberOfRGBStep: Int = 256

    private let numberOfAlphaStep: Int = 11

    

    

    

    @IBAction func sliderValueChanged(_ sender: UISlider) {

        guard (ViewTag.sliderRed...ViewTag.sliderAlpha).contains(sender.tag) else {

            print("wrong slider tag")

            return

        }

        

        let component: Int = ColorComponent.component(from: sender.tag)

        let row: Int

        

        if component == ColorComponent.alpha {

            row = Int(sender.value * 10)

        }else {

            row = Int(sender.value)

        }

        

        self.pickerView.selectRow(row, inComponent: component, animated: false)

        

        self.matchViewColorWithCurrentValue()

    }

    

    

    

    override func viewDidLoad() {

        super.viewDidLoad()

        

        for i in 0..<self.pickerView.numberOfComponents{

            let numberOfRows: Int = self.pickerView.numberOfRows(inComponent: i)

            self.pickerView.selectRow(numberOfRows - 1 , inComponent: i, animated: false)

        }

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }


    private func matchViewColorWithCurrentValue(){

        guard let redSlider: UISlider = self.view.viewWithTag(ViewTag.sliderRed) as? UISlider,

            let greenSlider: UISlider = self.view.viewWithTag(ViewTag.sliderGreen) as? UISlider,

            let blueSlider: UISlider = self.view.viewWithTag(ViewTag.sliderBlue) as? UISlider,

            let alphaSlider: UISlider = self.view.viewWithTag(ViewTag.sliderAlpha) as? UISlider

            else{

                return

        }

        

        // UIColor의 Red, Green, Blue, Alpha 값은 0과 1 사이의 실수 값

        let red: CGFloat = CGFloat(redSlider.value / self.rgbStep)

        let green: CGFloat = CGFloat(greenSlider.value / self.rgbStep)

        let blue: CGFloat = CGFloat(blueSlider.value / self.rgbStep)

        let alpha: CGFloat = CGFloat(alphaSlider.value)

        

        let color: UIColor = UIColor(red: red, green: green, blue: blue, alpha: alpha)

        

        self.colorView.backgroundColor = color

    }


}


extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource{

    

    func numberOfComponents(in pickerView: UIPickerView) -> Int {

        return ColorComponent.count

    }

    

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {

        if component == ColorComponent.alpha {

            return self.numberOfAlphaStep

        }else {

            return self.numberOfRGBStep

        }

    }

    

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

        if component == ColorComponent.alpha {

            return String(format: "%1.1lf", Double(row) * 0.1)

        }else {

            return "\(row)"

        }

    }

    

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

        let sliderTag: Int = ColorComponent.tag(for: component)

        

        guard let slider: UISlider = self.view.viewWithTag(sliderTag) as? UISlider else {

            return

        }

        

        if component == ColorComponent.alpha {

            slider.setValue(Float(row) / 10.0 , animated: false)

        }else {

            slider.setValue(Float(row), animated: false)

        }

        self.matchViewColorWithCurrentValue()

    }

}






스위프트 익스텐션 swift extension



import Swift


/*

- 익스텐션

 익스텐션은 구조체, 클래스, 열거형, 프로토콜 타입에

 새로운 기능을 추가할 수 있는 기능입니다.

 기능을 추가하려는 타입의 구현된 소스 코드를 알지 못하거나 볼수 없다해도,

 타입만 알고 있다면 그 타입의 기능을 확장할 수 도 있습니다.

 

 익스텐션으로 추가할 수 있는 기능

 연산 타입 프로퍼티 / 연산 인스턴스 프로퍼티

 타입 메서드 / 인스턴스 메서드

 이니셜라이저

 서브스크립트

 중첩 타입

 특정 프로토콜을 준수할 수 있도록 기능 추가

 

 기존에 존재하는 기능을 재정의할 수는 없습니다.

 

 extension 확장할 타입 이름 {

    타입에 추가될 새로운 기능 구현

 }

 

 익스텐션은 기존에 존재하는 타입이 추가적으로 다른 프로토콜을 채택할 수 있도록

 확장할 수도 있습니다.

 

 extenstion 확장할 타입 이름: 프로토콜1, 프로토콜2, 프로토콜3 ... {

    프로토콜 요구사항 구현

 }

 */


// 연산 프로퍼티 추가


extension Int {

    var isEven: Bool {

        return self % 2 == 0

    }

    var isOdd: Bool {

        return self % 2 == 1

    }

}


print(1.isEven) // false

print(2.isEven) // true

print(1.isOdd) // true

print(2.isOdd) // false


var number: Int = 3

print(number.isEven) // false

print(number.isOdd) // true


number = 2

print(number.isEven) // true

print(number.isOdd) // false



extension Int {

    func multiply(by n: Int) -> Int {

        return self * n

    }

}


print(3.multiply(by: 2)) // 6

print(4.multiply(by: 5)) // 20


number = 3

print(number.multiply(by: 2)) // 6

print(number.multiply(by: 3)) // 9


extension String {

    init(intTypeNumber: Int) {

        self = "\(intTypeNumber)"

    }

    

    init(doubleTypeNumber: Double){

        self = "\(doubleTypeNumber)"

    }

}


let stringFromInt: String = String(intTypeNumber: 100) // 100


let stringFromDouble: String = String(doubleTypeNumber: 100.0) // 100.0





스위프트 프로토콜 swift protocol








import Swift


/*

 

 1. 프로토콜

 프로토콜(Protocol) 은 특정 역할을 수행하기 위한 메서드, 프로퍼티, 기타 요구사항 등의 청사진을 정의합니다.

 구조체, 클래스, 열거형은 프로토콜을 채택(Adopted) 해서 특정 기능을 수행하기 위한 프로토콜의 요구사항을 실제로 구현할 수 있습니다.

 어떤 프로토콜의 요구사항을 모두 따르는 타입은 그 프로토콜을 준수한다(Conform)라고 표현합니다.

 타입에서 프로토콜의 요구사항을 충족시키려면 프로토콜이 제시하는 청사진의 기능을 모두 구현해야 합니다. 즉, 프로토콜은 기능을 정의하고 제시할 뿐이지

 스스로 기능을 구현 하지는 않습니다.

 

 2. 정의

 protocol 키워드를 사용하여 정의합니다.

 

 protocol 프로토콜 이름 {

 /* 정의부 */

 }

 

 3. 구현

 <<프로퍼티 요구>>

 프로퍼티 요구는 항상 var 키워드를 사용합니다

 get은 읽기만 가능해도 상관 없다는 뜻이며 get과 set을 모두 명시 하면 읽기 쓰기 모두 가능한 프로퍼티이어야 합니다


 */


protocol Talkable{

    

    //프로퍼티 요구

    var topic: String{get set}

    var language: String{get}

    

    //메소드 요구

    func talk()

    

    //이니셜라이저 요구

    init(topic: String, language: String)

}


struct Person: Talkable {

    //프로퍼티 요구 준수

    var topic: String

    let language: String

    

    //읽기전용 프로퍼티 요구는 연산 프로퍼티로 대체가 가능합니다.

    //var language: String {return "한국어"}

    

    //물론 읽기, 쓰기 프로퍼티도 연산 프로퍼티로 대체할 수 있습니다.

    /*

     var subject: String =""

     var topic: String{

     set {

        self.subject = newValue

      }

     get {

        return self.subject

      }

     }

 */

    

    // 메소드 요구 준수

    func talk() {

        print("\(topic)에 대해 \(language)로 말합니다")

    }

    

    // 이니셜라이저 요구 준수

    init(topic: String, language:String){

        self.topic = topic

        self.language = language

    }

}


// 프로퍼티 요구는 다양한 방법으로 해석, 구현할 수 있습니다.

struct Person2: Talkable{


    

    var subject: String = ""

    

    //프로퍼티 요구는 연산 프로퍼티로 대체가 가능합니다.

    var topic: String {

        set {

            self.subject = newValue

        }

        get {

            return self.subject

        }

    }

    

    var language: String{ return "한국어"}

    

    func talk(){

        print("\(topic)에 대해 \(language)로 말합니다")

    }

    

    init(topic: String, language: String){

        self.topic = topic

    }

}


/*

 - 프로토콜 상속

 프로토콜은 하나 이상의 프로토콜을 상속받아 기존 프로토콜의 요구사항보다 더 많은 요구사항을 추가할 수 있습니다.

 프로토콜 상속 문법은 클래스의 상속 문법과 유사하지만, 프로토콜은 클래스와 다르게 다중상속이 가능합니다.

 

 protocol 프로토콜 이름: 부모 프로토콜 이름 목록 {

 /* 정의부 */

 }

 */



protocol Readable {

    func read()

}


protocol Writeable{

    func write()

}


protocol ReadSpeakable: Readable{

    func speak()

}


protocol ReadWriteSpeakable: Readable, Writeable{

    func speak()

}


struct SomeType: ReadWriteSpeakable{

    func read() {

        print("Read")

    }

    func write() {

        print("Write")

    }

    func speak() {

        print("Speak")

    }

}


/*

 - 클래스 상속과 프로토콜

 클래스에서 상속과 프로토콜 채택을 동시에 하려면 상속받으려는 클래스를 먼저 명시하고 그 뒤에 채택할 프로토콜 목록을 작성합니다.

 */


class SuperClass: Readable{

    func read() {

    }

}


class SubClass: SuperClass, Writeable, ReadSpeakable{

    func write() {

    }

    func speak() {

    }

}


/*

 - 프로토콜 준수 확인

 is, as 연산자를 사용해서 인스턴스가 특정 프로토콜을 준수하는지 확인할 수 있습니다.

 */


let sup: SuperClass = SuperClass()

let sub: SubClass = SubClass()


var someAny: Any = sup

someAny is Readable // true

someAny is ReadSpeakable //false


someAny = sub

someAny is Readable //true

someAny is ReadSpeakable // true


someAny = sup


if let someReadable: Readable = someAny as? Readable{

    someReadable.read()

}


if let someReadSpeakable: ReadSpeakable = someAny as? ReadSpeakable{

    someReadSpeakable.speak()

} // 동작하지 않음


someAny = sub


if let someReadable: Readable = someAny as? Readable{

    someReadable.read()

}




업다운 게임 ( 오토레이아웃,  여백 클릭시 키보드 사라지는 기능 )


//

//  ViewController.swift

//  UpDown

//

//  Created by stayfoolish on 29/09/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class ViewController: UIViewController {

    

    // MARK - Properties

    

    @IBOutlet var resultLabel: UILabel!

    @IBOutlet var turnCountLabel : UILabel!

    @IBOutlet var inputField: UITextField!

    

    var randomNumber: UInt32 = 0

    var turnCount: Int = 0

    

    // MARK:- Methods

    @IBAction func touchUpSubmitButton (_ sender: UIButton) {

        guard let inputText = self.inputField.text,

            inputText.isEmpty == false else {

                print("입력값 없음")

                return

        }

        

        guard let inputNumber: UInt32 = UInt32(inputText) else {

            print("입력값이 잘 못 되었음")

            return

        }

        

        turnCount += 1

        self.turnCountLabel.text = "\(turnCount)"

        

        if inputNumber  > randomNumber{

            self.resultLabel.text = "UP!"

        }else if inputNumber < randomNumber{

            self.resultLabel.text = "DOWN!"

        }else {

            self.resultLabel.text = "정답입니다!"

        }


    }

    

    @IBAction func touchUPResetButton(_ sender: UIButton) {

        self.initializeGame()

    }

    

    @IBAction func tapBackground(_ sender: UITapGestureRecognizer) {

// 아래 3가지 중에 하나만 사용해도 키보드가 사라지는 기능 구현

        self.view.endEditing(true)

//        self.inputField.resignFirstResponder()

//        self.inputField.endEditing(true)


    }

    

    func initializeGame(){

        

        self.randomNumber = arc4random() % 25

        self.turnCount = 0

        

        self.resultLabel.text = "Strart!"

        self.turnCountLabel.text = "\(turnCount)"

        self.inputField.text = nil

        

        print("임의의 숫자 \(self.randomNumber)")

    }

    

    override func viewDidLoad() {

        super.viewDidLoad()

        self.initializeGame()

        // Do any additional setup after loading the view, typically from a nib.

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }



}













import Swift



/*

 

- Assertion

 

 assert(_:_:file:line:)함수를 사용합니다.

 assert 함수는 디버깅 모드에서만 동작합니다.

 배포하는 애플리케이션에서는 제외됩니다.

 예상했던 조건의 검증을 위하여 사용합니다.

 */


var someInt: Int = 0


// 검증 조건과 실패시 나타날 문구를 작성해 줍니다.

// 검증 조건에 부합하므로 지나갑니다.

assert(someInt == 0, "someInt != 0")


someInt = 1


//assert(someInt == 0) // 동작 중지, 검증 실패

//assert(someInt == 0, "someInt != 0") // 동작 중지, 검증 실패

//assertion failed: someInt != 0: file guard_assert.swift, line 26


func fuctionWithAssert(age: Int?) {

    assert(age != nil, "age == nil")

    

    assert((age! >= 0) && (age! <= 130), "나이값 입력이 잘못되었습니다")

    print("당신의 나이는 \(age!)세입니다")

}


fuctionWithAssert(age: 50)

//fuctionWithAssert(age: -1) // 동작 중지, 검증 실패

//fuctionWithAssert(age: nil) // 동작 중지, 검증 실패


// assert(_:_:file:line:)와 같은 역할을 하지만 실제 배포 환경에서도 동작하는 precondition(_:_:file:line:)함수도 있습니다.





autolayout 과 텍스트 필드에서 키보드 방식을 변경하여 적용하였습니다.










webkit 을 이용해서 웹브라우저 앱을 만들었습니다 뒤로 이동, 새로고침 앞으로 이동, 마지막 화면 저장했다가 앱 재실행 했을 경우 마지막 화면부터 시작하는 앱입니다.


//

//  ViewController.swift

//  MyWebBrowser

//

//  Created by stayfoolish on 2018. 9. 26..

//  Copyright © 2018년 stayfoolish. All rights reserved.

//


import UIKit

import WebKit


class ViewController: UIViewController {


    @IBOutlet var webView: WKWebView!

    @IBOutlet var activityIndicator: UIActivityIndicatorView!

    

    

    override func viewDidLoad() {

        super.viewDidLoad()

        // Do any additional setup after loading the view, typically from a nib.

        self.webView.navigationDelegate = self

    }


    override func viewDidAppear(_ animated: Bool) {

        super.viewDidAppear(animated)

        

        let firstPageURL: URL?

        

        if let lastURL: URL = UserDefaults.standard.url(forKey: lastPageURLDefaultKey){

            firstPageURL = lastURL

        }else {

            firstPageURL = URL(string: "https://www.google.com")

        }

        

        guard let pageURL: URL = firstPageURL else {

            return

        }

        

        let urlRequest: URLRequest = URLRequest(url: pageURL)

        self.webView.load(urlRequest)

    }

    

    @IBAction func goBack(_ sender: UIBarButtonItem) {

        self.webView.goBack()

    }

    

    @IBAction func goForward(_ sender: UIBarButtonItem) {

        self.webView.goForward()

    }

    

    @IBAction func refresh(_ sender: UIBarButtonItem) {

        self.webView.reload()

    }


    func showNetworkingIndicators(){

        self.activityIndicator.isHidden = false

        self.activityIndicator.startAnimating()

        UIApplication.shared.isNetworkActivityIndicatorVisible = true

    }


    func hideNetworkingIndicators(){

        self.activityIndicator.isHidden = true

        self.activityIndicator.stopAnimating()

        UIApplication.shared.isNetworkActivityIndicatorVisible = false

    }

}


extension ViewController: WKNavigationDelegate {

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!){

        print("did finish navigation")

        

        if let appDelegate: AppDelegate = UIApplication.shared.delegate as? AppDelegate {

            appDelegate.lastPageURL = webView.url

        }

        

        webView.evaluateJavaScript("document.title") { (value: Any? , error: Error?) in

            if let error: Error = error {

                print(error.localizedDescription)

                return

            }

            

            guard let title: String = value as? String else {

                return

            }

            

            self.navigationItem.title = title

    }

        self.hideNetworkingIndicators()

}


    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error){

        print("did fail navigation")

        print("\(error.localizedDescription)")

        

        self.hideNetworkingIndicators()

        let message: String = "오류발생!\n" + error.localizedDescription

        

        let alert: UIAlertController

        alert = UIAlertController(title: "알림", message: message, preferredStyle: UIAlertControllerStyle.alert)

        

        let okayAction: UIAlertAction

        okayAction = UIAlertAction(title: "확인", style: UIAlertActionStyle.cancel, handler: nil)

        

        alert.addAction(okayAction)

        

        self.present(alert, animated: true, completion: nil)

    }

    

    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!){

        print("did start navigation")

        self.showNetworkingIndicators()

    }


}






+ Recent posts