처음 시작할 때에만 나타나는 Tutorial 화면 구성하기(PageViewController 이용)
이번에는 앱을 처음 시작할 때만 실행하고 이후부터는 나타나지 않는 Tutorial 화면을 구성해 보자.
아래와 같이 구동된다.
==========================================================================
1. 메인 ViewController와 Tutorial View Controller와의 연결 (첫 실행인지 아닌지 확인 필요)
2. Tutorial View Controller에 pageViewController를 자식view로 설정
==========================================================================
1. MainViewController와 Tutorial View Controller와의 연결 (첫 실행인지 아닌지 확인 필요)
. 앱은 MainViewController로 시작하지만 만약 앱을 처음 시작한다면 TutorialViewController이 화면에 뜨게 만든다. 그리고 TutorialViewController에서 버튼을 click하면 MainViewController로 다시 돌아오게 하고 이후부터는 TutorialViewController가 나타나지 않게 한다.
. 우선 Storyboard를 하나 추가하고 Tutorial.storyboard로 이름을 변경한다.(File>New>File... 에서 storyboard 선택)
-> 이런 Tutorial 처럼 첫 실행에만 실행된다면 Main.storyboard와는 다른 storyboard에서 관리하는게 보기에 좋다.
. Tutorial.storyboard에 ViewController를 추가하고 Storyboard ID를 Master라고 명명한다.
-> Storyboard ID를 설정해야 향후 코드로 viewController를 읽을 수 있다.
. Swift file을 UIViewController 형식으로 추가를 하고 이름을 MasterTutorial로 명명한다. 그리고 storyboard에 추가된 viewController의 class로 설정해 준다.
. MasterTutorial ViewController 하단에 UIButton을 하나 추가하고 Start로 명명하였다.
아래 그림처럼 되었다.
. 이제 첫 실행 여부에 따라 MasterTutorial이 화면에 나오게 하고 MasterTutorial에서 start를 누르면 MainViewController로 돌아가는 코드를 만들어 보자
. 우선 MainViewController 화면이다.
(1) 첫 실행인지 확인
. UserDefaults객체에 tutorials key로 저장된 내용을 불러와서 false인지 확인한다. key값으로 tutorials가 없어도 false가 반환되니 처음 실행한다면 false가 반환되어 if구문 안의 내용이 실행된다.
(2) MasterTutorial viewController 실행
. 어느 storyboard에 있는지 확인하고 그 storyboard에서 ID값이 Master인 viewcontroller를 불러온다.
. 여기선 Tutorial.storyboard에 존재하는 MasterTutorial viewcontroller를 가져왔다.
. 만약 동일 storyboard에 존재하는 viewcontroller를 가져온다면 self.storyboard.instantiateViewController()로 적용하면 된다. 여기선 storyboard를 분리했기 때문에 이렇게 storyboard를 따로 가져와야 한다.
# 여기서 viewDidAppear에 실행하였다. viewDidLoad()에서 실행한다면 화면이 연결되지 않는다. MainViewController가 실행되고 이후에 self.present()로 연결해야 하기 때문에 view가 나타난 후 연결하기 위해 viewDidAppear()에 코딩해야 한다.
. 이번엔 MasterTutorial 화면이다.
(1) startButton IBAction 연결
. 우선 storyBoard에서 start 버튼을 IBAction으로 연결한다. (control drag)
(2) data 저장
. UserDefaults객체에 tutorials key로 Bool값인 true를 저장하고 싱크한다. 이렇게 해야 다음 앱 실행 때 tutorial 화면이 나오지 않게 된다.
(3) MainViewController로 돌아가기
. MainView에서 present로 들어왔기 때문에 dismiss로 MainView로 돌아갈 수 있다.
아래는 여기까지 구동 화면이다. 참고로 MainView와 MasterTutorial view의 바탕화면 색을 설정하였다.
2. Tutorial View Controller에 pageViewController를 자식view로 설정
. 자 이제 pageViewController를 이용하여 tutorial 화면을 구성해 보자.
. 우선 화면 구성을 아래와 같이 PageViewController와 UIViewController를 추가해 주자.
. PageViewController는 PageView로 UIViewController는 ContentsView로 각각 Storyboard ID 설정한다.
. UIViewController에는 ImageView와 Label을 그림과 같이 추가해 준다.
. swift 화일을 UIViewController class로 하나 추가하고 이름을 ContentsTutorial로 명명한다. 그리고 storyboard에서 contentsView로 설정된 ViewController의 class로 설정해 준다.
. 아래 그림과 같이 되었다.
. 이제 ContentsTutorial class를 작성해 보자.
(1) outlet 연결
. 화면에 표시항 Label과 Image를 IBOutlet으로 연결하였다.
(2) Contents 정보 정의
. MasterTutorial에서 받아올 정보를 정의하였다.
. 이번엔 다시 MasterTutorial이다.
(1) contentsPageName 정의
. ContentsTutorial class에 넘어갈 정보이다. 이전에 아래와 같이 assets에 page0~4까지 그림을 추가하였다. 추가한 그림의 이름과 동일한 string으로 array를 만들었다.
(2) ContentsTutorial View 가져오는 함수 정의
. index 정수를 받아서 어떤 ContentsTutorial을 반환하는지에 대한 함수이다.
. index는 contentsPageName array의 개수를 넘으면 안되므로 guard문을 이용했다.
. 동일한 storyboard이므로 self.storyboard.instantiateViewController()를 이용해서 ContentsTutorial class를 불러왔다.
. 불러온 ContentsTutorial class에서 표시될 내용(image 이름, pageIndex)를 index와 연결하여 대입하였다.
. 이렇게 설정된 ContentsTutorial을 반환한다.
(3) PageViewController를 설정한다.
. (2)처럼 동일 storyboard에 있는 pageViewController를 가져와서 pageVC에 대입해 준다.
. 먼저 UIPageViewControllerDataSource 프로토콜 따르도록 dataSource를 self로 지정한다. 이렇게 해야 page를 넘길때 어떤 page가 다음에 와야 하는지 이전 page는 머가 있는지 지정할 수 있다.
아래와 같이 구동된다.
==========================================================================
1. 메인 ViewController와 Tutorial View Controller와의 연결 (첫 실행인지 아닌지 확인 필요)
2. Tutorial View Controller에 pageViewController를 자식view로 설정
==========================================================================
1. MainViewController와 Tutorial View Controller와의 연결 (첫 실행인지 아닌지 확인 필요)
. 앱은 MainViewController로 시작하지만 만약 앱을 처음 시작한다면 TutorialViewController이 화면에 뜨게 만든다. 그리고 TutorialViewController에서 버튼을 click하면 MainViewController로 다시 돌아오게 하고 이후부터는 TutorialViewController가 나타나지 않게 한다.
. 우선 Storyboard를 하나 추가하고 Tutorial.storyboard로 이름을 변경한다.(File>New>File... 에서 storyboard 선택)
-> 이런 Tutorial 처럼 첫 실행에만 실행된다면 Main.storyboard와는 다른 storyboard에서 관리하는게 보기에 좋다.
. Tutorial.storyboard에 ViewController를 추가하고 Storyboard ID를 Master라고 명명한다.
-> Storyboard ID를 설정해야 향후 코드로 viewController를 읽을 수 있다.
. Swift file을 UIViewController 형식으로 추가를 하고 이름을 MasterTutorial로 명명한다. 그리고 storyboard에 추가된 viewController의 class로 설정해 준다.
. MasterTutorial ViewController 하단에 UIButton을 하나 추가하고 Start로 명명하였다.
아래 그림처럼 되었다.
. 이제 첫 실행 여부에 따라 MasterTutorial이 화면에 나오게 하고 MasterTutorial에서 start를 누르면 MainViewController로 돌아가는 코드를 만들어 보자
. 우선 MainViewController 화면이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(_ animated: Bool) {
// (1) 첫 실행인지 확인
let ud = UserDefaults.standard
if ud.bool(forKey: "tutorials") == false {
// (2) MasterTutorial viewController 실행
let sb = UIStoryboard(name: "Tutorial", bundle: Bundle.main)
let vc = sb.instantiateViewController(withIdentifier: "Master")
self.present(vc, animated: true, completion: nil)
}
}
}
| cs |
(1) 첫 실행인지 확인
. UserDefaults객체에 tutorials key로 저장된 내용을 불러와서 false인지 확인한다. key값으로 tutorials가 없어도 false가 반환되니 처음 실행한다면 false가 반환되어 if구문 안의 내용이 실행된다.
(2) MasterTutorial viewController 실행
. 어느 storyboard에 있는지 확인하고 그 storyboard에서 ID값이 Master인 viewcontroller를 불러온다.
. 여기선 Tutorial.storyboard에 존재하는 MasterTutorial viewcontroller를 가져왔다.
. 만약 동일 storyboard에 존재하는 viewcontroller를 가져온다면 self.storyboard.instantiateViewController()로 적용하면 된다. 여기선 storyboard를 분리했기 때문에 이렇게 storyboard를 따로 가져와야 한다.
# 여기서 viewDidAppear에 실행하였다. viewDidLoad()에서 실행한다면 화면이 연결되지 않는다. MainViewController가 실행되고 이후에 self.present()로 연결해야 하기 때문에 view가 나타난 후 연결하기 위해 viewDidAppear()에 코딩해야 한다.
. 이번엔 MasterTutorial 화면이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class MasterTutorial: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
// (1) startButton IBAction 연결
@IBAction func startButton(_ sender: Any) {
// (2) data저장
let ud = UserDefaults.standard
ud.set(true, forKey: "tutorials")
ud.synchronize()
// (3) MainViewController로 돌아가기
self.dismiss(animated: true, completion: nil)
}
}
| cs |
(1) startButton IBAction 연결
. 우선 storyBoard에서 start 버튼을 IBAction으로 연결한다. (control drag)
(2) data 저장
. UserDefaults객체에 tutorials key로 Bool값인 true를 저장하고 싱크한다. 이렇게 해야 다음 앱 실행 때 tutorial 화면이 나오지 않게 된다.
(3) MainViewController로 돌아가기
. MainView에서 present로 들어왔기 때문에 dismiss로 MainView로 돌아갈 수 있다.
아래는 여기까지 구동 화면이다. 참고로 MainView와 MasterTutorial view의 바탕화면 색을 설정하였다.
2. Tutorial View Controller에 pageViewController를 자식view로 설정
. 자 이제 pageViewController를 이용하여 tutorial 화면을 구성해 보자.
. 우선 화면 구성을 아래와 같이 PageViewController와 UIViewController를 추가해 주자.
. PageViewController는 PageView로 UIViewController는 ContentsView로 각각 Storyboard ID 설정한다.
. UIViewController에는 ImageView와 Label을 그림과 같이 추가해 준다.
. swift 화일을 UIViewController class로 하나 추가하고 이름을 ContentsTutorial로 명명한다. 그리고 storyboard에서 contentsView로 설정된 ViewController의 class로 설정해 준다.
. 아래 그림과 같이 되었다.
. 이제 ContentsTutorial class를 작성해 보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class ContentsTutorial: UIViewController {
// (1)
@IBOutlet weak var pageLabel: UILabel!
@IBOutlet weak var pageImage: UIImageView!
// (2)
var pageLabelText: String!
var pageImageName: String!
var pageIndex: Int!
override func viewDidLoad() {
super.viewDidLoad()
self.pageLabel.text = pageLabelText
self.pageImage.image = UIImage(named: pageImageName)
}
}
| cs |
. 화면에 표시항 Label과 Image를 IBOutlet으로 연결하였다.
(2) Contents 정보 정의
. MasterTutorial에서 받아올 정보를 정의하였다.
. 이번엔 다시 MasterTutorial이다.
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
|
class MasterTutorial: UIViewController, UIPageViewControllerDataSource {
// (1) contentsPageName 정의
let contentsPageName = ["page0","page1","page2","page3"]
override func viewDidLoad() {
super.viewDidLoad()
// (3) PageViewController를 설정한다.
let pageVC = self.storyboard?.instantiateViewController(withIdentifier: "PageView") as! UIPageViewController
pageVC.dataSource = self
pageVC.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height - 30)
pageVC.setViewControllers([getContentsView(pageIndex: 0)!], direction: .forward, animated: true, completion: nil)
self.addChildViewController(pageVC)
self.view.addSubview(pageVC.view)
pageVC.didMove(toParentViewController: self)
}
// (2) contentsView 가져오는 함수 정의
func getContentsView(pageIndex index:Int)->UIViewController? {
guard index < self.contentsPageName.count else {return nil}
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ContentsView") as! ContentsTutorial
vc.pageImageName = self.contentsPageName[index]
vc.pageLabelText = self.contentsPageName[index]
vc.pageIndex = index
return vc
}
// (4) UIPageViewControllerDataSource 프로토콜 정의 함수
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let index = (viewController as? ContentsTutorial)?.pageIndex else {return nil}
if index > 0 {
return getContentsView(pageIndex: index - 1)
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let index = (viewController as? ContentsTutorial)?.pageIndex else {return nil}
if index + 1 < self.contentsPageName.count {
return getContentsView(pageIndex: index + 1)
}
return nil
}
// (5) pageIndicator 설정
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return self.contentsPageName.count
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return 0
}
@IBAction func startButton(_ sender: Any) {
....
}
}
| cs |
(1) contentsPageName 정의
. ContentsTutorial class에 넘어갈 정보이다. 이전에 아래와 같이 assets에 page0~4까지 그림을 추가하였다. 추가한 그림의 이름과 동일한 string으로 array를 만들었다.
(2) ContentsTutorial View 가져오는 함수 정의
. index 정수를 받아서 어떤 ContentsTutorial을 반환하는지에 대한 함수이다.
. index는 contentsPageName array의 개수를 넘으면 안되므로 guard문을 이용했다.
. 동일한 storyboard이므로 self.storyboard.instantiateViewController()를 이용해서 ContentsTutorial class를 불러왔다.
. 불러온 ContentsTutorial class에서 표시될 내용(image 이름, pageIndex)를 index와 연결하여 대입하였다.
. 이렇게 설정된 ContentsTutorial을 반환한다.
(3) PageViewController를 설정한다.
. (2)처럼 동일 storyboard에 있는 pageViewController를 가져와서 pageVC에 대입해 준다.
. 먼저 UIPageViewControllerDataSource 프로토콜 따르도록 dataSource를 self로 지정한다. 이렇게 해야 page를 넘길때 어떤 page가 다음에 와야 하는지 이전 page는 머가 있는지 지정할 수 있다.
. pageVC의 위치 및 크기를 설정해 준다. 다만 start button이 가져지지 않게 height는 self.view에 조금 모자라게 설정한다.
. setViewControllers() method로 어떤 viewController를 pageVC에 첫번째로 나타나게 할지 설정해 준다.
. pageVC를 자식뷰로 설정하고 MasterTutorial을 pageVC의 부모뷰로 알려준다. 이렇게 custom container view controller를 설정할 때 항상 나오는 형식이다.
(4) UIPageViewControllerDataSource protocol 정의 함수
. PageView에서 어떤 view가 나올지 정의를 해줘야 한다. 하여 before view는 먼지, after view는 먼지 알려줘야 PageView에서 준비하고 있을 수 있다. tableView에서 dataSource 프로토콜처럼..
. 여기 두 함수에서 viewController 인자는 현재 viewController를 뜻하는 것이다. 하여 ContentsTutorial로 type casting하고 현재 view의 index가 얼마인지 확인한다. 그리고 맨처음인지 아니면 맨 마지막 view인지 확인해서 before, after view가 무엇인지 지정해 주면 된다.
(5)마지막으로 pageIndicator 설정하기 위한 함수이다.
. 총 page가 몇개인지, 그리고 최초 page의 정보는 어떻게 되는지에 대해 알려준다.
. 이렇게 하고 실행하더라도 문제 없지만 indicator의 색을 수정하는게 좋을거 같다. 하여 아래와 같이 AppDelegate에 코드를 수정하다.
(1) appearence 설정
. 모든 UIPageControl의 외관에 대한 내용을 수정을 한다.
. 이렇게 수정을 하면 UIPageControl의 indicator의 색과 선택된 indicator의 색에 대해 설정할 수 있다.
. 만약 TableView나 UIViewController또한 이런 방식으로 외관에 대한 내용을 설정할 수 있다. 각각의 UIViewController class에 들어가서 설정하지 않더라도 모두 동일한 concept으로 설정 가능하다.
(4) UIPageViewControllerDataSource protocol 정의 함수
. PageView에서 어떤 view가 나올지 정의를 해줘야 한다. 하여 before view는 먼지, after view는 먼지 알려줘야 PageView에서 준비하고 있을 수 있다. tableView에서 dataSource 프로토콜처럼..
. 여기 두 함수에서 viewController 인자는 현재 viewController를 뜻하는 것이다. 하여 ContentsTutorial로 type casting하고 현재 view의 index가 얼마인지 확인한다. 그리고 맨처음인지 아니면 맨 마지막 view인지 확인해서 before, after view가 무엇인지 지정해 주면 된다.
(5)마지막으로 pageIndicator 설정하기 위한 함수이다.
. 총 page가 몇개인지, 그리고 최초 page의 정보는 어떻게 되는지에 대해 알려준다.
. 이렇게 하고 실행하더라도 문제 없지만 indicator의 색을 수정하는게 좋을거 같다. 하여 아래와 같이 AppDelegate에 코드를 수정하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//(1) appearence 설정
let appearence = UIPageControl.appearance()
appearence.pageIndicatorTintColor = UIColor.lightGray
appearence.currentPageIndicatorTintColor = UIColor.black
return true
}
......
}
| cs |
(1) appearence 설정
. 모든 UIPageControl의 외관에 대한 내용을 수정을 한다.
. 이렇게 수정을 하면 UIPageControl의 indicator의 색과 선택된 indicator의 색에 대해 설정할 수 있다.
. 만약 TableView나 UIViewController또한 이런 방식으로 외관에 대한 내용을 설정할 수 있다. 각각의 UIViewController class에 들어가서 설정하지 않더라도 모두 동일한 concept으로 설정 가능하다.
댓글
댓글 쓰기