//

//  LoginViewController.swift

//  FreeTalk

//

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

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

//


import UIKit

import Firebase


class LoginViewController: UIViewController {


    @IBOutlet var email: UITextField!

    @IBOutlet var password: UITextField!

    @IBOutlet var loginButton: UIButton!

    @IBOutlet var signup: UIButton!

    let remoteConfig = RemoteConfig.remoteConfig()

    var color : String!

    override func viewDidLoad() {

        super.viewDidLoad()

        

        try! Auth.auth().signOut()

        let statusBar = UIView()

        self.view.addSubview(statusBar)

        statusBar.snp.makeConstraints {(m) in

            m.right.top.left.equalTo(self.view)

            m.height.equalTo(20)

            

        }

        color = remoteConfig["splash_background"].stringValue

        

        statusBar.backgroundColor = UIColor(hex: color)

        loginButton.backgroundColor = UIColor(hex: color)

        signup.backgroundColor = UIColor(hex: color)

        

        loginButton.addTarget(self, action: #selector(logingEvent), for: .touchUpInside)

        

        Auth.auth().addStateDidChangeListener{(auth, user) in

            if(user != nil){

                let view = self.storyboard?.instantiateViewController(withIdentifier: "MainViewController") as! MainViewController

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

            }

        }

        

        signup.addTarget(self, action: #selector(presentsSignup), for: .touchUpInside)

        // Do any additional setup after loading the view.

    }

    

    @objc func logingEvent(){

        Auth.auth().signIn(withEmail: email.text!, password: password.text!) {( user, err) in

            if(err != nil) {

                let alert = UIAlertController(title: "에러", message: err.debugDescription, preferredStyle: UIAlertControllerStyle.alert)

                alert.addAction(UIAlertAction(title: "확인",style: UIAlertActionStyle.default, handler: nil))

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

            }

        }

    }

    

    @objc func presentsSignup(){

        let view = self.storyboard?.instantiateViewController(withIdentifier: "SignupViewController") as! SignupViewController

        self.present(view, 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.

    }

    */


}





//

//  SignupViewController.swift

//  FreeTalk

//

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

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

//


import UIKit

import Firebase


class SignupViewController: UIViewController,UINavigationControllerDelegate,UIImagePickerControllerDelegate {

    

    @IBOutlet var imageView: UIImageView!

    

    @IBOutlet var email: UITextField!

    @IBOutlet var name: UITextField!

    

    @IBOutlet var password: UITextField!

   

    @IBOutlet var signup: UIButton!

    @IBOutlet var cancel: UIButton!

    

    let remoteConfig = RemoteConfig.remoteConfig()

    var color: String?


    override func viewDidLoad() {

        super.viewDidLoad()


        let statusBar = UIView()

        self.view.addSubview(statusBar)

        statusBar.snp.makeConstraints {(m) in

            m.right.top.left.equalTo(self.view)

            m.height.equalTo(20)

        }

        color = remoteConfig["splash_background"].stringValue

        

        statusBar.backgroundColor = UIColor(hex: color!)

        

        

        imageView.isUserInteractionEnabled = true

        imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(imagePicker)))

        

        

        signup.backgroundColor = UIColor(hex: color!)

        cancel.backgroundColor = UIColor(hex: color!)

        

        signup.addTarget(self, action: #selector(signupEvent), for: .touchUpInside)

        cancel.addTarget(self, action: #selector(cancelevent), for: .touchUpInside)

        // Do any additional setup after loading the view.

    }

    @objc func imagePicker(){

        

        let imagePicker = UIImagePickerController()

        imagePicker.delegate = self

        imagePicker.allowsEditing = true

        imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary

        

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

    }

    

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]){

        imageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage

        

        dismiss(animated: true, completion: nil)

    }

    

    @objc func signupEvent(){

        Auth.auth().createUser(withEmail: email.text!, password: password.text!) {(user, err) in

            let uid = user?.uid

            

            let image = UIImageJPEGRepresentation(self.imageView.image!, 0.1)

            

            Storage.storage().reference().child("userImages").child(uid!).putData(image!, metadata: nil, completion: { (data, error) in

             

                let imageUrl = data?.downloadURL()?.absoluteString

                Database.database().reference().child("users").child(uid!).setValue(["userName":self.name.text!,"profileImageUrl":imageUrl])

            })

        }

    }

    

    @objc func cancelevent(){

        self.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.

    }

    */


}













//

//  ViewController.swift

//  FreeTalk

//

//  Created by stayfoolish on 2018. 8. 30..

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

//



import UIKit

import SnapKit

import Firebase


class ViewController: UIViewController {


    var box = UIImageView() 

    var remoteConfig: RemoteConfig!

    

    override func viewDidLoad() {

        super.viewDidLoad()

        

        remoteConfig = RemoteConfig.remoteConfig()

        let remoteConfigSettings = RemoteConfigSettings(developerModeEnabled: true)

        remoteConfig.configSettings = remoteConfigSettings!

        remoteConfig.setDefaults(fromPlist: "RemoteConfigDefaults")


        remoteConfig.fetch(withExpirationDuration: TimeInterval(0)) { (status, error) -> Void in

            if status == .success {

                print("Config fetched!")

                self.remoteConfig.activateFetched()

            } else {

                print("Config not fetched")

                print("Error: \(error!.localizedDescription)")

            }

            self.displayWelcome()

        }

        

        

        self.view.addSubview(box)

        box.snp.makeConstraints{(make) in

            make.center.equalTo(self.view)

        }

        box.image =  imageLiteral(resourceName: "loading_icon")

        self.view.backgroundColor = UIColor(hex: "#000000")

    }


    func displayWelcome(){

        let color = remoteConfig["splash_background"].stringValue

        let caps = remoteConfig["splash_message_caps"].boolValue

        let message = remoteConfig["splash_message"].stringValue

        

        if(caps){

            let alert = UIAlertController(title: "공지사항", message: message, preferredStyle: UIAlertControllerStyle.alert)

            alert.addAction(UIAlertAction(title: "확인", style: UIAlertActionStyle.default, handler: { (action) in

                exit(0)

            }))

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

        }else{

            let loginVC = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController



            self.present(loginVC, animated: false, completion: nil)

        }

        self.view.backgroundColor = UIColor(hex: color!)

    }

    

    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }



}


extension UIColor {

    convenience init(hex: String) {

        let scanner = Scanner(string: hex)

        

        scanner.scanLocation = 1

        

        var rgbValue: UInt64 = 0

        

        scanner.scanHexInt64(&rgbValue)

        

        let r = (rgbValue & 0xff0000) >> 16

        let g = (rgbValue & 0xff00) >> 8

        let b = rgbValue & 0xff

        

        self.init(

            red: CGFloat(r) / 0xff,

            green: CGFloat(g) / 0xff,

            blue: CGFloat(b) / 0xff, alpha: 1

        )

    }

}





//

//  LoginViewController.swift

//  FreeTalk

//

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

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

//


import UIKit

import Firebase


class LoginViewController: UIViewController {


    @IBOutlet var loginButton: UIButton!

    @IBOutlet var signup: UIButton!

    let remoteConfig = RemoteConfig.remoteConfig()

    var color : String!

    override func viewDidLoad() {

        super.viewDidLoad()

        

        let statusBar = UIView()

        self.view.addSubview(statusBar)

        statusBar.snp.makeConstraints {(m) in

            m.right.top.left.equalTo(self.view)

            m.height.equalTo(20)

            

        }

        color = remoteConfig["splash_background"].stringValue

        

        statusBar.backgroundColor = UIColor(hex: color)

        loginButton.backgroundColor = UIColor(hex: color)

        signup.backgroundColor = UIColor(hex: color)

        

        signup.addTarget(self, action: #selector(presentsSignup), for: .touchUpInside)

        // Do any additional setup after loading the view.

    }

    

    @objc func presentsSignup(){

        let view = self.storyboard?.instantiateViewController(withIdentifier: "SignupViewController") as! SignupViewController

        self.present(view, 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.

    }

    */


}





//

//  SignupViewController.swift

//  FreeTalk

//

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

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

//


import UIKit

import Firebase


class SignupViewController: UIViewController {

    

    

    @IBOutlet var email: UITextField!

    @IBOutlet var name: UITextField!

    

    @IBOutlet var password: UITextField!

   

    @IBOutlet var signup: UIButton!

    @IBOutlet var cancel: UIButton!

    

    let remoteConfig = RemoteConfig.remoteConfig()

    var color: String?


    override func viewDidLoad() {

        super.viewDidLoad()


        let statusBar = UIView()

        self.view.addSubview(statusBar)

        statusBar.snp.makeConstraints {(m) in

            m.right.top.left.equalTo(self.view)

            m.height.equalTo(20)

        }

        color = remoteConfig["splash_background"].stringValue

        

        statusBar.backgroundColor = UIColor(hex: color!)

        signup.backgroundColor = UIColor(hex: color!)

        cancel.backgroundColor = UIColor(hex: color!)

        

        signup.addTarget(self, action: #selector(signupEvent), for: .touchUpInside)

        cancel.addTarget(self, action: #selector(cancelevent), for: .touchUpInside)

        // Do any additional setup after loading the view.

    }

    

    @objc func signupEvent(){

        Auth.auth().createUser(withEmail: email.text!, password: password.text!) {(user, err) in

            let uid = user?.uid

            Database.database().reference().child("users").child(uid!).setValue(["name":self.name.text!])

        }

    }

    @objc func cancelevent(){

        self.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.

    }

    */


}





















//

//  ViewController.swift

//  FreeTalk

//

//  Created by stayfoolish on 2018. 8. 30..

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

//



import UIKit

import SnapKit

import Firebase


class ViewController: UIViewController {


    var box = UIImageView() 

    var remoteConfig: RemoteConfig!

    

    override func viewDidLoad() {

        super.viewDidLoad()

        

        remoteConfig = RemoteConfig.remoteConfig()

        let remoteConfigSettings = RemoteConfigSettings(developerModeEnabled: true)

        remoteConfig.configSettings = remoteConfigSettings!

        remoteConfig.setDefaults(fromPlist: "RemoteConfigDefaults")


        remoteConfig.fetch(withExpirationDuration: TimeInterval(0)) { (status, error) -> Void in

            if status == .success {

                print("Config fetched!")

                self.remoteConfig.activateFetched()

            } else {

                print("Config not fetched")

                print("Error: \(error!.localizedDescription)")

            }

            self.displayWelcome()

        }

        

        

        self.view.addSubview(box)

        box.snp.makeConstraints{(make) in

            make.center.equalTo(self.view)

        }

        box.image =  imageLiteral(resourceName: "loading_icon")

        self.view.backgroundColor = UIColor(hex: "#000000")

    }


    func displayWelcome(){

        let color = remoteConfig["splash_background"].stringValue

        let caps = remoteConfig["splash_message_caps"].boolValue

        let message = remoteConfig["splash_message"].stringValue

        

        if(caps){

            let alert = UIAlertController(title: "공지사항", message: message, preferredStyle: UIAlertControllerStyle.alert)

            alert.addAction(UIAlertAction(title: "확인", style: UIAlertActionStyle.default, handler: { (action) in

                exit(0)

            }))

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

        }else{

            let loginVC = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController



            self.present(loginVC, animated: false, completion: nil)

        }

        self.view.backgroundColor = UIColor(hex: color!)

    }

    

    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }



}


extension UIColor {

    convenience init(hex: String) {

        let scanner = Scanner(string: hex)

        

        scanner.scanLocation = 1

        

        var rgbValue: UInt64 = 0

        

        scanner.scanHexInt64(&rgbValue)

        

        let r = (rgbValue & 0xff0000) >> 16

        let g = (rgbValue & 0xff00) >> 8

        let b = rgbValue & 0xff

        

        self.init(

            red: CGFloat(r) / 0xff,

            green: CGFloat(g) / 0xff,

            blue: CGFloat(b) / 0xff, alpha: 1

        )

    }

}





//

//  LoginViewController.swift

//  FreeTalk

//

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

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

//


import UIKit

import Firebase


class LoginViewController: UIViewController {


    @IBOutlet var loginButton: UIButton!

    @IBOutlet var signIn: UIButton!

    let remoteConfig = RemoteConfig.remoteConfig()

    var color : String!

    override func viewDidLoad() {

        super.viewDidLoad()

        let statusBar = UIView()

        self.view.addSubview(statusBar)

        statusBar.snp.makeConstraints {(m) in

            m.right.top.left.equalTo(self.view)

            m.height.equalTo(20)

            

        }

        color = remoteConfig["splash_background"].stringValue

        statusBar.backgroundColor = UIColor(hex: color)

        loginButton.backgroundColor = UIColor(hex: color)

        signIn.backgroundColor = UIColor(hex: color)

        

        

        // 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

//  FreeTalk

//

//  Created by stayfoolish on 2018. 8. 30..

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

//



import UIKit

import SnapKit

import Firebase


class ViewController: UIViewController {


    var box = UIImageView()

    var remoteConfig: RemoteConfig!

    

    override func viewDidLoad() {

        super.viewDidLoad()

        

        remoteConfig = RemoteConfig.remoteConfig()

        let remoteConfigSettings = RemoteConfigSettings(developerModeEnabled: true)

        remoteConfig.configSettings = remoteConfigSettings!

        remoteConfig.setDefaults(fromPlist: "RemoteConfigDefaults")


        remoteConfig.fetch(withExpirationDuration: TimeInterval(0)) { (status, error) -> Void in

            if status == .success {

                print("Config fetched!")

                self.remoteConfig.activateFetched()

            } else {

                print("Config not fetched")

                print("Error: \(error!.localizedDescription)")

            }

            self.displayWelcome()

        }

        

        

        self.view.addSubview(box)

        box.snp.makeConstraints{(make) in

            make.center.equalTo(self.view)

        }

        box.image =  imageLiteral(resourceName: "loading_icon")

        self.view.backgroundColor = UIColor(hex: "#000000")

    }


    func displayWelcome(){

        let color = remoteConfig["splash_background"].stringValue

        let caps = remoteConfig["splash_message_caps"].boolValue

        let message = remoteConfig["splash_message"].stringValue

        

        if(caps){

            let alert = UIAlertController(title: "공지사항", message: message, preferredStyle: UIAlertControllerStyle.alert)

            alert.addAction(UIAlertAction(title: "확인", style: UIAlertActionStyle.default, handler: { (action) in

                exit(0)

            }))

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

        }

        self.view.backgroundColor = UIColor(hex: color!)

    }

    

    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }



}


extension UIColor {

    convenience init(hex: String) {

        let scanner = Scanner(string: hex)

        

        scanner.scanLocation = 1

        

        var rgbValue: UInt64 = 0

        

        scanner.scanHexInt64(&rgbValue)

        

        let r = (rgbValue & 0xff0000) >> 16

        let g = (rgbValue & 0xff00) >> 8

        let b = rgbValue & 0xff

        

        self.init(

            red: CGFloat(r) / 0xff,

            green: CGFloat(g) / 0xff,

            blue: CGFloat(b) / 0xff, alpha: 1

        )

    }

}



import Swift


/*

 스위프트의 모든 인스턴스는 초기화와 동시에

 모든 프로퍼티에 유효한 값이 할당외어 있어야 합니다.

 프로퍼티에 미리 기본값을 할당해주면

 인스턴스가 생성됨과 동시에 초기값을 지니게 욉니다.

 */


class PersonA {

    // 모든 저장 프로퍼티에 기본값 할당

    var name: String = "unknown"

    var age: Int = 0

    var nickName: String = "nick"

}


let jason: PersonA = PersonA()

jason.name = "jason"

jason.age = 30

jason.nickName = "j"


/*

 이니셜라이저

 

 프로퍼티 기본값을 지정하기 어려운 경우에는

 이니셜라이저를 통해

 인스턴스가 가져야 할 초기값을 전달할 수 있습니다.

*/


class PersonB {

    var name: String

    var age: Int

    var nickName: String

    

    // 이니셜라이저

    init(name: String, age: Int, nickName: String){

        self.name = name

        self.age = age

        self.nickName = nickName

    }

    

}


let hana : PersonB = PersonB(name: "hana", age: 20, nickName: "하나")

// let hana : PersonB = PersonB(name: "hana", age: 20, nickName: "")


// 프로퍼티의 초기값이 꼭 필요 없을 때 옵셔널을 사용!


class PersonC {

    var name: String

    var age: Int

    var nickName: String?

    

    init(name: String, age: Int, nickName: String){

        // a

        self.name = name

        self.age = age

        self.nickName = nickName

    }

    

    /*

     중복 제거하는 방법

     convenience init(name: String, age: Int , nickName: String) {

        self.init(name: name, age: age)

        self.nickName = nickName

     }

     */

    

    init(name: String, age: Int){

        //a

        self.name = name

        self.age = age

    }

    

}


let jenny: PersonC = PersonC(name: "jenny", age: 10)

let mike: PersonC = PersonC(name: "mike", age: 15, nickName: "m")



/*

 암시적 추출 옵셔널은

 인스턴스 사용에 꼭 필요하지만

 초기값을 할당하지 않고자 할 때 사용

 */


class Puppy {

    var name: String

    var owner: PersonC!

    

    init(name: String){

        self.name = name

    }

    

    func goOut() {

        print("\(name)가 주인 \(owner.name)와 산책을 합니다")

    }

}


let happy: Puppy = Puppy(name: "happy")

// happy.goOut()

happy.owner = jenny

happy.goOut() // happy가 주인 jenny와 산책을 합니다.


/*

 실패가능한 이니셜라이저

 이니셜라이저 매개변수로 전달되는 초기값이 잘못된 경우

 인스턴스 생성에 실패할 수 있습니다.

 인스턴스 생성에 실패하면 nil을 반환합니다.

 그래서 실패가능한 이니셜라이저의 반환타입은 옵셔널 타입입니다.

 */


class PersonD {

    var name: String

    var age: Int

    var nickName: String?

    

    init?(name: String, age: Int) {

        if (0...120).contains(age) == false {

            return nil

        }

        

        if name.characters.count == 0 {

            return nil

        }

        

        self.name = name

        self.age = age

    }

}


// let john: PersonD = PersonD(name: "john", age: 23)

let john: PersonD? = PersonD(name: "john", age: 23)

let joker: PersonD? = PersonD(name: "joker", age: 123)

let batman: PersonD? = PersonD(name: "", age: 10)


print(joker)

print(batman)


/*

 디이니셜라이저

 

 deinit은 클래스의 인스턴스가

 메모리에서 해제되는 시점에 호출됩니다.

 인스턴스가 해제되는 시점에 해야할 일을 구현할 수 있습니다.

*/


class PersonE{

    var name: String

    var pet: Puppy?

    var child: PersonC

    

    init(name: String, child: PersonC){

        self.name = name

        self.child = child

    }

    

    deinit {

        if let petName = pet?.name {

            print("\(name)가 \(child.name)에게 \(petName)를 인도합니다")

            self.pet?.owner = child

        }

    }

}


var donald: PersonE? = PersonE(name: "donald", child: jenny)

donald?.pet = happy

donald = nil // donald 인스턴스가 더이상 필요없으므로 메모리에서 해제됩니다.

// donald가 jenny에게 happy를 인도합니다.



import Swift


/* 상속

 스위프트의 상속은 클래스, 프로토콜 등에서 가능합니다.

 열거형, 구조체는 상속이 불가능합니다.

 스위프트는 다중상속을 지원하지 않습니다.


*/


class Person {

    var name: String = ""

    

    func selfIntroduce() {

        print("저는 \(name)입니다")

    }

    // final 키워드를 사용하여 재정의를 방지할 수 있습니다.

    // 자식 class로 물려줬을 때 덮어쓰지(override) 않게 하기 위한 것입니다.

    final func sayHello(){

        print("hello")

    }

    

    // 타입 메서드

    // 재정의 불가 타입 메서드 - static

    static func typeMethod() {

        print("type method - static")

    }

    

    // 재정의 가능 타입 메서드 - class

    class func classMethod() {

        print("type method - class")

    }

    

    // 재정의 가능한 class 메서드라도 final 키워드를 사용하면 재정의 할 수 없습니다.

    // 메서드 앞의 `static` 과 `final class`는 똑같은 역할을 합니다.

    final class func finalclassMethod() {

        print("type method - final class")

    }

    

}


class Student: Person {

    // var name: String = ""

    var major: String = ""

    

    override func selfIntroduce() {

        print("저는 \(name)이고, 전공은 \(major)입니다.")

    }

    

    override class func classMethod(){

        print("overriden type method - class")

    }

    

    // static을 사용한 타입 메서드는 재정의 할 수 없습니다.

    // override static func typeMethod() {   }

    

    // final 키워드를 사용한 메서드, 프로퍼티는 재정의 할 수 없습니다.

    // override func sayHello() {   }

    // override class func finalClassMethod() {   }

}


let whoami: Person = Person()

let hana: Student = Student()


whoami.name = "realName"

hana.name = "hana"

hana.major = "Swift"


whoami.selfIntroduce() // 저는 realName입니다


hana.selfIntroduce() // 저는 hana이고, 전공은 Swift입니다.



Person.classMethod() // type method - class



Person.typeMethod() // type method - static



Person.finalclassMethod() // type method - final class



Student.classMethod() // overriden type method - class



Student.typeMethod() // type method - static



Student.finalclassMethod() // type method - final class







import Swift



struct Student {

    // 인스턴스 저장 프로퍼티

    var name: String = ""

    var `class`: String = "Swift"

    var koreanAge: Int = 0

    

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

    var westernAge: Int {

        get {

            return koreanAge - 1

        }

        set(inputValue){

            koreanAge = inputValue + 1

        }

    }

    

    // 타입 저장 프로퍼티

    static var typeDescription: String = "학생"

    

    // 읽기전용 인스턴스 연산 프로퍼티

    var selfIntroduction: String {

        get {

            return "저는 \(self.class)반 \(name)입니다"

        }

    }

    // 읽기전용 타입 연산 프로퍼티

    // 읽기전용에서는 get을 생략할 수 있습니다.

    static var selfIntroduction: String {

        return  "학생타입입니다"

    }

}

// 타입 연산 프로퍼티 사용

print(Student.selfIntroduction)


// 인스턴스 생성

var senior: Student = Student()

senior.koreanAge = 10


// 인스턴스 저장 프로퍼티 사용

senior.name = "성인"

print(senior.name)


// 인스턴스 연산 프로퍼티 사용

print(senior.selfIntroduction)


print("제 한국나이는 \(senior.koreanAge)살이고, 미국나이는 \(senior.westernAge)살입니다.")


struct Money {

    var currencyRate: Double = 1100

    var dollar: Double = 0

    var won: Double {

        get {

            return dollar * currencyRate

        }

        set {

            dollar = newValue / currencyRate

        }

    }

}


var moneyInMyPocket = Money()


moneyInMyPocket.won = 11000


print(moneyInMyPocket.won)


moneyInMyPocket.dollar = 10


print(moneyInMyPocket.won)  // 11000


var a: Int = 100

var b: Int = 200

var sum: Int {

    return a + b

}


print(sum) // 300


// 프로퍼티 감시자


struct Money2 {

    // 프로퍼티 감시자 사용

    var currencyRate: Double = 1100 {

        willSet(newRate){

            print("환율이 \(currencyRate)에서 \(newRate)으로 변경될 예정입니다.")

        }

        

        didSet(oldRate){

            print("환율이 \(oldRate)에서 \(currencyRate)으로 변경되었습니다.")

        }

    }

    // 프로퍼티 감시자 사용

    var dollar: Double = 0 {

        // willSet의 암시적 매개변수 이름 newValue

        willSet {

            print("\(dollar)달러에서 \(newValue)달러로 변경될 예정입니다")

        }

        

        // didSet의 암시적 매개변수 이름 oldValue

        didSet {

            print("\(oldValue)달러에서 \(dollar)달러로 변경되었습니다")

        }

    }

    

    // 연산 프로퍼티

    var won: Double {

        get {

            return dollar * currencyRate

        }

        set {

            dollar = newValue / currencyRate

        }

    }

    

}


var moneyInMyPocket2: Money2 = Money2()


moneyInMyPocket2.currencyRate = 1150


moneyInMyPocket2.dollar = 10


print(moneyInMyPocket2.won)


/*

 프로퍼티 감시자의 기능은

 함수, 메서드, 클로저, 타입 등의 외부에 위치한

 지역/전역 변수에도 모두 사용 가능합니다.

 */


var c: Int = 100 {

    willSet {

        print("\(c)에서 \(newValue)로 변경될 예정입니다.")

    }

    didSet {

        print("\(oldValue)에서 \(c)로 변경되었습니다")

    }

}


c = 200



import Swift


// 코드의 블럭

// 일급 시민

// 변수, 상수 등으로 저장, 전달인자로 전달이 가능

// 함수 : 이름이 있는 클로저



//{(매개변수 목록) -> 반환타입 in

//   실행 코드

//}



// 함수 사용

func sumFunction(a: Int, b: Int) -> Int {

    return a + b

}


var sumResult: Int = sumFunction(a: 1, b: 2)

print(sumResult) // 3


// 클로저 사용

var sum: (Int, Int) -> Int = { (a: Int, b: Int) in

    return a + b

}


sumResult = sum(1, 2)

print(sumResult) // 3


// 함수는 클로저의 일종이므로

// sum 변수에는 당연히 함수도 할당할 수 있습니다.

sum = sumFunction(a:b:)


sumResult = sum(1, 2)

print(sumResult) // 3


// 함수의 전달인자로서의 클로저

let add: (Int, Int) -> Int

add = { (a: Int, b: Int) in

    return a + b

}


let substract: (Int, Int) -> Int

substract = { (a: Int, b: Int) -> Int in

    return a - b

}


let divide: (Int, Int) -> Int

divide = {(a: Int, b:Int ) -> Int in

    return a / b

}


func calculate(a: Int, b: Int, method: (Int, Int) -> Int ) -> Int {

    return method(a, b)

}


var calculated: Int


calculated = calculate(a: 50, b: 10, method: add)

print(calculated) // 60


calculated = calculate(a: 50, b:10 , method: substract)

print(calculated) // 40


calculated = calculate(a: 50, b:10 , method: divide)

print(calculated) // 5


calculated = calculate(a: 50, b: 10, method: {(left: Int, right: Int) -> Int in

    return left * right

})

print (calculated) // 500


// 클로저 고급


/*

 후행 클로저

 반환타입 생략

 단축 인자이름

 암시적 반환 표현

*/


func calculate2(a: Int, b: Int, method: (Int, Int) -> Int) -> Int {

    return method(a, b)

}


var result: IntegerLiteralType


/*

 후행 클로저

 클로저가 함수의 마지막 전달인자라면

 마지막 매개변수 이름을 생략한 후

 함수 소괄호 외부에 클로저를 구현할 수 있습니다.

*/


result = calculate2(a: 10, b: 10) { (left: Int, right: Int) -> Int in

    return left + right

}


print(result) // 20


/*

 반환타입 생략

 calculate 함수의 method 매개변수는 Int 타입을 반환할 것이라는 사실을 컴파일러도 알기 때문에

 굳이 클로저에서 반환타입을 명시해 주지 않아도 됩니다.

 대신 in 키워드는 생략할 수 없습니다.

*/


result = calculate2(a: 10, b:10, method: {(left: Int, right: Int) in

    return left + right

})


print(result) // 20


// 후행클로저와 함께 사용할 수도 있습니다.

result = calculate2(a: 10, b: 10) {(left: Int, right: Int) in

    return left + right

}


/*

 단축 인자이름

 클로저의 매개변수 이름이 굳이 불필요하다면 단축 인자이름을 활용할 수 있습니다.

 단축 인자이름은 클로저의 매개변수의 순서대로 $0, $1 ... 처럼 표현합니다.

 */


result = calculate2(a: 10, b: 10, method: {

   return $0 + $1

})


print(result) // 20


// 당연히 후행 클로저와 함께 사용할 수 있습니다.

result = calculate2(a: 10, b: 10){

    return $0 + $1

}


print(result) // 20


// 간결하게 한 줄로 표현해 줄 수도 있습니다.

result = calculate2(a: 10, b: 10) { $0 + $1}

print(result) // 20


// 축약하지 않는 클로저 문법과 축약 후의 문법 비교


result = calculate2(a: 10, b: 10, method: {(left: Int, right: Int) -> Int in

    return left + right

})


result = calculate2(a: 10, b: 10) { $0 + $1 }

print(result) // 20


















import Swift


//class:

// 단일상속

// 참조타입

// apple 프레임워크의 대부분의 큰 뼈대는 모두 클래스로 구성

//

//struct:

// 상속불가

// 값타입

// swift의 대부분의 큰 뼈대는 모두 구조체로 구성

//

//Enum:

// 상속불가

// 값타입

// 열거형 자체가 하나의 데이터 타입

// 열거형의 case 하나하나 전부 하나의 유의미한 값으로 취급

//

//struct(구조체) 언제 사용?

// 참조가 아닌 복사를 원할 때, 상속받을 필요가 없을 때

//

//Value vs Reference

// Value : 데이터를 전달할 때 값을 복사하여 전달

// Reference : 데이터를 전달할 때 값의 메모리 위치를 전달


struct ValueType {

    var property = 1

}


class ReferenceType {

    var property = 1

}


let firstStructInstance = ValueType()

var secondStructInstance = firstStructInstance

secondStructInstance.property = 2


print("first struct instance property : \(firstStructInstance.property)") // first struct instance property : 1

print("second struct instance property : \(secondStructInstance.property)") // second struct instance property : 2


let firstClassReference = ReferenceType()

var secondClassReference = firstClassReference

secondClassReference.property = 2


print ("first class reference property : \(firstClassReference.property)") // first class reference property : 2

print ("second class reference property : \(secondClassReference.property)") // second class reference property : 2


struct SomeStruct {

    var someProperty: String = "Property"

}


var someStructInstance: SomeStruct = SomeStruct()


func someFunction(structInstance: SomeStruct) {

    var localVar: SomeStruct = structInstance

    localVar.someProperty = "ABC"

}


// 복사되서 들어가기 때문에 property 그대로 값이 유지된다.

someFunction(structInstance: someStructInstance)

print(someStructInstance.someProperty) // Property



class SomeClass {

    var someProperty: String = "Property"

}


var someClassInstance: SomeClass = SomeClass()


func someFunction(classInstance: SomeClass) {

    var localVar: SomeClass = classInstance

    localVar.someProperty = "ABC"

}


// 참조값이 전달되기 때문에 ABC 값으로 변경된다.

someFunction(classInstance: someClassInstance)

print(someClassInstance.someProperty) // ABC


// 스위프트는 구조체, 열거형 사용을 선호

// Apple 프레임워크는 대부분 class 사용

// Apple 프레임워크 사용시 struct/class 선택은 우리의 몫









+ Recent posts