2018년 8월 17일 금요일

네비게이션 컨트롤의 rootViewController 변경하기

 앱 최초 실행시에 intro -> 가입유도 / 또는 로그인

로그인 성공이후는 main 으로 실행 되는 앱이 있다고 하면

어느 경우는 intro가 navigation controller의 rootViewController 이고

어느 경우는 main이 navigation controller의 rootViewCotnorller  가 된다.

main으로 계속 실행되던 앱에서 logout 기능을 이용하면 login viewController가

navigationViewController에 rootViewController가 되어 실행된다.


스토리 보드를 이용하고 segue를 잘 쓰려고 하는데 앱 최초 진입점이 다르고
navigation controller를 결국에는 storyboard Embed in 으로 해서 만들 수 도 없고

결국 코드로 ViewController를 storyboard에서 찾아다가 push 하고 navigation controller를 초기 화 하고 복잡하게 ... 스파게티...


이러한 앱을 개발 할때 다음과 같이 하면 좀 수월 하다.

1. navigation controller 는 storyboard에 만들지 않는다.

2. navigation controller에 root가 될 viewController 들 ( 2개 또는 3개) 는
attribute inspector에서 top bar 항목을 설정 해준다.

그래야 하위 segue가 연결된 viewController들이 네비바가 있는것처럼 디자인 할 수 있다.

3. init viewController 및 navgation controller의 rootController를 appdelegate.swift에서 구현 한다.



didFinishLaunchingWithOptions 메서드에서 UserDefaults 등으로 구현하여 현재 상황에 맡는 ViewController를 rootViewController로 하여 navigation Controller를 설정 하고 시작 한다.

//intro
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let root = storyboard.instantiateViewController(withIdentifier: "IntroViewController")
        nvc = UINavigationController(rootViewController: root)


        window?.rootViewController = nvc

        window?.makeKeyAndVisible()


로그인 등이 완료되어 main으로 시작 하거나, 또는 로그 아웃으로 인해 다시 intro로 시작 해야 하는 경우를 대비해 
스위칭 하는 메서드를 appdelegate에 구현 한다.
func switchIntro() {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "IntroViewController")
        nvc = UINavigationController(rootViewController: vc)
        
        self.window?.rootViewController = nvc
        window?.makeKeyAndVisible()
    }
    
    func switchMain() {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "MainViewController")
        nvc = UINavigationController(rootViewController: vc)
        
        self.window?.rootViewController = nvc
        window?.makeKeyAndVisible()

    }



어떠한 ViewController에서 navigaion Controller의 루트를 변경 하고자 하면 다음과 같이 하면 된다.
let appDelegate = UIApplication.shared.delegate as! AppDelegate
            
            appDelegate.switchIntro()




2018년 6월 6일 수요일

iPhone 6 7 8 plus 에서 상태바가 크게 나오는 앱 올바른 스케일로 나오게 하려면?

실제로 오래전에 만들어진 프로젝트에서 코드를 추가하다 보니

플러스 모델에서 화면 스케일이 업 되어 표출 되는 경우를 발견 했다.

실제로 아직도 내가 사용하는 iphone 6+ 에서 사용되는 앱중에 이렇게 오래된 프로그램인 듯 보이는 앱들이 존재 한다.

내가 사용중인 앱중에는  증권통,  키움증권 영웅문  과 같은 앱들이 아직도 상태바가 크게 보인다. 마치 오래전에 만든 앱이 6+에서 그냥 화면이 늘어 나서 보이는 느낌이다.

대신 증권 앱이나 기업 은행 앱은 최근에 바로 잡힌 듯 하다.



위에부터 키움증권, 증권통, facebook 의 iPhone 6 +에서 스크린샷이다.

왜 이러한 현상이 나타날까?

실제로 오래전에 만들어진 앱에 코드를 추가하고 유지보수 하다가 이러한 현상을 바로 잡기 위해 프로젝트 설정을 해메고 찾고 하였지만 해답은 의외로 간단 했다.



Launch Screen 스토리 보드르 추가 하여 위와 같이 프로젝트를 설정하면
올바른 크기로 프로그램이 실행 된다.

다음은 스택오버플로우의 관련 글이다.
https://stackoverflow.com/questions/25754942/how-to-enable-native-resolution-for-apps-on-iphone-6-and-6-plus

알면 별것 아니고 모르면 개고생이다.

증권통앱에 이방법을 알려주고 싶다.

2018년 4월 18일 수요일

Xcode 9 에서 컬러 리터럴 사용하기

코드에서 색상 값을 UIColor()에 생성자에 RGB 값으로 코딩을 하면 무슨 색인지 코드만 보고는 알수가 없다.



Xcode에서는 이러한 점을 고려하여 위와 같이 color literal을 지원하게 되었다.
색상이 Xcode에디터에서 문자 처럼 표시 된다.

color lteral을 코드에 적용 하는 방법은 다음과 같다.

color literal을 타이핑 하면 다음과 같이 코드 완성이 이루어지려 한다.


에디터에서 색상을 더블클릭 하면 색상 선택 창이 나타난다.




Other를 선택 하여 RGB 및 alpha 값을 적용 하여 원하는 색상 리터럴 문자를 만들수 있다.




이렇게 코드를 작성하면 실제는 colorLiteral() 로 코딩되어 있고 Xcode editor 상에서는 색상으로 표시되어 가독성이 좋다.











2018년 4월 12일 목요일

Xcode 9 에서 markdown파일을 렌더링 하여 보기




Xcode에서 .md 파일을 추가 할수 있다.
하지만 기본은 그냥 편집 할 수 있게만 되고 미리보기라 든지 그런 기능이 없다.


위에글은 링크된 파일을 다운로드 받으면 Xcode 프로젝트가 있는데 Xcode로 오픈해 보면 정말 README.md 가 렌더링 되서 보여준다.

아무런 차이도 없는데 해당 프로젝트는 그렇게 보여준다.
위 리크에서 설명 하듯이 답은 .xcodesamplecode.plist 파일이 프로젝트 (패키지 내용보기) 내부 에 있는 것이다. 파인더에서도 디폴트는 보여지지 않기 때문에 터미널을 이용하여 ls -al 로 확인 하였다.

sparrow-mac-mini:ARKitExample.xcodeproj sparrow$ ls -al
total 56
drwxr-xr-x@ 6 sparrow  staff    204  4 12 22:18 .
drwxr-xr-x@ 9 sparrow  staff    306  4 12 22:03 ..
-rw-r--r--@ 1 sparrow  staff    182  8  8  2017 .xcodesamplecode.plist
-rw-r--r--  1 sparrow  staff  24272  4 12 22:07 project.pbxproj
drwxr-xr-x@ 5 sparrow  staff    170  4 12 22:04 project.xcworkspace
drwxr-xr-x  3 sparrow  staff    102  4 12 22:04 xcuserdata

현재 작업중인  프로젝트는 워크스페이스로 구성되어 있었는데 여러 포함된  프로젝트 파일중에 README.md 파일을 추가 했고 렌더링 된 결과가 나올 줄 알았지만 결과는 아무런 변화가 없다.

하여 잘못된 글로 생각 했다.

워크스페이스로 된 프로젝트에서는 .xcodesamplecode.plist 파일을 workspace 디렉토리에 넣어야 된다.

결국 이글은 정확하게 잘된다.

구지 ARKitExample.xcodeproj을 다운 받지 않고도

터미널에서 워크스페이스 파일이나 xcode 프로젝트 파일에 디렉토리에 들어가서 .xcodesamplecode.plist 파일을 생성 하면 될 것으로 보인다.

해당 파일의 냉용은 다음과 같다.

sparrow-mac-mini:ARKitExample.xcodeproj sparrow$ cat .xcodesamplecode.plist 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array/>
</plist>


이파일이 프로젝트 디렉토리 (패키지내용보기) 또는 터미널에서 cd  진입 하여 .xcodesamplecode.plist (ARKitExample.xcodeproj) 에 있는 파일이나 직접 만들어 넣으면 xcode가 markdown 파일을 렌더링 해서 보여준다.

단! 렌더링 되면 수정 xcode에서는 수정이 되지 않는다.

Visual Studio Code로 편집 수정하여 Xcode 프로젝트에 추가하면 멋진 도큐먼트를 포함하는 프로젝트가 될 것이다.

그리고 표문법은 적용 되지 않는다.

그래도 이정도면 쓸만 하다.

2018년 3월 9일 금요일

UIPickerView의 선택된 텍스트 색상 변경, 선택 라인의 색상 변경을 하려면?

어쩔수 없이 UI작업이 디자인 가이드를 우선으로 해야 하는 경우 기본적인 UIPickerView를 변경 해야 하는 경우가 있다.


UIPikckerView를 디폴트로 사용하면 데이터소스로 데이터 값정도를 변경 할 수 있다.

위와 같이 선택라인의 색상을 변경 시키거나 선택된 텍스트의 컬러를 변경 시키는 작업은 코드를 이용 해야 한다.

첫번째 선택된 Text의 컬러를 변경 하기 위해서는 AttributeString을 리턴 하는 아래의 메서드를 구현 해야 한다.

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

}

선택된 row 일때와 그렇지 않을때의 컬러를 결정 하여 NSAttributedString을 리턴 해야 한다.

1,2,3,4와 같은 UIPickerView 의 표출될 문자열 스트링 어레이가. pickerData 인 경우 
아래의 코드는 선택된 텍스트의 색상을 blue, 선택되지 않은 색상은 black으로 표출 하는 코드이다.
    func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
        var color: UIColor!
        if pickerView.selectedRow(inComponent: component) == row {
            color = UIColor.blue
        } else {
            color = UIColor.black
        }
        
        let attributes: [NSAttributedStringKey: Any] = [
            NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue): color,
            NSAttributedStringKey(rawValue: NSAttributedStringKey.font.rawValue): UIFont.systemFont(ofSize: 15)
        ]
        
        return NSAttributedString(string: pickerData[row], attributes: attributes)
    }



다음은 선택 라인의 색상을 변경 해야 하는데 기본 UIPickerView는 Property로 제공하지 않는다.

UIPickerView를 서브클래싱 하여 CustomPickerView class를 생성 한다음 다음의 두 라인이 을 찾아서 색상을 변경 하는 코드를 추가 해야 한다.

didAddSubview 메서드를 오버라이딩 하여 서브뷰 중에 height가 1인 값의 즉 두선을 찾아 색상을 변경 한다.

 @IBDesignable와 @IBInspectable을 이용하여 스토리보드에서 변경 사항을 확인 까지 가능 하도록 다음과 같이 클래스를 생성 하면 된다.

//
//  CustomPickerView.swift
//  datetimepickerDemo
//
//  Created by  sparrow on 2018. 3. 8..
//  Copyright © 2018년  sparrow. All rights reserved.
//

import UIKit

@IBDesignable
class CustomPickerView: UIPickerView
{
    @IBInspectable var selectorColor: UIColor? = nil
    
    override func didAddSubview(_ subview: UIView) {
        super.didAddSubview(subview)
        if let color = selectorColor
        {
            if subview.bounds.height <= 1.0
            {
                subview.backgroundColor = color
            }
        }
    }
}


스토리 보드상에서 selectorColor을 설정 하면 바로 색상이 적용된다.








2018년 3월 8일 목요일

가로 모드에서 특정 뷰가 전체 화면이 되는 앱을 autolayout으로 어떻게 구현 하는가?

세로 모드에서 컨텐츠가 가운데 표시되고 상단과 하단에는 네비게이션 바 부터 정보를 보여주는 Label 하단에는 각종 버튼이 있다고 하자.

이러한 상태에서 가로모드로 전환을 하면 가운데 컨텐츠가 전체 화면으로 변경 되는 앱을 만든다고 하면 어찌 하는가?
아래 그림을 참조






화면 전환을 인지 하는 코드는. willTransition() 메서드로 인지 할 수 있다.

UIDevice.current.orientation.isLandscape 의 값을 확인 하여 현재 landscape 모드인지 확인이 가능 하다.

이럴때 가운데 컨텐츠의 autolayout constraint 값을 (0)으로 변경 하면 쉽게 해결 할 수 있다.
즉 세로모드로 IB에서 디자인을 하고 autolayout constraint를 적용 할때 Video 라는 글이 있는 검정색 뷰의 부모 뷰에 대한 constraint Align top to:와 Align Bottom to:를 IBOutlet으로 연결하여
코드로 값을 조정 하면된다.

나머지 나비게이션콘트롤러의 바나, 레이블, 버튼등도 코드로 isHidden 값을 정해 주면 된다.

하여 완성된  ViewController의 코드는 다음과 같다.

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var topContraint: NSLayoutConstraint!
    @IBOutlet weak var bottomConstraint: NSLayoutConstraint!
    @IBOutlet weak var infoLabel: UILabel!
    @IBOutlet weak var controlButton: UIButton!
    
    override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
        if UIDevice.current.orientation.isLandscape == true {
            topContraint.constant = 0
            bottomConstraint.constant = 0
            self.navigationController?.isNavigationBarHidden = true
            infoLabel.isHidden = true
            controlButton.isHidden = true
        } else {
            topContraint.constant = 122
            bottomConstraint.constant = 300
            self.navigationController?.isNavigationBarHidden = false
            infoLabel.isHidden = false
            controlButton.isHidden = false
        }
    }


}

2018년 3월 1일 목요일

Xcode 9 GitHub 계정 지원 기능 알아 보기

xcode 9 이 되면서 Github 계정 연동 기능이 추가 되었다.
기존 버젼도 git을 지원 하기는 하였지만 좀더 많은 기능이 추가되었다.



특히 이번 버젼에는 좌측 Navigator 화면에 Source Control Navigator가 추가 되었고 직관적으로 볼수 있게 되었다.

1. github계정 생성



메뉴 Xcode -> Preferences -> Accounts
에서 Github 계정을 추가 할 수 있다.





메뉴 Xcode -> Preferences -> Source Control -> Git
에서 git 관련 설정을 할 수 있다.


2. Source Control Navigator 활용





좌측 Source Control Navigator ( Cmd + 2) 화면에서는 브랜치 전환 및 git message를 확인 할 수 있는 기능이 새롭게 추가 되었다.


3. github 계정에 원격 리포지토리 생성





Source Control Navigator에서. Remotes 마우스 우클릭으로 원격 리포지토리 생성이 가능 하다. 계정 설정에 연결된 GitHub 계정에 원격 리포지토리를 생성 할 수 있다.








branch 생성 branch 간 전환도 가능 하다.

4. 머지



test브랜치를 만들고 브랜치 전환을 하여 수정한 다음 손쉽게 마스터 브랜치에 머지 할 수 있다.


6. 소스 컨트롤 메뉴



상단 메뉴에서 Source Control 메뉴 GitHub 프로젝트에 대한 Clone , Repositores 생성 , Commit, Push, Pull 등 모든 기능을 할 수 있는 메뉴가 존재 한다.



이상으로 간단하게 Xcode 9 에 새롭게 추가된 github 연동 및 git 관련 기능을 살펴 보았다.