ios 실전 앱 만들기 : 어떤 앱이 만들어 질까



logincontroller.swift


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

// t\색상68cd4c


import UIKit

import Firebase

class LoginController: UIViewController,UIPickerViewDelegate,UIPickerViewDataSource {

    

    //사진 선택했는지 체크

    var picCheck = false

    

    //피커뷰 데이터

    let gender = ["남자","여자"]

    var age:[String] = []

    

    var messagesController: MessageController?

    

    //피커뷰 객체

    let genderPickerView :UIPickerView = {

        let pick = UIPickerView()

        pick.tag = 1

        return pick

    }()

    //나이 피커뷰 객체

    let agePickerView :UIPickerView = {

        let pick = UIPickerView()

        pick.tag = 2

        return pick

    }()

    

    //피커뷰 상속 메서드

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

        return 1

    }

    //피커뷰 row 개수

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


        var countrows : Int = age.count

        if (pickerView == genderPickerView){

            countrows = gender.count

        }

        return countrows

    }

    

    //피커뷰 제목

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

        if pickerView == genderPickerView {

            let titleRow = gender[row]

            return titleRow

        } else if pickerView == agePickerView {

            let titleRow = age[row]

            return titleRow

        }

        return ""

    }

    //피커뷰를 선택했을 때

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

        if pickerView == genderPickerView {

            let titleRow = gender[row]

            genderSegmentControl.text = titleRow

            genderSegmentControl.resignFirstResponder()

        } else if pickerView == agePickerView {

            let titleRow = age[row]

            ageTextField.text = titleRow

            ageTextField.resignFirstResponder()

        }

    }

    

    //컨테이너 뷰

    let inputsContainerView: UIView = {

        let view = UIView()

        view.backgroundColor = UIColor.black

        view.translatesAutoresizingMaskIntoConstraints = false

        view.layer.cornerRadius = 5

        view.layer.masksToBounds = true

        return view

    }()

    

    //로그인 버튼

    lazy var loginRegisterButton: UIButton = {

        let button = UIButton(type: .system)

        button.backgroundColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        button.setTitle("가입ㄱㄱ", for: UIControlState())

        button.translatesAutoresizingMaskIntoConstraints = false

        button.setTitleColor(.black, for: UIControlState())

        button.titleLabel?.font = UIFont(name: "SDMiSaeng", size: 30)

        button.layer.cornerRadius = 5

        button.layer.masksToBounds = true

        button.addTarget(self, action: #selector(handleLoginRegister), for: .touchUpInside)

        return button

    }()

    

    @objc func handleLoginRegister(){

        if loginRegisterSegmentedControl.selectedSegmentIndex == 0 {

            handleLogin()

        }else{

            handleRegister()

        }

    }

    

    //로그인 버튼 액션

    func handleLogin(){

        guard let email = emailTextField.text, let password = passwordTextField.text else {

            print("값이 없거나 잘못된 형식")

            return

        }

        

        Auth.auth().signIn(withEmail: email, password: password) { (user, error) in

            if let error = error {

                print(error)

                return

            }

            //로그인 할때 네비게이션 바 데이터 변경 함수 호출

            self.messagesController?.fetchUserAndSetupNavBarTitle()

            //로그인 성공시 로그인창 내려주기

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

        }

        

    }

    

    //닉네임 텍스트 필드

    let nameTextField: UITextField = {

        let tf = UITextField()

        tf.placeholder = "어렸을때 별명ㅋㅋ"

        if let placeholder = tf.placeholder {

            tf.attributedPlaceholder = NSAttributedString(string:placeholder,

                                                                     attributes: [NSAttributedStringKey.foregroundColor: UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)])

        }

        tf.font = UIFont(name: "SDMiSaeng", size: 25)

        tf.textColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        tf.tintColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        tf.translatesAutoresizingMaskIntoConstraints = false

        return tf

    }()

    //닉네임 구분선

    let nameSeparatorView: UIView = {

        let view = UIView()

        view.backgroundColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        view.translatesAutoresizingMaskIntoConstraints = false

        return view

    }()

    

    //이메일 텍스트 필드

    let emailTextField: UITextField = {

        let tf = UITextField()

        tf.placeholder = "비번 찾을때 이메일"

        if let placeholder = tf.placeholder {

            tf.attributedPlaceholder = NSAttributedString(string:placeholder,

                                                          attributes: [NSAttributedStringKey.foregroundColor: UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)])

        }

        tf.font = UIFont(name: "SDMiSaeng", size: 25)

        tf.textColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        tf.tintColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        tf.translatesAutoresizingMaskIntoConstraints = false

        return tf

    }()

    //이메일 구분선

    let emailSeparatorView: UIView = {

        let view = UIView()

        view.backgroundColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        view.translatesAutoresizingMaskIntoConstraints = false

        return view

    }()

    //패스워드 텍스트 필드

    let passwordTextField: UITextField = {

        let tf = UITextField()

        tf.placeholder = "비밀번호는 여섯자리 이상"

        if let placeholder = tf.placeholder {

            tf.attributedPlaceholder = NSAttributedString(string:placeholder,

                                                          attributes: [NSAttributedStringKey.foregroundColor: UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)])

        }

        tf.font = UIFont(name: "SDMiSaeng", size: 25)

        tf.textColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        tf.tintColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        tf.translatesAutoresizingMaskIntoConstraints = false

        tf.isSecureTextEntry = true

        return tf

    }()

    

    //패스워드 구분선

    let passwordSeparatorView: UIView = {

        let view = UIView()

        view.backgroundColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        view.translatesAutoresizingMaskIntoConstraints = false

        return view

    }()

    

    //성별

    lazy var genderSegmentControl: UITextField = {

        let tf = UITextField()

        tf.placeholder = "남자 여자?"

        if let placeholder = tf.placeholder {

            tf.attributedPlaceholder = NSAttributedString(string:placeholder,

                                                          attributes: [NSAttributedStringKey.foregroundColor: UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)])

        }

        tf.font = UIFont(name: "SDMiSaeng", size: 25)

        tf.textColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        tf.tintColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        tf.translatesAutoresizingMaskIntoConstraints = false

        return tf

        

    }()

    

    //성별 구분선

    let genderSeperatorView:UIView = {

        let view = UIView()

        view.backgroundColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        view.translatesAutoresizingMaskIntoConstraints = false

        return view

    }()

    

    

    //나이

    lazy var ageTextField:UITextField = {

        let tf = UITextField()

        tf.placeholder = "나이"

        if let placeholder = tf.placeholder {

            tf.attributedPlaceholder = NSAttributedString(string:placeholder,

                                                          attributes: [NSAttributedStringKey.foregroundColor: UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)])

        }

        tf.font = UIFont(name: "SDMiSaeng", size: 25)

        tf.textColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        tf.tintColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        tf.translatesAutoresizingMaskIntoConstraints = false

        return tf

    }()

    

    

    //프로필 이미지

    lazy var profileImageView: UIImageView = {

        let imageView = UIImageView()

        imageView.image = UIImage(named: "main2")

        imageView.translatesAutoresizingMaskIntoConstraints = false

        imageView.contentMode = .scaleAspectFill

        //클릭시 이벤트 등록

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

        imageView.isUserInteractionEnabled = true

        return imageView

    }()

    

    lazy var loginRegisterSegmentedControl:UISegmentedControl = {

        

        let sc = UISegmentedControl(items: ["로그인","가입ㄱㄱ"])

        sc.translatesAutoresizingMaskIntoConstraints = false

        let font = UIFont(name: "SDMiSaeng", size: 20)

        sc.setTitleTextAttributes([NSAttributedStringKey.font: font as Any],

                                                for: .normal)

        sc.tintColor = UIColor(red:0.41, green:0.80, blue:0.30, alpha:1.0)

        sc.selectedSegmentIndex = 1

        sc.addTarget(self, action: #selector(handleLoginRegisterChange), for: .valueChanged)

        return sc

    }()

    

    //로그인 등록 세그먼트

    @objc func handleLoginRegisterChange(){

        let title = loginRegisterSegmentedControl.titleForSegment(at: loginRegisterSegmentedControl.selectedSegmentIndex)

        loginRegisterButton.setTitle(title, for: UIControlState())

        

        let containerHeight =  loginRegisterSegmentedControl.selectedSegmentIndex  == 0 ? 100 : 200

        inputsContainerViewHeightAnchor?.constant = CGFloat(containerHeight)

        

        //이름 필드 높이

        nameTextFieldHeightAnchor?.isActive = false

        nameTextFieldHeightAnchor = loginRegisterSegmentedControl.selectedSegmentIndex  == 0 ? nameTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 0) : nameTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/5)

        nameTextFieldHeightAnchor?.isActive = true

        

        //이메일 필드 높이

        emailTextFieldHeightAnchor?.isActive = false

        emailTextFieldHeightAnchor = loginRegisterSegmentedControl.selectedSegmentIndex  == 0 ? emailTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/2) : emailTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/5)

        emailTextFieldHeightAnchor?.isActive = true

        

        //비밀번호 필드 높이

        passwordTextFieldHeightAnchor?.isActive = false

        passwordTextFieldHeightAnchor = loginRegisterSegmentedControl.selectedSegmentIndex  == 0 ? passwordTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/2) : passwordTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/5)

        passwordTextFieldHeightAnchor?.isActive = true

        

        //성별 높이

        genderSegmentControlHeightAnchor?.isActive = false

        genderSegmentControlHeightAnchor = loginRegisterSegmentedControl.selectedSegmentIndex  == 0 ? genderSegmentControl.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 0) : genderSegmentControl.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/5)

        genderSegmentControlHeightAnchor?.isActive = true

        

        //나이 높이

        ageTextFieldHeightAnchor?.isActive = false

        ageTextFieldHeightAnchor = loginRegisterSegmentedControl.selectedSegmentIndex  == 0 ? ageTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 0) : ageTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/5)

        ageTextFieldHeightAnchor?.isActive = true

        

    }

    

    

    

    //진입점

    override func viewDidLoad() {

        super.viewDidLoad()

        

        //나이 피커뷰에 데이터 넣어주기

        for i in 8...99{

            self.age.append("\(i)")

        }

        

        //바깥탭 -> 키보드 숨기기

        self.hideKeyboard()

        

        //피커뷰 델리게이트

        genderPickerView.delegate = self

        genderPickerView.dataSource = self

        agePickerView.delegate = self

        agePickerView.dataSource = self

        

        view.backgroundColor = .black

        

        view.addSubview(inputsContainerView)

        view.addSubview(loginRegisterButton)

        view.addSubview(profileImageView)

        view.addSubview(loginRegisterSegmentedControl)

        

        

        //입력 객체

        setupInputsContainerView()

        //로그인버튼 객체

        setupLoginRegisterButton()

        //이미지뷰 객체

        setupProfileImageView()

        //로그인 세그먼트 컨트롤

        setupLoginRegisterSegmentedControl()

        

    }

    

    //로그인등록 버튼 세그먼트 제약조건

    func setupLoginRegisterSegmentedControl(){

        loginRegisterSegmentedControl.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        loginRegisterSegmentedControl.bottomAnchor.constraint(equalTo: inputsContainerView.topAnchor, constant: -15).isActive = true

        loginRegisterSegmentedControl.heightAnchor.constraint(equalToConstant: 30).isActive = true

        loginRegisterSegmentedControl.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true

        

    }

    

    //높이 제약조건

    var inputsContainerViewHeightAnchor: NSLayoutConstraint?

    var nameTextFieldHeightAnchor: NSLayoutConstraint?

    var emailTextFieldHeightAnchor: NSLayoutConstraint?

    var passwordTextFieldHeightAnchor: NSLayoutConstraint?

    var genderSegmentControlHeightAnchor: NSLayoutConstraint?

    var ageTextFieldHeightAnchor: NSLayoutConstraint?

    

    //컨테이너 뷰 제약조건 설정

    func setupInputsContainerView(){

        //컨테이너 뷰 제약조건

        inputsContainerView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        inputsContainerView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

        inputsContainerView.widthAnchor.constraint(equalTo:view.widthAnchor,constant:-24).isActive = true

        

        inputsContainerViewHeightAnchor = inputsContainerView.heightAnchor.constraint(equalToConstant: 200)

        inputsContainerViewHeightAnchor?.isActive = true

        

        

        //컨테이너 뷰 안에 뷰객체 넣기

        inputsContainerView.addSubview(nameTextField)

        inputsContainerView.addSubview(nameSeparatorView)

        inputsContainerView.addSubview(emailTextField)

        inputsContainerView.addSubview(emailSeparatorView)

        inputsContainerView.addSubview(passwordTextField)

        

        inputsContainerView.addSubview(passwordSeparatorView)

        inputsContainerView.addSubview(genderSegmentControl)

        genderSegmentControl.inputView = genderPickerView

        inputsContainerView.addSubview(genderSeperatorView)

        inputsContainerView.addSubview(ageTextField)

        ageTextField.inputView = agePickerView

        

        //뷰객체 제약조건 설정

        //이름

        nameTextField.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor, constant: 12).isActive = true

        nameTextField.topAnchor.constraint(equalTo: inputsContainerView.topAnchor, constant: 0).isActive = true

        nameTextField.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor, constant: 0).isActive = true

        

        nameTextFieldHeightAnchor = nameTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/5)

        nameTextFieldHeightAnchor?.isActive = true

        

        //이름 구분선

        nameSeparatorView.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true

        nameSeparatorView.topAnchor.constraint(equalTo: nameTextField.bottomAnchor).isActive = true

        nameSeparatorView.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true

        nameSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true

        

        //이메일

        emailTextField.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor, constant: 12).isActive = true

        emailTextField.topAnchor.constraint(equalTo: nameTextField.bottomAnchor, constant: 0).isActive = true

        emailTextField.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor, constant: 0).isActive = true

        emailTextFieldHeightAnchor = emailTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/5)

        emailTextFieldHeightAnchor?.isActive = true

        

        //이메일 구분선

        emailSeparatorView.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true

        emailSeparatorView.topAnchor.constraint(equalTo: emailTextField.bottomAnchor).isActive = true

        emailSeparatorView.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true

        emailSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true

        

        //비밀번호

        passwordTextField.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor, constant: 12).isActive = true

        passwordTextField.topAnchor.constraint(equalTo: emailTextField.bottomAnchor, constant: 0).isActive = true

        passwordTextField.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor, constant: 0).isActive = true

        passwordTextFieldHeightAnchor = passwordTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/5)

        passwordTextFieldHeightAnchor?.isActive = true

        

        //비밀번호 구분선

        passwordSeparatorView.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true

        passwordSeparatorView.topAnchor.constraint(equalTo: passwordTextField.bottomAnchor).isActive = true

        passwordSeparatorView.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true

        passwordSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true

        

        //성별

        genderSegmentControl.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor, constant: 12).isActive = true

        genderSegmentControl.topAnchor.constraint(equalTo: passwordTextField.bottomAnchor, constant: 0).isActive = true

        genderSegmentControl.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor, constant: 0).isActive = true

        genderSegmentControlHeightAnchor = genderSegmentControl.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/5)

        genderSegmentControlHeightAnchor?.isActive = true

        

        //성별 구분선

        genderSeperatorView.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true

        genderSeperatorView.topAnchor.constraint(equalTo: genderSegmentControl.bottomAnchor).isActive = true

        genderSeperatorView.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true

        genderSeperatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true

        

        //나이

        ageTextField.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor, constant: 12).isActive = true

        ageTextField.topAnchor.constraint(equalTo: genderSegmentControl.bottomAnchor, constant: 0).isActive = true

        ageTextField.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor, constant: 0).isActive = true

        ageTextFieldHeightAnchor = ageTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/5)

        ageTextFieldHeightAnchor?.isActive = true

        

    }

    

    //로그인버튼 제약 조건 설정

    func setupLoginRegisterButton(){

        loginRegisterButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        loginRegisterButton.topAnchor.constraint(equalTo: inputsContainerView.bottomAnchor, constant: 12).isActive = true

        loginRegisterButton.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true

        loginRegisterButton.heightAnchor.constraint(equalToConstant: 30).isActive = true

    }

    

    //프로필 이미지 제약 조건 설정

    func setupProfileImageView(){

        profileImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        profileImageView.bottomAnchor.constraint(equalTo: loginRegisterSegmentedControl.topAnchor, constant: -75).isActive = true

        profileImageView.widthAnchor.constraint(equalToConstant: 60).isActive = true

        profileImageView.heightAnchor.constraint(equalToConstant: 60).isActive = true

    }

    

    

}


extension UIColor {

    

    convenience init(r: CGFloat, g: CGFloat, b: CGFloat) {

        self.init(red: r/255, green: g/255, blue: b/255, alpha: 1)

    }

}


//바탕화면 텝 했을 때 키보드 숨기기

extension UIViewController

{

    func hideKeyboard()

    {

        let tap: UITapGestureRecognizer = UITapGestureRecognizer(

            target: self,

            action: #selector(UIViewController.dismissKeyboard))

        

        view.addGestureRecognizer(tap)

    }

    

    @objc func dismissKeyboard()

    {

        view.endEditing(true)

    }

}


LoginController+handlers.swift



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

//


import UIKit

import Firebase


extension LoginController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    

    //등록 버튼 액션

    func handleRegister(){

        

        if(picCheck){

            //유효성 검사

            guard let email = emailTextField.text, let password = passwordTextField.text, let name = nameTextField.text,let gender = genderSegmentControl.text, let age = ageTextField.text else {

                

                

                //유효성 검사 해주기

                print("값이 없거나 잘못된 형식")

                return

            }

            //파이어베이스 가입

            Auth.auth().createUser(withEmail: email, password: password) { (user, error) in

                //에러 발생

                if let error = error{

                    if let errCode = AuthErrorCode(rawValue: error._code) {

                        switch errCode {

                        case .invalidEmail:

                            let alert = UIAlertController(title: "경고 ", message:"이메일 형식이 아닌것 같음..", preferredStyle: UIAlertControllerStyle.alert)

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

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

                        case .wrongPassword :

                            let alert = UIAlertController(title: "경고 ", message:"비밀번호 확인 ㄱㄱ", preferredStyle: UIAlertControllerStyle.alert)

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

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

                        case .accountExistsWithDifferentCredential :

                            let alert = UIAlertController(title: "경고 ", message:"이메일을 확인좀..", preferredStyle: UIAlertControllerStyle.alert)

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

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

                        case .userNotFound :

                            let alert = UIAlertController(title: "경고 ", message:"존재하지 않는 이메일이여", preferredStyle: UIAlertControllerStyle.alert)

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

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

                        default:

                            let alert = UIAlertController(title: "경고 ", message:"빈칸없는지 다시바바ㅠㅠ", preferredStyle: UIAlertControllerStyle.alert)

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

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

                        }

                    }

                    return

                }

                //가입후 uid  넘겨준다. uid 가 nil이면 return

                guard let uid = user?.uid else {

                    return

                }

                

                //유저 가입 성공후

                //유일한 스트링 값

                let imageName = NSUUID().uuidString

                //firebase 저장소 위치 가져오기

                let storageRef = Storage.storage().reference().child("profile_images").child("\(imageName).jpg")

                //image 파일 변환

                

                //더 안전하게

                if let profileImage = self.profileImageView.image, let uploadData = UIImageJPEGRepresentation(profileImage, 0.1){

                    

                    //업로드

                    storageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in

                        if let error = error {

                            print(error)

                            return

                        }

                        //이미지가 저장된 url 가져온 후 users db에 삽입

                        if let profileImageUrl = metadata?.downloadURL()?.absoluteString {

                            

                            let values = ["name": name, "email": email, "profileImageUrl": profileImageUrl,"gender":gender,"age":age]

                            //최종 저장 함수 호출(데이터 넘겨줌)

                            self.registerUserIntoDatabaseWithUID(uid, values: values as [String : AnyObject])

                        }

                    })

                }

            }

        }else{

            

            let alert = UIAlertController(title: "경고 ", message:"맨위에 바바 사진넣어야됨...", preferredStyle: UIAlertControllerStyle.alert)

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

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

        }

        

        

    }

    //최종적으로 유저 저장

    fileprivate func registerUserIntoDatabaseWithUID(_ uid: String, values: [String: AnyObject]) {

        let ref = Database.database().reference()

        let usersReference = ref.child("users").child(uid)

        //최종 저장

        usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in

            

            if let err = err {

                print(err)

                return

            }

            

            let user = User(dic:values)

            //등록 할때 메시지 컨트롤러에 있는 setupnavbar 함수 호출

            self.messagesController?.setupNavBarWithUser(user: user)

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

        })

        

        picCheck = false

    }

    

    

    //프로필 이미지 클릭했을 때 실행되는 이벤트 함수

    @objc func handleSelectProfileImageView(){

        

        let picker = UIImagePickerController()

        picker.delegate = self

        picker.allowsEditing = true

        

        present(picker, animated: true, completion: nil)

    }

    

    

    //이미지 피커 선택 완료

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

        var selectedImageFromPicker: UIImage?

        

        if let editedImage = info["UIImagePickerControllerEditedImage"] as? UIImage {

            selectedImageFromPicker = editedImage

        } else if let originalImage = info["UIImagePickerControllerOriginalImage"] as? UIImage {

            

            selectedImageFromPicker = originalImage

        }

        

        if let selectedImage = selectedImageFromPicker {

            profileImageView.image = selectedImage

            picCheck = true

        }

        

        dismiss(animated: true, completion: nil)

    }

    

    

    //이미지 피커 취소

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {

        dismiss(animated: true, completion: nil)

    }

    

}



mainviewcontroller.swift

//

//  MainViewController.swift

//  DatingApp

//

//  Created by MacBookPro on 2018. 5. 15..

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

//


import UIKit

import Firebase

class MainViewController: UIViewController {


    var ref: DatabaseReference!

    var mainViewController: MainViewController?

    //진입점

    override func viewDidLoad() {

        super.viewDidLoad()

        

        navigationItem.leftBarButtonItem = UIBarButtonItem(title: "로그아웃", style: .plain, target:self , action: #selector(handleLogout))

        

        

        //로그인or로그아웃 체크

        checkIfUserIsLoggedIn()

        


        

    }


    //로그인or로그아웃 체크 함수

    func checkIfUserIsLoggedIn(){

        //로그아웃 되었을 때 실행

        if Auth.auth().currentUser?.uid == nil{

            perform(#selector(handleLogout), with: nil, afterDelay: 0)

        }else{

            

            //로그인 되었으면 네비게이션 타이틀의 제목을 유저 이름으로 지정해준다.

            fetchUserAndSetupNavBarTitle()

            

        }

    }

    

    func fetchUserAndSetupNavBarTitle(){

        //로그인 되었으면 네비게이션 타이틀의 제목을 유저 이름으로 지정해준다.

        guard let uid = Auth.auth().currentUser?.uid else{

            //uid가

            return

        }

        ref = Database.database().reference()

        ref.child("users").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in

            print("타이틀 바 표시 함수 호출 성공-")

            print(snapshot)

            if let dictionary = snapshot.value as? [String: AnyObject]{

                

                let user = User(dic: dictionary)

                self.setupNavBarWithUser(user: user)

                

            }

        }, withCancel: nil)

        

    }

    

    //네비게이션 타이틀 바 변경해주기

    func setupNavBarWithUser(user: User){


        print("사진있는 타이틀! 호출")

        let titleView = MyUIView()

        

        titleView.frame = CGRect(x:0, y:0, width: 100, height: 50)

        

        //이미지와 라벨을 담을 뷰 객체

        let containerView = UIView()

        containerView.translatesAutoresizingMaskIntoConstraints = false

        

        titleView.addSubview(containerView)

        

        //이미지 객체

        let profileImageView = UIImageView()

        profileImageView.translatesAutoresizingMaskIntoConstraints = false

        profileImageView.contentMode = .scaleAspectFill

        profileImageView.layer.cornerRadius = 20

        profileImageView.clipsToBounds = true

        

        if let profileImageUrl = user.profileImageUrl{

            profileImageView.loadImageUsingCacheWithUrlString(profileImageUrl)

        }

        containerView.addSubview(profileImageView)

        

        profileImageView.leftAnchor.constraint(equalTo: containerView.leftAnchor).isActive = true

        profileImageView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true

        profileImageView.widthAnchor.constraint(equalToConstant: 35).isActive = true

        profileImageView.heightAnchor.constraint(equalToConstant: 35).isActive = true

        

        let nameLable = UILabel()

        containerView.addSubview(nameLable)

        

        nameLable.text = user.name

        nameLable.translatesAutoresizingMaskIntoConstraints = false

        nameLable.leftAnchor.constraint(equalTo: profileImageView.rightAnchor, constant: 8).isActive = true

        nameLable.centerYAnchor.constraint(equalTo: profileImageView.centerYAnchor).isActive = true

        nameLable.rightAnchor.constraint(equalTo: containerView.rightAnchor).isActive = true

        nameLable.heightAnchor.constraint(equalTo: profileImageView.heightAnchor).isActive = true

        //nameLable.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(showChatController)))

        

        containerView.centerXAnchor.constraint(equalTo: titleView.centerXAnchor).isActive = true

        containerView.centerYAnchor.constraint(equalTo: titleView.centerYAnchor).isActive = true

        self.navigationItem.titleView = titleView

        

    }

    

    //로그아웃 액션

    @objc func handleLogout(){

        

        do{

            try Auth.auth().signOut()

        } catch let logError{

            print(logError)

        }

        

        mainViewController?.fetchUserAndSetupNavBarTitle()

        

        let loginController = LoginController()

        

        present(loginController, animated: true, completion: nil)

    }

}



myuiview.swift

import UIKit


class MyUIView: UIView {

    

    override var intrinsicContentSize: CGSize {

        return UILayoutFittingExpandedSize

    }

    

}



Extensions.swift

//

//  Extensions.swift

//  DatingApp

//

// 

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

//


import UIKit


let imageCache = NSCache<NSString, AnyObject>()


extension UIImageView{

    

    //새 메시지 보내기 테이블 뷰에서 호출하는 이미지 캐쉬 함수

    func loadImageUsingCacheWithUrlString(_ urlString: String) {

         self.image = nil

        

        //이미지 캐쉬가 있는지 확인 후 있으면 return

        if let cachedImage = imageCache.object(forKey: urlString as NSString) as? UIImage {

            self.image = cachedImage

            return

        }

        

        //이미지 캐치가 없으면 다운로드

        let url = URL(string: urlString)

        URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in

            

            //다운로드 중 에러발생, 종료

            if let error = error {

                print(error)

                return

            }

            

            DispatchQueue.main.async(execute: {

                //이미지 캐쉬에 넣기

                if let downloadedImage = UIImage(data: data!) {

                    imageCache.setObject(downloadedImage, forKey: urlString as NSString)

                    self.image = downloadedImage

                }

            })

            

        }).resume()

    }

    

}



//

//  User.swift

//  DatingApp

//

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

//


import UIKit


class User: NSObject {

    

    var name : String?

    var email : String?

    var profileImageUrl: String?

    var id : String?

    init(dic:[String:Any]){

        self.name = dic["name"] as? String ?? ""

        self.email = dic["email"] as? String ?? ""

         self.profileImageUrl = dic["profileImageUrl"] as? String

        self.id = dic["id"] as? String

        

    }

    

}




'ios 뽀개기 > 실전' 카테고리의 다른 글

ios 실전 앱 만들기 : 어떤 앱이 만들어 질까  (0) 2018.05.15
instagram like  (0) 2018.03.06
alert 커스텀 슬라이더  (0) 2018.01.03
alert 커스텀 - 이미지  (0) 2018.01.03
alert 커스텀 - 지도 2  (0) 2018.01.03
alert 커스텀 - 지도1  (0) 2018.01.03
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        let uid = FIRAuth.auth()!.currentUser!.uid
        let ref = FIRDatabase.database().reference()
        let key = ref.child("users").childByAutoId().key
        
        var isFollower = false
        
        ref.child("users").child(uid).child("following").queryOrderedByKey().observeSingleEvent(of: .value, with: { snapshot in
        
            if let following = snapshot.value as? [String : AnyObject] {
                for (ke, value) in following {
                    if value as! String == self.user[indexPath.row].userID {
                        isFollower = true
                        
                        ref.child("users").child(uid).child("following/\(ke)").removeValue()
                        ref.child("users").child(self.user[indexPath.row].userID).child("followers/\(ke)").removeValue()
                        
                        self.tableview.cellForRow(at: indexPath)?.accessoryType = .none
                    }
                }
            }
            if !isFollower {
                let following = ["following/\(key)" : self.user[indexPath.row].userID]
                let followers = ["followers/\(key)" : uid]
                
                ref.child("users").child(uid).updateChildValues(following)
                ref.child("users").child(self.user[indexPath.row].userID).updateChildValues(followers)
                
                self.tableview.cellForRow(at: indexPath)?.accessoryType = .checkmark
            }
        })
        ref.removeAllObservers()
        
    }
    
    
    func checkFollowing(indexPath: IndexPath) {
        let uid = FIRAuth.auth()!.currentUser!.uid
        let ref = FIRDatabase.database().reference()
        
        ref.child("users").child(uid).child("following").queryOrderedByKey().observeSingleEvent(of: .value, with: { snapshot in
            
            if let following = snapshot.value as? [String : AnyObject] {
                for (_, value) in following {
                    if value as! String == self.user[indexPath.row].userID {
                        self.tableview.cellForRow(at: indexPath)?.accessoryType = .checkmark
                    }
                }
            }
        })
        ref.removeAllObservers()
        
    }
cs


'ios 뽀개기 > 실전' 카테고리의 다른 글

ios 실전 앱 만들기 : 어떤 앱이 만들어 질까  (0) 2018.05.15
instagram like  (0) 2018.03.06
alert 커스텀 슬라이더  (0) 2018.01.03
alert 커스텀 - 이미지  (0) 2018.01.03
alert 커스텀 - 지도 2  (0) 2018.01.03
alert 커스텀 - 지도1  (0) 2018.01.03

alert 커스텀 슬라이더



//

//  ViewController.swift

//  AlertCustom1

//

//  Created by MacBookPro on 2018. 1. 3..

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

//


import UIKit


class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        

        //버튼 객체 만들기

        let btn = UIButton(type:.system)

        btn.frame =  CGRect(x:50, y:50 , width: 200, height: 100)

        btn.center = CGPoint(x:self.view.frame.width / 2, y: self.view.frame.height / 2)

        btn.setTitle("alert", for: UIControlState.normal)

        btn.backgroundColor = UIColor.brown

        btn.layer.borderColor = UIColor.blue.cgColor

        btn.layer.borderWidth = 4

        

        self.view.addSubview(btn)

        

        btn.addTarget(self, action: #selector(alertAction(_:)), for: .touchUpInside)

        

    }


    @objc func alertAction(_ sender:Any){

        

        //컨텐트 뷰 영역에 들어갈 컨트롤러를 생성하고, 알림창에 등록한다.

        let contentVC = ControlViewController()

        

        

        //1. 알림창을 경고 형식으로 정의 한다.

        let alert = UIAlertController(title: nil, message: "이글의 평점은 다음과 같습니다",preferredStyle: .alert)

        

        // 뷰 컨트롤러 알림창의 콘텐츠 뷰 컨트롤러 속성에 등록한다.

        alert.setValue(contentVC, forKeyPath: "contentViewController")

        

        

        //2. 버튼을 정의 한다.

        // OK 버튼을 추가한다.

        let okAction = UIAlertAction(title: "OK", style: .default) { (_) in

            print(">>> sliderValue = \(contentVC.sliderValue)")

        }

        

        //3. 정의된 버튼을 알림창 객체에 추가한다.

        alert.addAction(okAction)

        

        //4. 알림창을 화면에 표시한다.

        self.present(alert, animated: false)

        


    }



}




//

//  ContentViewController.swift

//  AlertCustom1

//

//  Created by MacBookPro on 2018. 1. 3..

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

//


import UIKit


class ControlViewController: UIViewController {


    //외부에서 객체를 참조하기 위해서 빼 놨음

    let slider = UISlider()

    

    //슬라이더 객체의 값을 읽어 반환하는 역할로 정의된 연산 프로퍼티

    //읽기전용이라서 set 생략가능,

    var sliderValue: Float {

        

        return self.slider.value

    }

    

    override func viewDidLoad() {

        

        self.slider.minimumValue = 0

        self.slider.maximumValue = 100

        

        

        //슬라이더 영역과 크기 , 루트 뷰에 추가

        self.slider.frame = CGRect(x:0,y:0,width:170, height:30)

        self.view.addSubview(self.slider)

        

        //뷰 컨트롤러의 콘텐츠 사이즈를 지정해준다.

        self.preferredContentSize = CGSize(width: self.slider.frame.width, height: self.slider.frame.height + 10)

    }



}


'ios 뽀개기 > 실전' 카테고리의 다른 글

ios 실전 앱 만들기 : 어떤 앱이 만들어 질까  (0) 2018.05.15
instagram like  (0) 2018.03.06
alert 커스텀 슬라이더  (0) 2018.01.03
alert 커스텀 - 이미지  (0) 2018.01.03
alert 커스텀 - 지도 2  (0) 2018.01.03
alert 커스텀 - 지도1  (0) 2018.01.03

alert 커스텀 - 이미지


//

//  ViewController.swift

//  AlertCustom1

//

//  Created by MacBookPro on 2018. 1. 3..

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

//


import UIKit

import MapKit

class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        

        //버튼 객체 만들기

        let btn = UIButton(type:.system)

        btn.frame =  CGRect(x:50, y:50 , width: 200, height: 100)

        btn.center = CGPoint(x:self.view.frame.width / 2, y: self.view.frame.height / 2)

        btn.setTitle("alert", for: UIControlState.normal)

        btn.backgroundColor = UIColor.brown

        btn.layer.borderColor = UIColor.blue.cgColor

        btn.layer.borderWidth = 4

        

        self.view.addSubview(btn)

        

        btn.addTarget(self, action: #selector(alertAction(_:)), for: .touchUpInside)

        

    }


    @objc func alertAction(_ sender:Any){

        

        //1. 알림창을 경고 형식으로 정의 한다.

        let alert = UIAlertController(title: nil, message: "이글의 평점은 다음과 같습니다",preferredStyle: .alert)

        

        //2. 버튼을 정의 한다.

        let okAction = UIAlertAction(title: "ok", style: .default)

        

        //3. 정의된 버튼을 알림창 객체에 추가한다.

        alert.addAction(okAction)

 

    

        //컨텐트 뷰 영역에 들어갈 컨트롤러를 생성하고, 알림창에 등록한다.

        let contentVC = ImageViewController()

        

       

        // 뷰 컨트롤러 알림창의 콘텐츠 뷰 컨트롤러 속성에 등록한다.

        alert.setValue(contentVC, forKeyPath: "contentViewController")

        

        

        //4. 알림창을 화면에 표시한다.

        self.present(alert, animated: false)

        

        

        


        

    }



}





//

//  MapKitViewController.swift

//  AlertCustom1

//

//  Created by MacBookPro on 2018. 1. 3..

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

//


import UIKit


class ImageViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        

        //1.이미지와 이미지 뷰 객체 생성

        let icon = UIImage(named: "rating5") //실제 이미지를 저장하는 객체

        let iconV = UIImageView(image:icon) // 이미지 객체를 이용해서 화면에 표시하는 뷰의 일종

        

        //2. 이미지 뷰의 영역과 위치를 지정

        iconV.frame = CGRect(x:0, y:0, width:(icon?.size.width)!,height:(icon?.size.height)!)

        

        //3. 루트뷰에 이미지 뷰를 추가

        self.view.addSubview(iconV)

        

        //preferredContentSize 속성을 통해 외부 객체가 ImageViewController를 나타낼 때 참고할 사이즈 지정

        //4.  외부에서 참조할 뷰 컨트롤러 사이즈를 이미지 크기와 동일하게 설정 + 10은 알림창에 이미지가 표시될때 아래 여백 주기

        self.preferredContentSize = CGSize(width:(icon?.size.width)!,height:(icon?.size.height)!+10)

        

    }



}


'ios 뽀개기 > 실전' 카테고리의 다른 글

instagram like  (0) 2018.03.06
alert 커스텀 슬라이더  (0) 2018.01.03
alert 커스텀 - 이미지  (0) 2018.01.03
alert 커스텀 - 지도 2  (0) 2018.01.03
alert 커스텀 - 지도1  (0) 2018.01.03
alert 커스텀 - 기본  (0) 2018.01.03

alert 커스텀 - 지도 2





//

//  ViewController.swift

//  AlertCustom1

//

//  Created by MacBookPro on 2018. 1. 3..

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

//


import UIKit

import MapKit

class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        

        //버튼 객체 만들기

        let btn = UIButton(type:.system)

        btn.frame =  CGRect(x:50, y:50 , width: 200, height: 100)

        btn.center = CGPoint(x:self.view.frame.width / 2, y: self.view.frame.height / 2)

        btn.setTitle("alert", for: UIControlState.normal)

        btn.backgroundColor = UIColor.brown

        btn.layer.borderColor = UIColor.blue.cgColor

        btn.layer.borderWidth = 4

        

        self.view.addSubview(btn)

        

        btn.addTarget(self, action: #selector(alertAction(_:)), for: .touchUpInside)

        

    }


    @objc func alertAction(_ sender:Any){

        

        //1. 알림창을 경고 형식으로 정의 한다.

        let alert = UIAlertController(title: nil, message: "여기가 맞나요?",preferredStyle: .alert)

        

        //2. 버튼을 정의 한다.

        let okAction = UIAlertAction(title: "ok", style: .default)

        let cancel = UIAlertAction(title: "cancel", style: .cancel)

        

        //3. 정의된 버튼을 알림창 객체에 추가한다.

        alert.addAction(okAction)

        alert.addAction(cancel)

        

        

        //4. 알림창을 화면에 표시한다.

        self.present(alert, animated: false)

        

        

        

        //컨텐트 뷰 영역에 들어갈 컨트롤러를 생성하고, 알림창에 등록한다.

        let contentVC = MapKitViewController()

        

        

       

        // 뷰 컨트롤러 알림창의 콘텐츠 뷰 컨트롤러 속성에 등록한다.

        alert.setValue(contentVC, forKeyPath: "contentViewController")

        

        



        

    }



}






//

//  MapKitViewController.swift

//  AlertCustom1

//

//  Created by MacBookPro on 2018. 1. 3..

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

//


import UIKit

import  MapKit

class MapKitViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()


        //뷰 컨트롤러에 맵킷 뷰를 추가한다.

        

        let mapkitView = MKMapView(frame: CGRect(x:0, y:0 , width: 0, height: 0))

        //맵킷뷰를 루트 뷰로 정했다. 그래서 위에 위치와 높이 넓이 값을 0으로 맞췄다.

        self.view = mapkitView

        // 이 값은 외부(알림창)에서 뷰 컨트롤러를 읽어 들일 때 참고하는 사이즈

        //알림창은 contentVC 객체의 정보를 읽어 들일 때 preferredContentSize 속성을 참고하여

        //표현해야할 크기가 얼마인지 계산한다.

        //이 속성의 높이 값이 200으로 주어져 있으므로 콘텐츠 영역에도 200만큼의 높이가 할당된다.

        self.preferredContentSize.height = 200

        

        

        //1 위치 정보를 설정한다.

        let pos = CLLocationCoordinate2D(latitude:37.5593582, longitude:126.95928759999993)

        

        //2. 지도에서 보여줄 넓이 // 일종의 축적// 숫자가 작을 수록 좁은 범위를 확대 시켜 보여 준다.

        let span = MKCoordinateSpan(latitudeDelta:0.005, longitudeDelta:0.005)

        

        //3. 지도 영역을 정의

        let region = MKCoordinateRegion(center:pos, span:span)

        //4 지도 뷰에 표시

        mapkitView.region = region

        mapkitView.regionThatFits(region)

        

        //5 위치를 핀으로 표시

        let point = MKPointAnnotation()

        point.coordinate = pos

        mapkitView.addAnnotation(point)

        

        

        

        

    }



}


'ios 뽀개기 > 실전' 카테고리의 다른 글

alert 커스텀 슬라이더  (0) 2018.01.03
alert 커스텀 - 이미지  (0) 2018.01.03
alert 커스텀 - 지도 2  (0) 2018.01.03
alert 커스텀 - 지도1  (0) 2018.01.03
alert 커스텀 - 기본  (0) 2018.01.03
메모장 - 커스텀(x)  (0) 2018.01.03

//



//  ViewController.swift

//  AlertCustom1

//

//  Created by MacBookPro on 2018. 1. 3..

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

//


import UIKit

import MapKit

class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        

        //버튼 객체 만들기

        let btn = UIButton(type:.system)

        btn.frame =  CGRect(x:50, y:50 , width: 200, height: 100)

        btn.center = CGPoint(x:self.view.frame.width / 2, y: self.view.frame.height / 2)

        btn.setTitle("alert", for: UIControlState.normal)

        btn.backgroundColor = UIColor.brown

        btn.layer.borderColor = UIColor.blue.cgColor

        btn.layer.borderWidth = 4

        

        self.view.addSubview(btn)

        

        btn.addTarget(self, action: #selector(alertAction(_:)), for: .touchUpInside)

        

    }


    @objc func alertAction(_ sender:Any){

        

        //1. 알림창을 경고 형식으로 정의 한다.

        let alert = UIAlertController(title: nil, message: "여기가 맞나요?",preferredStyle: .alert)

        

        //2. 버튼을 정의 한다.

        let okAction = UIAlertAction(title: "ok", style: .default)

        let cancel = UIAlertAction(title: "cancel", style: .cancel)

        

        //3. 정의된 버튼을 알림창 객체에 추가한다.

        alert.addAction(okAction)

        alert.addAction(cancel)

        

        

        //4. 알림창을 화면에 표시한다.

        self.present(alert, animated: false)

        

        

        

        //컨텐트 뷰 영역에 들어갈 컨트롤러를 생성하고, 알림창에 등록한다.

        let contentVC = UIViewController()

        

        

        //뷰 컨트롤러에 맵킷 뷰를 추가한다.

        

        let mapkitView = MKMapView(frame: CGRect(x:0, y:0 , width: 0, height: 0))

        //맵킷뷰를 루트 뷰로 정했다. 그래서 위에 위치와 높이 넓이 값을 0으로 맞췄다.

        contentVC.view = mapkitView

        // 이 값은 외부(알림창)에서 뷰 컨트롤러를 읽어 들일 때 참고하는 사이즈

        //알림창은 contentVC 객체의 정보를 읽어 들일 때 preferredContentSize 속성을 참고하여

        //표현해야할 크기가 얼마인지 계산한다.

        //이 속성의 높이 값이 200으로 주어져 있으므로 콘텐츠 영역에도 200만큼의 높이가 할당된다.

        contentVC.preferredContentSize.height = 200

        

        

        //1 위치 정보를 설정한다.

        let pos = CLLocationCoordinate2D(latitude:37.5593582, longitude:126.95928759999993)

        

        //2. 지도에서 보여줄 넓이 // 일종의 축적// 숫자가 작을 수록 좁은 범위를 확대 시켜 보여 준다.

        let span = MKCoordinateSpan(latitudeDelta:0.005, longitudeDelta:0.005)

        

        //3. 지도 영역을 정의

        let region = MKCoordinateRegion(center:pos, span:span)

        //4 지도 뷰에 표시

        mapkitView.region = region

        mapkitView.regionThatFits(region)

        

        //5 위치를 핀으로 표시

        let point = MKPointAnnotation()

        point.coordinate = pos

        mapkitView.addAnnotation(point)

        

        // 뷰 컨트롤러 알림창의 콘텐츠 뷰 컨트롤러 속성에 등록한다.

        alert.setValue(contentVC, forKeyPath: "contentViewController")

        

        

        

        //let lb = UILabel()

        //lb.frame = CGRect(x:50, y:50 , width: 60, height: 20)

        //lb.center  = CGPoint(x:self.view.frame.width / 2, y: self.view.frame.height / 2)

        //lb.text = "안녕하소"

        //lb.textColor = UIColor.black

        //v.view.addSubview(lb)

        //v.view.layer.borderColor = UIColor.blue.cgColor

        

        


        

 


        

    }



}



'ios 뽀개기 > 실전' 카테고리의 다른 글

alert 커스텀 - 이미지  (0) 2018.01.03
alert 커스텀 - 지도 2  (0) 2018.01.03
alert 커스텀 - 지도1  (0) 2018.01.03
alert 커스텀 - 기본  (0) 2018.01.03
메모장 - 커스텀(x)  (0) 2018.01.03
커스텀 내비게이션 바  (0) 2018.01.03

alert 커스텀




//

//  ViewController.swift

//  AlertCustom1

//

//  Created by MacBookPro on 2018. 1. 3..

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

//


import UIKit


class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        

        //버튼 객체 만들기

        let btn = UIButton(type:.system)

        btn.frame =  CGRect(x:50, y:50 , width: 200, height: 100)

        btn.center = CGPoint(x:self.view.frame.width / 2, y: self.view.frame.height / 2)

        btn.setTitle("alert", for: UIControlState.normal)

        btn.backgroundColor = UIColor.brown

        btn.layer.borderColor = UIColor.blue.cgColor

        btn.layer.borderWidth = 4

        

        self.view.addSubview(btn)

        

        btn.addTarget(self, action: #selector(alertAction(_:)), for: .touchUpInside)

        

    }


    @objc func alertAction(_ sender:Any){

        

        //1. 알림창을 경고 형식으로 정의 한다.

        let alert = UIAlertController(title: nil, message: nil,preferredStyle: .alert)

        

        //2. 버튼을 정의 한다.

        let okAction = UIAlertAction(title: "ok", style: .default)

        let cancel = UIAlertAction(title: "cancel", style: .cancel)

        

        //3. 정의된 버튼을 알림창 객체에 추가한다.

        alert.addAction(okAction)

        alert.addAction(cancel)

        

        //UIViewController() 를 상속받은 어떠한 객체를 이용해서라도 커스터마이징 할 수 있다.

        //추가된 코드 - 알림창에 들어갈 뷰 컨트롤러

        let v = UIViewController()

        let lb = UILabel()

        lb.frame = CGRect(x:50, y:50 , width: 60, height: 20)

        //lb.center  = CGPoint(x:self.view.frame.width / 2, y: self.view.frame.height / 2)

        lb.text = "안녕하소"

        lb.textColor = UIColor.black

        v.view.addSubview(lb)

        v.view.layer.borderColor = UIColor.blue.cgColor

        

        

        

        alert.setValue(v, forKeyPath: "contentViewController")

        

        //4. 알림창을 화면에 표시한다.

        self.present(alert, animated: false)

        

        

        

        

        //기본 구문!

        //alert 객체에 contentView를 넣을 수 있다.!!

        //let v = UIViewController()

        //alert.setValue(v, forKey: "contentViewController")

        

    }



}










'ios 뽀개기 > 실전' 카테고리의 다른 글

alert 커스텀 - 지도 2  (0) 2018.01.03
alert 커스텀 - 지도1  (0) 2018.01.03
alert 커스텀 - 기본  (0) 2018.01.03
메모장 - 커스텀(x)  (0) 2018.01.03
커스텀 내비게이션 바  (0) 2018.01.03
탭바 커스텀하기  (0) 2018.01.02

메모장 - 커스텀(x)


//


//  AppDelegate.swift

//  Real

//

//  Created by MacBookPro on 2017. 12. 29..

//  Copyright © 2017년 MacBookPro. All rights reserved.

//


import UIKit

import CoreData


@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {


    var window: UIWindow?

    

    //접근성과 일관성 데이터 보존의 이유로 이곳에 작성

    var memolist = [MemoData]() //메모 데이터를 저장할 배열 변수 - 여러개의 메모를 목록형식으로 저장할 것임

    

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

        // Override point for customization after application launch.

        return true

    }


    func applicationWillResignActive(_ application: UIApplication) {

        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.

        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.

    }


    func applicationDidEnterBackground(_ application: UIApplication) {

        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.

        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

    }


    func applicationWillEnterForeground(_ application: UIApplication) {

        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.

    }


    func applicationDidBecomeActive(_ application: UIApplication) {

        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

    }


    func applicationWillTerminate(_ application: UIApplication) {

        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.

        // Saves changes in the application's managed object context before the application terminates.

        self.saveContext()

    }


    // MARK: - Core Data stack


    lazy var persistentContainer: NSPersistentContainer = {

        /*

         The persistent container for the application. This implementation

         creates and returns a container, having loaded the store for the

         application to it. This property is optional since there are legitimate

         error conditions that could cause the creation of the store to fail.

        */

        let container = NSPersistentContainer(name: "Real")

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in

            if let error = error as NSError? {

                // Replace this implementation with code to handle the error appropriately.

                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                 

                /*

                 Typical reasons for an error here include:

                 * The parent directory does not exist, cannot be created, or disallows writing.

                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.

                 * The device is out of space.

                 * The store could not be migrated to the current model version.

                 Check the error message to determine what the actual problem was.

                 */

                fatalError("Unresolved error \(error), \(error.userInfo)")

            }

        })

        return container

    }()


    // MARK: - Core Data Saving support


    func saveContext () {

        let context = persistentContainer.viewContext

        if context.hasChanges {

            do {

                try context.save()

            } catch {

                // Replace this implementation with code to handle the error appropriately.

                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                let nserror = error as NSError

                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")

            }

        }

    }


}



//

//  MemoData.swift

//  Real

//

//  Created by MacBookPro on 2017. 12. 29..

//  Copyright © 2017년 MacBookPro. All rights reserved.

//


import Foundation

import UIKit


class MemoData  {

    

    var memoIdx : Int? //데이터 식별값

    var title : String? //제목

    var contents : String? //내용

    var image : UIImage? //이미지

    var regdate: Date? //작성일

    

}




//

//  MemoCell.swift

//  Real

//

//  Created by MacBookPro on 2017. 12. 29..

//  Copyright © 2017년 MacBookPro. All rights reserved.

//


import UIKit


class MemoCell: UITableViewCell {


   

    @IBOutlet var subject: UILabel! //메모 제목

    

    @IBOutlet var contents: UILabel! // 메모 내용

    

    @IBOutlet var regdate: UILabel! // 등록 일자

    

    @IBOutlet var img: UIImageView! // 이미지

    

}


//

//  MemoFormVC.swift

//  Real

//

//  Created by MacBookPro on 2017. 12. 29..

//  Copyright © 2017년 MacBookPro. All rights reserved.

//


import UIKit


class MemoFormVC: UIViewController,UIImagePickerControllerDelegate, UINavigationControllerDelegate,UITextViewDelegate {

    var subject: String! //제목을 저장하는 역할

    @IBOutlet var contents: UITextView!

    @IBOutlet var preview: UIImageView!


    func textViewDidChange(_ textView: UITextView) {

        //내용의 최대 15자리 까지 읽어 subject변수에 저장한다.

        let contents = textView.text as NSString

        let length = ((contents.length > 15) ? 15 : contents.length)

        self.subject = contents.substring(with: NSRange(location:0, length: length))

        self.navigationItem.title = subject

    }

    

    

    

    override func viewDidLoad() {

        super.viewDidLoad()


        self.contents.delegate = self

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

    

    //저장

    @IBAction func save(_ sender: Any) {

        

        

        //내용을 입력하지 않았을 경우, 경고한다.

        

        guard self.contents.text?.isEmpty == false else{

            

            let alert = UIAlertController(title:nil,

                                          message:"내용을 입력해주세요",

                                          preferredStyle:.alert)

            alert.addAction(UIAlertAction(title:"ok",style:.default, handler:nil))

            self.present(alert,animated: true)

            return

            

        }

        

        //메모 데이터에 저장

        let data = MemoData()

        data.title = self.subject

        data.contents = self.contents.text

        data.image = self.preview.image

        data.regdate = Date()

        

        let appDelegate = UIApplication.shared.delegate as! AppDelegate

        appDelegate.memolist.append(data)

        

        _ = self.navigationController?.popViewController(animated: true)

        

        

    }

    

    //사진 가져오기

    @IBAction func pick(_ sender: Any) {

    //이미지 피커 인스턴스 생성

    let picker = UIImagePickerController()

    //이미지 피커 컨트롤러 인스턴스의 델리게이트 속성을 현재의 뷰 컨트롤러 인스턴스로 설정

    picker.delegate = self

    //이미지 편집 허용

    picker.allowsEditing = true

    //이미지 피커 화면을 표시한다

    self.present(picker, animated: false)

    }

    //이미지 선택을 완료했을 때 호출되는 메소드

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

        //선택된 이미지를 미리보기에 표시

        self.preview.image = info[UIImagePickerControllerEditedImage] as? UIImage

        //이미지 피커 컨트롤러를 닫는다.

        picker.dismiss(animated: false)

    }

    

}


//

//  MemoListVC.swift

//  Real

//

//  Created by MacBookPro on 2017. 12. 29..

//  Copyright © 2017년 MacBookPro. All rights reserved.

//


import UIKit


class MemoListVC: UITableViewController {

    

    //앱델리게이트 객체의 참조 정보를 읽어 온다.

    let appDelegate = UIApplication.shared.delegate as! AppDelegate

    

     //테이블 데이터를 다시 읽어들인다. 이에 따라 행을 구하는 로직이 다시 실행된다. / 해당뷰컨트롤러가 디바이스의 스크린에 출력될때마다 호출된다.

    override func viewWillAppear(_ animated: Bool) {

        // 다른 화면으로 이동했다가 목록으로 돌아왔을때,

        // 홈버튼을 눌러 앱이 백그라운드 모드로 내려간 후 다시 활성화되었을 때

        // 키타 상황으로 뷰 컨트롤러가 스크린에 표시될 때

       self.tableView.reloadData()

    }

    

    //테이블 행의 개수를 결정하는 메소드

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        let count = self.appDelegate.memolist.count

        return count

    }


   //테이블 행을 구성하는 메소드

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


        //1. memolist 배열 데이터에서 주어진 행에 맞는 데이터를 꺼낸다.

        let row = self.appDelegate.memolist[indexPath.row]

        

        //2. 이미지 속성이 비어 있을 경우 "memoCell" 아니면 "memoCellWidthImage"

        let cellId = row.image == nil ? "memoCell" : "memoCellWithImage"

        

        //3.재사용 큐로 부터 프로토타입 셀의 인스턴스를 전달 받는다.

        let cell = tableView.dequeueReusableCell(withIdentifier: cellId) as? MemoCell

        

        //4. memoCell의 내용을 구성한다.

        cell?.subject?.text = row.title

        cell?.contents?.text = row.contents

        cell?.img?.image = row.image

        

        //5. Date 타입의 날짜를 yyyy-MM-dd HH:mm:ss 포멧에 맞게 변경한다.

        let formatter = DateFormatter()

        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"

        cell?.regdate?.text = formatter.string(from: row.regdate!)

        

        return cell!

    }


    

    //테이블의 특정 행이 선택되었을 때 호출되는 메소드, 선택된 행의 정보는 indexpath에 담겨 있다.

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        

        //1. memoList 배열에서 선택된 행에 맞는 데이터를 꺼낸다.

        let row = self.appDelegate.memolist[indexPath.row]

        

        //2.상세 화면의 인스턴스를 생성한다.

        guard let vc = self.storyboard?.instantiateViewController(withIdentifier: "MemoRead") as? MemoReadVC else {

            return

        }

        //3.값을 전달한 다음, 상세화면으로 이동한다.

        vc.param = row

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

    }

    

    

    override func viewDidLoad() {

        super.viewDidLoad()

        

    }

    

    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }


}


//

//  MemoReadVC.swift

//  Real

//

//  Created by MacBookPro on 2017. 12. 29..

//  Copyright © 2017년 MacBookPro. All rights reserved.

//


import UIKit


class MemoReadVC: UIViewController {

    

    //콘텐츠 데이터를 저장하는 변수

    var param : MemoData?

    

    @IBOutlet var subject: UILabel!

    

    @IBOutlet var contents: UILabel!

    

    @IBOutlet var img: UIImageView!

    

    

    override func viewDidLoad() {

        super.viewDidLoad()

        

        self.subject.text = param?.title

        self.contents.text = param?.contents

        self.img.image = param?.image

        

        let formatter = DateFormatter()

        formatter.dateFormat = "dd일 HH:mm분에 작성됨"

        let dateString = formatter.string(from: (param?.regdate)!)

        

        self.navigationItem.title = dateString

        

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

    


}


//

//  MemoFormVC.swift

//  Real

//

//  Created by MacBookPro on 2017. 12. 29..

//  Copyright © 2017년 MacBookPro. All rights reserved.

//


import UIKit


class MemoFormVC: UIViewController,UIImagePickerControllerDelegate, UINavigationControllerDelegate,UITextViewDelegate {

    var subject: String! //제목을 저장하는 역할

    @IBOutlet var contents: UITextView!

    @IBOutlet var preview: UIImageView!


    func textViewDidChange(_ textView: UITextView) {

        //내용의 최대 15자리 까지 읽어 subject변수에 저장한다.

        let contents = textView.text as NSString

        let length = ((contents.length > 15) ? 15 : contents.length)

        self.subject = contents.substring(with: NSRange(location:0, length: length))

        self.navigationItem.title = subject

    }

    

    

    

    override func viewDidLoad() {

        super.viewDidLoad()


        self.contents.delegate = self

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

    

    //저장

    @IBAction func save(_ sender: Any) {

        

        

        //내용을 입력하지 않았을 경우, 경고한다.

        

        guard self.contents.text?.isEmpty == false else{

            

            let alert = UIAlertController(title:nil,

                                          message:"내용을 입력해주세요",

                                          preferredStyle:.alert)

            alert.addAction(UIAlertAction(title:"ok",style:.default, handler:nil))

            self.present(alert,animated: true)

            return

            

        }

        

        //메모 데이터에 저장

        let data = MemoData()

        data.title = self.subject

        data.contents = self.contents.text

        data.image = self.preview.image

        data.regdate = Date()

        

        let appDelegate = UIApplication.shared.delegate as! AppDelegate

        appDelegate.memolist.append(data)

        

        _ = self.navigationController?.popViewController(animated: true)

        

        

    }

    

    //사진 가져오기

    @IBAction func pick(_ sender: Any) {

    //이미지 피커 인스턴스 생성

    let picker = UIImagePickerController()

    //이미지 피커 컨트롤러 인스턴스의 델리게이트 속성을 현재의 뷰 컨트롤러 인스턴스로 설정

    picker.delegate = self

    //이미지 편집 허용

    picker.allowsEditing = true

    //이미지 피커 화면을 표시한다

    self.present(picker, animated: false)

    }

    //이미지 선택을 완료했을 때 호출되는 메소드

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

        //선택된 이미지를 미리보기에 표시

        self.preview.image = info[UIImagePickerControllerEditedImage] as? UIImage

        //이미지 피커 컨트롤러를 닫는다.

        picker.dismiss(animated: false)

    }

    

}



'ios 뽀개기 > 실전' 카테고리의 다른 글

alert 커스텀 - 지도1  (0) 2018.01.03
alert 커스텀 - 기본  (0) 2018.01.03
메모장 - 커스텀(x)  (0) 2018.01.03
커스텀 내비게이션 바  (0) 2018.01.03
탭바 커스텀하기  (0) 2018.01.02
커스텀 버튼 및 데이터 전달하기  (0) 2018.01.02

커스텀 내비게이션 바



//

//  AppDelegate.swift

//  NavCustom

//

//  Created by MacBookPro on 2018. 1. 2..

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

//


import UIKit

import CoreData


@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {


    var window: UIWindow?



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

        // Override point for customization after application launch.

        return true

    }


    func applicationWillResignActive(_ application: UIApplication) {

        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.

        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.

    }


    func applicationDidEnterBackground(_ application: UIApplication) {

        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.

        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

    }


    func applicationWillEnterForeground(_ application: UIApplication) {

        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.

    }


    func applicationDidBecomeActive(_ application: UIApplication) {

        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

    }


    func applicationWillTerminate(_ application: UIApplication) {

        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.

        // Saves changes in the application's managed object context before the application terminates.

        self.saveContext()

    }


    // MARK: - Core Data stack


    lazy var persistentContainer: NSPersistentContainer = {

        /*

         The persistent container for the application. This implementation

         creates and returns a container, having loaded the store for the

         application to it. This property is optional since there are legitimate

         error conditions that could cause the creation of the store to fail.

        */

        let container = NSPersistentContainer(name: "NavCustom")

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in

            if let error = error as NSError? {

                // Replace this implementation with code to handle the error appropriately.

                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                 

                /*

                 Typical reasons for an error here include:

                 * The parent directory does not exist, cannot be created, or disallows writing.

                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.

                 * The device is out of space.

                 * The store could not be migrated to the current model version.

                 Check the error message to determine what the actual problem was.

                 */

                fatalError("Unresolved error \(error), \(error.userInfo)")

            }

        })

        return container

    }()


    // MARK: - Core Data Saving support


    func saveContext () {

        let context = persistentContainer.viewContext

        if context.hasChanges {

            do {

                try context.save()

            } catch {

                // Replace this implementation with code to handle the error appropriately.

                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                let nserror = error as NSError

                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")

            }

        }

    }


}





//

//  ViewController.swift

//  NavCustom

//

//  Created by MacBookPro on 2018. 1. 2..

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

//

// 내비게이션 바는 내비게이션 컨트롤러 아래에 있다 (내비게이션 바는 모든 뷰 컨트롤러에 공통으로 적용된다.)

// 내비게이션 아이템은 개별적인 뷰 컨트롤러의 통제를 받는다.(각각의 뷰 컨트롤러 마다 독립적이다.)

// 내비게이션 바는 내비게이션 컨트롤러에 속한 객체이며, 내비게이션 아이템은 뷰 컨트롤러에 속한 객체이다.

// 그래서 내비게이션 아이템을 화면에 추가할 때에는 내비게이션 컨트롤러가 아니라 뷰 컨트롤러에 추가해야 한다. 참조할때도 역시 뷰 컨트롤러를 거쳐야 한다.

// 코코아 터치 프래임 워크는 titleView를 제공한다. 타입은 UIView (뷰를 상속받은 레이블이나 버튼, 이미지 뷰를 제약 없이 타이틀에 표현 가능하다.)

import UIKit


class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        //initTitle()

        //initTitleNew()

        //imag()

        initTitleInput()

        

        //일반적인 네비게이션 바 버튼 커스텀

        //let item = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(navItem))

        //self.navigationItem.leftBarButtonItem = item

    }


    //@objc func navItem(){

    //print("버튼이 눌렸어요")

    //}

    

    

    //1. - 레이블 객체를 이용해서 표현

    func initTitle(){

        let nTitle = UILabel(frame: CGRect(x:0, y:0, width: 200, height: 40))

        nTitle.numberOfLines = 2 //줄 수

        nTitle.textAlignment = .center  // 정렬

        nTitle.textColor = UIColor.white

        nTitle.font = UIFont.systemFont(ofSize: 15) //font 사이즈

        nTitle.text = "58개 숙소 \n 1박(1월 10일 ~ 1월 11일)"

        

        self.navigationItem.titleView = nTitle

    

        //배경색상 설정

        let color = UIColor(red:0.02, green:0.22, blue:0.49, alpha:1.0)

        self.navigationController?.navigationBar.barTintColor = color

    }


    

    //2. - 컨테이너 뷰 객체에 레이블 객체를 넣어서 표현

    func initTitleNew(){

        //복합적인 레이아웃을 구현할 컨테이너 뷰

        let containerView = UIView(frame:CGRect(x:0, y:0, width:200, height:36))

        

        //상단 레이블 설정

        let nTitle = UILabel(frame: CGRect(x:0, y:0, width: 200, height: 18))

        nTitle.numberOfLines = 1 //줄 수

        nTitle.textAlignment = .center  // 정렬

        nTitle.textColor = UIColor.white

        nTitle.font = UIFont.systemFont(ofSize: 15) //font 사이즈

        nTitle.text = "58개 숙소"

        

        //하단 레이블 설정

        let subTitle = UILabel(frame: CGRect(x:0, y:18, width: 200, height: 18))

        subTitle.numberOfLines = 1 //줄 수

        subTitle.textAlignment = .center  // 정렬

        subTitle.textColor = UIColor.white

        subTitle.font = UIFont.systemFont(ofSize: 12) //font 사이즈

        subTitle.text = "1박(1월 10일 ~ 1월 11일)"

        

        

        // 상하단 레이블을 컨테이너 뷰에 추가한다.

        containerView.addSubview(nTitle)

        containerView.addSubview(subTitle)

        

        //내비게이션 타이틀에 컨테이너 뷰를 넣는다.

        self.navigationItem.titleView = containerView

        

        //배경색상 설정

        let color = UIColor(red:0.02, green:0.22, blue:0.49, alpha:1.0)

        self.navigationController?.navigationBar.barTintColor = color

    }

    

    // 3.- 이미지를 이용해서 표현

    func imag(){

        let image = UIImage(named: "swift_logo")

        let imageV = UIImageView(image: image)

        self.navigationItem.titleView = imageV

    }

    

    //4. - 텍스트 필드를 이용해서 타이틀 초기화

    func initTitleInput(){

        

        //스텝.1

        let tf = UITextField()

        tf.frame = CGRect(x:0 ,y:0,width:300, height:35)

        tf.backgroundColor = UIColor.white

        tf.font = UIFont.systemFont(ofSize: 13)

        tf.autocapitalizationType = .none //자동 대문자 변환 속성 사용하지 않기

        tf.autocorrectionType = .no //자동 입력기능 해제

        tf.spellCheckingType = .no // 스펠링 체크 해제

        tf.keyboardType = .URL // URL 입력 전용 키보드

        tf.keyboardAppearance = .dark

        tf.layer.borderWidth = 0.3 //테두리 경계선 두깨

        tf.layer.borderColor = UIColor(red: 0.60, green: 0.60, blue: 0.60, alpha: 1.0).cgColor

        

        // 타이틀 뷰 속성에 대입

        self.navigationItem.titleView = tf

        

        //스텝.2

        //왼쪽 이미지 버튼

        let back = UIImage(named: "arrow-back")

        let leftItem = UIBarButtonItem(image: back, style: .plain, target: self, action: nil)

        self.navigationItem.leftBarButtonItem = leftItem

        

        //스텝.3

        //오른쪽 버튼은 컨테이너 뷰를 만들어서 레이블과 버튼을 뷰에 넣어주면서 추가

        let rv = UIView()

        //뷰와 뷰를 상속받는 모든 객체는 위치와 크기를 지정해 줘야 한다.

        rv.frame = CGRect(x:0, y:0, width: 70, height: 37)

        

        //내비게이션 바 버튼 아이템 매개변수로 위에서 만들었던 컨테이너 뷰를 넣어주었다.

        let rItem = UIBarButtonItem(customView: rv)

        self.navigationItem.rightBarButtonItem = rItem

        

        let cnt = UILabel()

        cnt.frame = CGRect(x:10, y:8, width: 20, height: 20)

        cnt.font = UIFont.boldSystemFont(ofSize: 10)

        cnt.textColor = UIColor(red: 0.60, green: 0.60, blue: 0.60, alpha: 1.0)

        cnt.text = "12"

        cnt.textAlignment = . center

        

        //외곽선

        cnt.layer.cornerRadius = 3

        cnt.layer.borderWidth = 2

        cnt.layer.borderColor = UIColor(red: 0.60, green: 0.60, blue: 0.60, alpha: 1.0).cgColor

        

        //레이블을 서브 뷰로 추가 하기

        rv.addSubview(cnt)

        

        

        //스텝.4

        let more = UIButton(type:.system)

        more.frame = CGRect(x:50, y:10, width: 16, height: 16)

        more.setImage(UIImage(named:"more"), for: .normal)

        rv.addSubview(more)

    }

    


    

}





'ios 뽀개기 > 실전' 카테고리의 다른 글

alert 커스텀 - 기본  (0) 2018.01.03
메모장 - 커스텀(x)  (0) 2018.01.03
커스텀 내비게이션 바  (0) 2018.01.03
탭바 커스텀하기  (0) 2018.01.02
커스텀 버튼 및 데이터 전달하기  (0) 2018.01.02
커스터마이징 버튼  (0) 2017.12.27

탭바 커스텀하기


//

//  ViewController.swift

//  TabTab

//

//  Created by MacBookPro on 2018. 1. 2..

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

//


import UIKit


class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        let title = UILabel(frame: CGRect(x:0, y:100, width: 100, height: 30))

        

        title.text = "첫번째"

        title.textColor = UIColor.red

        title.textAlignment = .center

        title.font = UIFont.boldSystemFont(ofSize: 14)

        

        title.sizeToFit() //콘텐츠의 내용에 맞게 레이블 크기 변경, center 속성 전에 사용하기

        title.center.x = self.view.frame.width / 2 //x축의 중앙에 오도록

        //값을 입력할때는 self.view.frame.size.width

        //값을 가져올때 self.view.frame.width

        

        self.view.addSubview(title)

        

        

        // 탭바 컨트롤러 -> 탭바를 통해 접근

        // 모든 탭바 아이템을 참조할 수 있다.

        //self.tabBarController?.tabBar.items?[0]

        //탭바를 참조하기 위해서 반드시 tabBarController를 거쳐야 한다.

        //탭바 관련 객체 중에서 뷰 컨트롤러에서 직접 참조할 수 있는 것은 탭바 컨트롤러와 탭 바 아이템 뿐이다.

        //탭바 아이템은 뷰 컨트롤러에서 self.tabBarItem 속성을 이용해서 직접 참조 할 수 있다.

        //self.tabBarItem.image = UIImage(named:"calendar.png")

        //self.tabBarItem.title = "캘린더"

        

        //탭 바 컨트롤러는 연결된 모든 뷰 컨트롤러의 화면을 처음부터 생성하는건 아니다.

        //각 탭이 처음 활성화 되는 순간에, 사용자가 탭을 누르는 순간에 비로소 그 탭에 연결된 뷰 컨트롤러의 화면을 읽어 들인다.

        //이는 viewDidLoad 메소드가 두번째 세번째 뷰 컨트롤러에서 아직 호출 되지 않았다는 뜻

        //해결: appDelegate클래스의 application(:didFinishLaunchingWithOptions:) 메소드로 옮기기

    }


    

    

    // UIViewController의 상위 클래스인 UIResponder에는 화면 터치 관련 메소드들이 정의 되어 있다.

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

        let tabBar = self.tabBarController?.tabBar

       // tabBar?.isHidden = (tabBar?.isHidden == true) ? false : true

        

        //애니메이션 적용해주기

        UIView.animate(withDuration:  TimeInterval(0.1)){

            tabBar?.alpha = (tabBar?.alpha == 0 ? 1 : 0)

            

        }

    }



}



//

//  SecondViewController.swift

//  TabTab

//

//  Created by MacBookPro on 2018. 1. 2..

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

//


import UIKit


class SecondViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()


        let title = UILabel(frame: CGRect(x:0, y:100, width: 100, height: 30))

        

        title.text = "두 번째 탭"

        title.textColor = UIColor.red

        title.textAlignment = .center

        title.font = UIFont.boldSystemFont(ofSize: 14)

        

        title.sizeToFit() //콘텐츠의 내용에 맞게 레이블 크기 변경, center 속성 전에 사용하기

        title.center.x = self.view.frame.width / 2 //x축의 중앙에 오도록

        //값을 입력할때는 self.view.frame.size.width

        //값을 가져올때 self.view.frame.width

        

        self.view.addSubview(title)

        

        // 탭바 컨트롤러 -> 탭바를 통해 접근

        // 모든 탭바 아이템을 참조할 수 있다.

        //self.tabBarController?.tabBar.items?[0]

        //탭바를 참조하기 위해서 반드시 tabBarController를 거쳐야 한다.

        //탭바 관련 객체 중에서 뷰 컨트롤러에서 직접 참조할 수 있는 것은 탭바 컨트롤러와 탭 바 아이템 뿐이다.

        //탭바 아이템은 뷰 컨트롤러에서 self.tabBarItem 속성을 이용해서 직접 참조 할 수 있다.

        //self.tabBarItem.image = UIImage(named:"file-tree.png")

        //self.tabBarItem.title = "파일"

    }


    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.

    }

    */


}


//

//  ThirdViewController.swift

//  TabTab

//

//  Created by MacBookPro on 2018. 1. 2..

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

//


import UIKit


class ThirdViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()


        let title = UILabel(frame: CGRect(x:0, y:100, width: 100, height: 30))

        

        title.text = "세 번째 탭"

        title.textColor = UIColor.red

        title.textAlignment = .center

        title.font = UIFont.boldSystemFont(ofSize: 14)

        

        title.sizeToFit() //콘텐츠의 내용에 맞게 레이블 크기 변경, center 속성 전에 사용하기

        title.center.x = self.view.frame.width / 2 //x축의 중앙에 오도록

        //값을 입력할때는 self.view.frame.size.width

        //값을 가져올때 self.view.frame.width

        

        self.view.addSubview(title)

        // 탭바 컨트롤러 -> 탭바를 통해 접근

        // 모든 탭바 아이템을 참조할 수 있다.

        //self.tabBarController?.tabBar.items?[0]

        //탭바를 참조하기 위해서 반드시 tabBarController를 거쳐야 한다.

        //탭바 관련 객체 중에서 뷰 컨트롤러에서 직접 참조할 수 있는 것은 탭바 컨트롤러와 탭 바 아이템 뿐이다.

        //탭바 아이템은 뷰 컨트롤러에서 self.tabBarItem 속성을 이용해서 직접 참조 할 수 있다.

        //self.tabBarItem.image = UIImage(named:"photo.png")

        //self.tabBarItem.title = "사진"

    }


    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.

    }

    */


}



//

//  AppDelegate.swift

//  TabTab

//

//  Created by MacBookPro on 2018. 1. 2..

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

//


import UIKit

import CoreData


//@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {


    var window: UIWindow?



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

        

        //1.윈도우 객체에 연결된 루트 뷰 컨트롤러를 읽어와 uitabbarcontroller 타입 캐스팅 한다.

        //루트 뷰 컨트롤러를 uitabbarcontroller로 캐스팅 한다.

        if let tbC = self.window?.rootViewController as? UITabBarController{

            

            //2.탭바로 부터 탭 바 아이템 배열을 가져 온다.

           if let tbItems =  tbC.tabBar.items{

            //tbItems[0].image = UIImage(named:"calendar")

            //tbItems[1].image = UIImage(named:"file-tree")

            //tbItems[2].image = UIImage(named:"photo")

            

            //커스텀 탭바 아이템으로 변경시키기 - 랜더링 메소드 이용!

            tbItems[0].image = UIImage(named:"designbump")?.withRenderingMode(.alwaysOriginal)

            tbItems[1].image = UIImage(named:"rss")?.withRenderingMode(.alwaysOriginal)

            tbItems[2].image = UIImage(named:"facebook")?.withRenderingMode(.alwaysOriginal)

            

            

            //탭바 아이템 전체를 순회하면서 selectedImage 속성에 이미지를 설정한다. -- 랜더링 메소드 이용!

            for tbItem in tbItems{

                let image = UIImage(named: "checkmark")?.withRenderingMode(.alwaysOriginal)

                tbItem.selectedImage = image

                

                //탭바 아이템 타이틀 색깔 속성값 변경하기. - 선택 안되었을때

                tbItem.setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue) : UIColor.gray], for: .disabled)

                //선택 되었을 때

                tbItem.setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue) : UIColor.red], for: .selected)

           

                //탭바 아이템의 폰트 값 설정

                tbItem.setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.font.rawValue) : UIFont.systemFont(ofSize: 15)], for: .normal)

            }

            

            //외형 프록시 객체를 이용하여 아이템의 타이틀 색상과 폰트 크기를 설정한다.

            //외형 프록시 객체는 화면 요소별 속성을 공통으로 적용할 수 있는 객체다.

            //외형 프록시 객체에 속성을 설정해두면 해 당 타입으로 생성된 모든 객체에 해당 속성이 적용된다.

            

            //let tbItemProxy = UITabBarItem.appearance()

            //tbItemProxy.setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue) : UIColor.red], for: .selected)

            //tbItemProxy.setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue) : UIColor.red], for: .disabled)

            //tbItemProxy.setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.font.rawValue) : UIFont.systemFont(ofSize: 15)], for: .normal)

            

            //3. 탭 바 아이템에 타이틀을 설정한다.

            tbItems[0].title = "달력"

            tbItems[1].title = "파일"

            tbItems[2].title = "사진"

            }

            

            //4.활성화된 탭 바 아이템의 이미지 색상을 변경한다.

            //tbC.tabBar.tintColor = UIColor.white

            //tbC.tabBar.backgroundImage = UIImage(named:"menubar-bg-mini")

            

            //let image = UIImage(named: "menubar-bg-mini")!

            //tbC.tabBar.barTintColor = UIColor(patternImage: image)

            

            //인자값으로 입력된 x좌표의 이미지만 늘어나고, x좌표를 기준으로 분할된 좌우측의 이미지는 나뉘어 양쪽 끝에 밀착하게 된다.

            //let bg = UIImage(named: "connectivity-bar")?.stretchableImage(withLeftCapWidth: 5, topCapHeight: 16)

            //tbC.tabBar.backgroundImage = bg

            

            //참고 tbC.tabBar.clipsToBounds = true // 탭바에서 넘쳐나는 이미지 잘라내기

        }

        

        return true

    }


    func applicationWillResignActive(_ application: UIApplication) {

        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.

        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.

    }


    func applicationDidEnterBackground(_ application: UIApplication) {

        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.

        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

    }


    func applicationWillEnterForeground(_ application: UIApplication) {

        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.

    }


    func applicationDidBecomeActive(_ application: UIApplication) {

        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

    }


    func applicationWillTerminate(_ application: UIApplication) {

        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.

        // Saves changes in the application's managed object context before the application terminates.

        self.saveContext()

    }


    // MARK: - Core Data stack


    lazy var persistentContainer: NSPersistentContainer = {

        /*

         The persistent container for the application. This implementation

         creates and returns a container, having loaded the store for the

         application to it. This property is optional since there are legitimate

         error conditions that could cause the creation of the store to fail.

        */

        let container = NSPersistentContainer(name: "TabTab")

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in

            if let error = error as NSError? {

                // Replace this implementation with code to handle the error appropriately.

                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                 

                /*

                 Typical reasons for an error here include:

                 * The parent directory does not exist, cannot be created, or disallows writing.

                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.

                 * The device is out of space.

                 * The store could not be migrated to the current model version.

                 Check the error message to determine what the actual problem was.

                 */

                fatalError("Unresolved error \(error), \(error.userInfo)")

            }

        })

        return container

    }()


    // MARK: - Core Data Saving support


    func saveContext () {

        let context = persistentContainer.viewContext

        if context.hasChanges {

            do {

                try context.save()

            } catch {

                // Replace this implementation with code to handle the error appropriately.

                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                let nserror = error as NSError

                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")

            }

        }

    }


}


앱 델리게이트 새로 만들어서 스토리보드 없이 하기 ~~~~~


//

//  NewDelegate.swift

//  TabTab

//

//  Created by MacBookPro on 2018. 1. 2..

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

//


import UIKit

import CoreData


@UIApplicationMain //전체를 통해 하나면 구현할 수 있다.

class NewDelegate: UIResponder, UIApplicationDelegate{

    //앱이 실행 될 때 앱 델리게이트 클래스는 스토리 보드 파일을 읽어와 윈도우 객체를 생성하는데, 이 객체를 앱 델리게이트 내의 변수 window에 저장하도록 프로그래밍 되어 있다.

    var window: UIWindow?

    

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

        

        //1. 탭바 컨트롤러를 생성하고 , 배경을 흰색으로 한다.

        let tbC = UITabBarController()

        tbC.view.backgroundColor = .white

        

        //2.생성된 tbC를 루트뷰 컨트롤러로 등록한다. : 윈도우 객체가 참조하는 뷰컨트롤러가 곧 루트 뷰 컨트롤러다.

        self.window?.rootViewController = tbC

        

        //3.각 탭바 아이템에 연결될 뷰 컨트롤러 객체를 생성한다.

        let view01 = ViewController()

        let view02 = SecondViewController()

        let view03 = ThirdViewController()

        

        //4.생성된 뷰 컨트롤러 객체들을 탭 바 컨트롤러에 등록한다.

        tbC.setViewControllers([view01,view02,view03], animated: false)

        

        //5 개별 탭바 아이템 속성을 설정한다.

        view01.tabBarItem = UITabBarItem(title:"달력",image:UIImage(named:"calendar"), selectedImage: nil)

        view02.tabBarItem = UITabBarItem(title:"파일",image:UIImage(named:"file-tree"), selectedImage: nil)

        view03.tabBarItem = UITabBarItem(title:"사진",image:UIImage(named:"photo"), selectedImage: nil)

        

        

        //주의: 탭 바 아이템을 참조할 때 탭바 컨트롤러 -> 탭바 -> 탭바 아이템 순으로 참조(x)

        //뷰 컨트롤러에서 직접 탭바를 참조해야 한다.

        //이유: 탭바 아이템은 각각의 뷰 컨트롤러에 연결되어 있는 속성이다. 탭바 컨트롤러 하위에 뷰컨트롤러가 연결되면 탭바 컨트롤러는 각각의 뷰컨트롤러에게 탭바 아이템을 제공한다.

        //이같은 매커니즘으로 인해 탭 바 아이템의 소유권은 탭바가 아닌 뷰 컨트롤러가 된다.

        // 뷰 컨트롤러 -> 탭바 아이템 형식으로 참조한다.

        return true

    }

    

}



'ios 뽀개기 > 실전' 카테고리의 다른 글

메모장 - 커스텀(x)  (0) 2018.01.03
커스텀 내비게이션 바  (0) 2018.01.03
탭바 커스텀하기  (0) 2018.01.02
커스텀 버튼 및 데이터 전달하기  (0) 2018.01.02
커스터마이징 버튼  (0) 2017.12.27
버튼 커스터마이징  (0) 2017.12.27

+ Recent posts

티스토리 툴바