인앱 브라우저와 같은 interactive 웹 컨텐츠를 보여주는 객체
iOS
class WKWebView : UIView
macOS
class WKWebView : NSView
중요
iOS 8.0과 OS X 10.10 부터 앱에 웹 컨텐츠를 추가하기 위해 WKWebView를 사용합니다. UIWebView나 WebView를 사용하지 마세요.
앱에 웹 콘텐츠를 넣기 위해 WKWebView class를 사용할 수 있습니다. 이를 위해 WKwebView 객체를 만들고, 이를 뷰로 설정하고 웹 컨텐츠를 불러오기 위해 request를 보내세요.
Note
WKWebView에 httpBody 컨텐츠를 넣을 수 있는 POST request를 만들 수 있습니다.
WKWebView 객체를 init(frame:configuration:)
로 만들고 난 뒤, 웹 컨텐츠를 불러올 필요가 있습니다. 로컬 HTML 파일을 불러오려면loadHTMLString(_:baseURL:)
메소드를 사용하고 웹 컨텐츠를 불러오기 위해서는 load(_:)
를 사용하세요. 페이지 로딩을 중단하려면 stopLoading
을 사용하고, isLoading
속성을 사용하여 웹뷰가 로딩이 진행중인지의 여부를 확인할 수 있습니다. 웹 컨텐츠를 불러오는 걸 추적하기 위해서 WKUIDelegate 프로토콜을 채택하세요. 다음 코드목록은 WKWebView를 프로그램으로 만들어내는 예제입니다.
Listing 1 Creating a WKWebView programmatically
import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
let myURL = URL(string:"https://www.apple.com")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
}}
웹페이지의 히스토리를 통해 사용자가 앞으로 뒤로 가도록 허용하려면 goBack()
과 goForward()
메소드를 버튼 액션으로 사용하세요. canGoBack
과 canGoForward
속성으로 사용자가 그 방향(앞/뒤)으로 이동할 수 없을 때를 확인할 수 있습니다.
기본적으로, 웹 뷰는 자동적으로 웹 컨텐츠에 있는 전화번호를 전화 링크로 변환해줍니다. 전화 링크를 선택하면 전화 앱이 실행되고 번호를 보여줍니다. 이런 기본 동작을 끄기 위해서는, dataDetectoreTypes
프로퍼티를 전화번호 플래그를 포함하지 않는 WKdataDetectorTypes
로 설정하세요.
최초로 웹 컨텐츠에 표시될 크기를 setMagnification(_:centeredAt:)
를 사용하여 설정할 수 있습니다. 그 다음 사용자는 제스처를 사용하여 크기를 변경할 수 있습니다.
class func handlesURLScheme(String) -> Bool
WebKit에서 기본적으로 특정 URL 스키마로 리소스를 불러올 수 있는지 여부를 반환합니다.
웹 뷰를 초기화 하기 위한 설정
var configuration: WKWebViewConfiguration
// 정해진 frame과 설정을 가지는 webView 초기화
init(frame: CGRect, configuration: WKWebViewConfiguration)
init?(coder: NSCoder)
// webView과 연결된 스크롤 뷰
var scrollView: UIScrollView
// 페이지 타이틀
var title: String?
// 활성화된 URL
var url: URL?
// 사용자의 user-agent String 값
var customUserAgent: String?
The custom user agent string.
// 최근 발생된 이동(navigation)에서의 SecTrustRef 객체
var serverTrust: SecTrust?
// 최근 발생된 이동(navigation)에서의 인증서 체인을 구성하는 객체들의 배열
var certificateChain: [Any]
An array of objects forming the certificate chain for the currently com
// web view's navigation delegate.
var navigationDelegate: WKNavigationDelegate?
//web view's user interface delegate.
var uiDelegate: WKUIDelegate?
// 네비게이션의 로딩된 정도를 추정한 값입니다.
var estimatedProgress: Double
// 페이지의 모든 리소스가 안전하게 암호화 된 연결을 통해 로드되었는지 여부를 나타내는 Bool 값입니다.
var hasOnlySecureContent: Bool
// 웹 페이지 내용과 기본 URL을 설정합니다.
func loadHTMLString(String, baseURL: URL?) -> WKNavigation?
// 뷰가 현재 내용을 로드 중인지 여부를 나타내는 Bool 값입니다.
var isLoading: Bool
// 현재 페이지를 다시 로드합니다.
func reload() -> WKNavigation?
func reload(Any?)
// 가능한 경우 캐시 유효성 검사 조건을 사용하여 end point 간 재 검증을 수행하여 현재 페이지를 다시 로드합니다.
func reloadFromOrigin() -> WKNavigation?
func reloadFromOrigin(Any?)
// 현재 페이지의 모든 리소스 로딩을 중단합니다.
func stopLoading()
func stopLoading(Any?)
// 웹 페이지 내용과 기본 URL을 설정합니다.
func load(Data, mimeType: String, characterEncodingName: String, baseURL: URL) -> WKNavigation?
// 파일 시스템의 요청 된 파일 URL로 이동합니다.
func loadFileURL(URL, allowingReadAccessTo: URL) -> WKNavigation?
// 확대 제스쳐가 웹 뷰의 배율을 변경할 수 있도록 허용할 것인지 나타내는 Bool 값
var allowsMagnification: Bool
// 현재 페이지의 컨텐츠의 크기
var magnification: CGFloat
// 지정된 값으로 페이지 컨텐츠의 크기를 조정하고 지정된 지점에 결과를 중앙 정렬합니다.
func setMagnification(CGFloat, centeredAt: CGPoint)
// 가로 스와이프 제스처가 역방향으로 이동하도록 허용할 것인지 여부를 나타내는 Bool값
var allowsBackForwardNavigationGestures: Bool
// 웹 뷰의 이동할 수 있는 페이지 목록
var backForwardList: WKBackForwardList
// back-forward에 뒤로 갈 수 있는 항목이 있는지 여부를 나타내는 Bool 값
var canGoBack: Bool
// back-forward 목록에 앞으로 갈 수 있는 항목이 있는지 여부를 나타내는 Bool 값
var canGoForward: Bool
// 링크를 누르면 미리보기가 표시되게 할 것인지 여부를 결정하는 Bool 값
var allowsLinkPreview: Bool
// back-forward에서 뒤 항목으로 이동합니다.
func goBack() -> WKNavigation?
func goBack(Any?)
// back-forward에서 앞 항목으로 이동합니다.
func goForward() -> WKNavigation?
func goForward(Any?)
// back-forward에서 항목을 이동하여 현재 항목으로 설정합니다.
func go(to: WKBackForwardListItem) -> WKNavigation?
// 요청된 URL로 이동합니다.
func load(URLRequest) -> WKNavigation?
// JavaScript String을 수행합니다.
func evaluateJavaScript(String, completionHandler: ((Any?, Error?) -> Void)?)
현재 뷰의 보여지는 부분의 snapshot을 생성합니다.
func takeSnapshot(with: WKSnapshotConfiguration?, completionHandler: (UIImage?, Error?) -> Void)
WKUIDelegate는 웹페이지를 대신해서 고유 사용자 인터페이스 요소들을 보여주는 메소드들을 제공합니다.
protocol WKUIDelegate
이 프로토콜을 채택한 웹 뷰 사용자 인터페이스 위임자는 새창 열기를 제어하거나, 사용자가 요소를 클릭할 때 표시되는 기본 메뉴 항목의 동작을 늘리거나, 사용자 인터페이스 관련 작업들을 수행합니다. 이러한 메소드들은 JavaScript 또는 다른 플러그인 컨텐츠를 처리 한 결과를 호출 할 수 있습니다. 기본적인 웹 뷰 구현은 웹 뷰 마다 하나의 창을 사용하므로 일반적이지 않은 사용자 인터페이스는 아마 이 사용자 인터페이스 위임을 채택했다고 볼 수 있습니다.
func webView(WKWebView, createWebViewWith: WKWebViewConfiguration, for: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView?
// Javascript alert 패널을 보여줍니다.
func webView(WKWebView, runJavaScriptAlertPanelWithMessage: String, initiatedByFrame: WKFrameInfo, completionHandler: () -> Void)
// Javascript confirm 패널을 보여줍니다.
func webView(WKWebView, runJavaScriptConfirmPanelWithMessage: String, initiatedByFrame: WKFrameInfo, completionHandler: (Bool) -> Void)
// Javascript 텍스트 입력 패널을 보여줍니다.
func webView(WKWebView, runJavaScriptTextInputPanelWithPrompt: String, defaultText: String?, initiatedByFrame: WKFrameInfo, completionHandler: (String?) -> Void)
// DOM 창이 성공적으로 닫혔을 때 호출되는 메소드입니다.
func webViewDidClose(WKWebView)
// 파일 업로드 패널을 보여주는 메소드입니다.
func webView(WKWebView, runOpenPanelWith: WKOpenPanelParameters, initiatedByFrame: WKFrameInfo, completionHandler: ([URL]?) -> Void)
// 주어진 요소가 미리보기를 보여주어야 하는지 결정합니다.
func webView(WKWebView, shouldPreviewElement: WKPreviewElementInfo) -> Bool
// 사용자가 peek 액션을 수행했을 때 호출됩니다.
func webView(WKWebView, previewingViewControllerForElement: WKPreviewElementInfo, defaultActions: [WKPreviewActionItem]) -> UIViewController?
// 사용자가 미리보기에서 pop 액션을 수행했을 때 호출됩니다.
func webView(WKWebView, commitPreviewingViewController: UIViewController)
Called when the user performs a pop action on the preview.
WKProcessPool 객체는 웹 컨텐츠 프로세스를 나타내는 풀입니다.
class WKProcessPool : NSObject
웹 뷰와 연관된 프로세스 풀은 웹 뷰 configuration에 의해 지정됩니다. 각 웹뷰는 구현 정의 프로세스 제한(implementation-defined process limit)에 도달 할 때까지 자체 웹 컨텐츠 프로세스를 제공받습니다. 그 후에 동일한 프로세스 풀이 있는 웹 뷰가 결국 웹 컨텐츠 프로세스를 공유하게됩니다.
Note WKProcessPool 객체는 그 자체의 속성이나 메소드가 없는 불투명 토큰입니다.
웹 뷰에 대한 기본 속성 설정을 캡슐화한 객체입니다.
class WKPreferences : NSObject
이 preferences 객체는 웹 뷰가 초기화될 때 사용되는 configuration에 의해 지정됩니다.
// 최소 font size
var minimumFontSize: CGFloat
var tabFocusesLinks: Bool
// Java가 가능한지
var javaEnabled: Bool
// 사용자가 동작하지 않아도 JavaScript를 통해 새 창 열기가 가능한지
var javaScriptCanOpenWindowsAutomatically: Bool
// Javascript가 가능한지
var javaScriptEnabled: Bool
// PlugIn 사용이 가능한지
var plugInsEnabled: Bool
Apple의 HIG 문서를 번역했습니다. 의역과 오역이 난무합니다 XD 순서도 제각각입니다.
컨텐츠가 로드될 때, 빈 페이지나 정적인 화면은 앱이 멈춘 것처럼 보일 수 있어 혼란과 좌절감을 유발할 수 있고 잠재적으로 사람들이 앱을 종료시킬 수 있다.
로딩이 발생함을 명확히 하자! 최소한 Activity Spinner라도 보여줘서 뭔가 일어나고 있다고 알려주자. 대략적인 진행사항을 보여줘서 사용자들이 얼마나 기다려야 하는지에 대해 예상할 수 있으면 더 좋다.
가능한 한 빨리 컨텐츠를 보여주자. 내용이 로드되기를 기다리는 것 때문에 사람들이 기대하는 화면을 보여 주는 걸 늦추지 말자. 화면을 빠르게 보여주고, placeholder와 그래픽이나 애니메이션 요소들을 사용해서 아직 컨텐츠가 사용불가능하다는 걸 알려주자. 컨텐츠가 로드되면 그 때 이 placeholder 요소들을 교체하자. 가능하다면 다가올 컨텐츠들을 백그라운드에서 미리 로딩하자. 예를 들어서 애니메이션이 보이고 있다거나, 사용자가 레벨이나 메뉴를 탐색할 시점에.
로딩 타임에 사람들을 교육하거나 즐겁게 해라. 게임 플레이에 대한 힌트를 보여주거나, 재밌는 비디오를 보여주거나, 흥미로운 대체 이미지들을 보여주는 건 어떨까?
로딩 화면을 사용자화하자 물론 표준 progress indicator를 사용하는 것도 좋지만, 컨텍스트에 맞지 않다고 느낄 수도 있다. 당신의 앱이나 게임에 맞는 스타일의 사용자 애니메이션이나 요소들을 통해 더 인상적인 경험을 디자인하는 건 어떨까?
Modality는 사용자의 이전 컨텍스트와 분리되고 종료하는 명시적인 액션이 필요한 컨텐츠를 일시모드로 보여주는 디자인 기법입니다. 컨텐츠를 모달로 보여주는 건 다음과 같은 역할을 할 수 있습니다.
iOS는 앱의 특정 상황에서 사용할 수 있도록 알럿과 Activity View와 Action Sheet를 제공합니다. 사용자 모달 컨텐츠를 앱에서 보여주려면 iOS 13 이후에서는 다음과 같은 화면 스타일을 지원합니다.
sheet 프레젠테이션 스타일은 카드처럼 보이며 부분적으로 뒤의 컨텐츠를 덮으면서 덮이지 않은 영역이 액션을 받는 것을 막기 위해 딤처리합니다. 사용자가 카드를 열였을 때 이전 작업들이 정지되었음을 기억할 수 있도록 부모 뷰의 상단 모서리나 이전 카드는 현재 카드 뒤에 보여집니다. 사람들이 다음 방식으로 현재 카드를 닫을 수 있습니다.
모달 컨텐츠가 너무 복잡해서 혼란을 주지 않을 경우에만 sheet를 사용하세요.
fullscreen 프레젠테이션 스타일은 전체화면을 덮습니다. 이전 화면은 완전히 덮이기 때문에 시각적 산만함이 최소화됩니다. 사람들은 버튼을 누름으로써 전체 화면 모달 뷰를 종료할 수 있습니다.
전체 화면 모달 뷰는 예를 들어 비디오나, 사진, 카메라 뷰와 같은 몰입되어야 하는 컨텐츠에 사용하세요. 혹은 문서를 표시하거나 사진을 편집하는 것과 같이 복잡한 작업에 전체 화면 프레젠테이션을 사용하면 좋습니다.
Note 만약 현재 컨텍스트 모달 뷰 스타일이 split view pane 이나 popover, 혹은 전체화면이 아닌 뷰의 모달 컨텐츠라면, 소형 환경에서 모달 컨텐츠를 제공할 때는 풀스크린이 아니라 sheet 로 변경해야합니다.
상황에 맞게 모달을 사용하자. 모달로 화면을 보여주는 건 사용자들이 선택을 하거나 현재 작업과는 다른 작업을 수행하는데 집중시키는 게 중요할 경우에만 사용하세요. 모달로 보여주는 건 사용자로 하여금 현재 컨텍스트에서 빠져나오게 되고 어떤 빠져나가야만하는 액션을 요구하기 때문에, 이 모달을 보여주는 것이 명백히 이점일 때 사용해야 합니다.
필수적이고 이상적인 행동을 위한 정보를 제공하는 알럿을 준비하세요. 통상적으로 알럿은 뭔가 잘못됐을 때 나타납니다. 왜냐하면 알럿은 기존 경험을 중단시키고 탭하여 사라지기를 요구하기 때문에, 사람들이 이러한 간섭에 대해 확신을 갖는 것이 중요합니다. 가이드에서는 Alert을 참조하세요.
모달 작업은 단순하고, 짧고, 좁은 포커스여야합니다. 앱 내에서 새로운 앱을 만들지 맙시다.(복잡한 작업을 모달로 만들지 맙시다.) 만약 모달 작업이 너무 복잡하면 사람들이 모달 컨텍스트에 진입한 후에, 중단된 이전 작업에 대한 sight를 잃을 수 있습니다. 특히 사람들이 길을 잃고 길을 돌아가는 법을 잊을 수 있기 때문에 뷰의 계층 구조가 포함 된 모달 작업을 만드는 데 주의하십시오. 모달 작업에 하위보기가 포함되어야하는 경우 계층 구조를 통과하는 단일 경로와 완료까지 명확한 경로를 제공하세요. 작업 완료 이외의 작업에는 Done 버튼을 사용하지 마세요.
항상 모달 뷰를 닫는 버튼을 포함하세요. 예를 들어, 완료 또는 취소를 사용할 수 있습니다. 단추를 포함하면 모달 뷰가 보조 기술을 적용할 수 있고 dismiss 제스처 대신 사용할 수 있습니다.
필요한 경우 모달 뷰를 닫기 전에 확인을 받아 사람들이 데이터 손실을 피하도록 도와줍니다. 사람들이 짤막한 제스처 또는 뷰를 닫는 데 사용하는 버튼과 상관없이 작업으로 인해 사용자가 생성한 콘텐츠가 손실 될 수 있는 경우 상황을 설명하고 해결 방법을 제시하는 작업 시트를 제시합니다.
팝 오버 위에 카드를 표시하지 마십시오. popover 내에 카드를 표시 할 수는 있지만, popover의 상단에는 아무 것도 나타나지 않습니다 (alert는 제외). 드물게 사람들이 popover에서 행동을 취한 후에 카드를 제시해야 할 경우 카드를 표시하기 전에 popover를 닫습니다.
일반적으로 모달 작업을 식별하는 제목을 표시하세요. 사람들이 모달 작업에 참여하면 이전 컨텍스트에서 벗어나므로 새 컨텍스트를 명확하게 만드는 것이 좋습니다. 보기의 다른 부분에 텍스트를 제공하여 작업을 보다 자세히 설명하거나 지침을 제공할 수도 있습니다.
모달 뷰의 시각적 부분을 앱과 맞추세요. 예를 들어, 모달 뷰에 탐색 막대가 포함되어있는 경우 응용 프로그램의 탐색 막대와 동일한 모양을 사용해야합니다.
앱에서 적절한 모달 전환 스타일을 선택하십시오. 앱과 맞는 전환 스타일을 사용하면 임시 컨텍스트 이동에 대한 인지도를 높입니다. 기본 전환은 모달 뷰를 화면 아래쪽에서 수직으로 슬라이드시키고 닫을 때 뒤로 내립니다. 앱 전체에서 일관된 모달 전환 스타일을 사용하십시오.
For developer guidance, see UIViewController and UIPresentationController.
객체 지향 프로그래밍 (Object Oriented Programming)
컴퓨터 프로그래밍 패러다임 주 하나입니다. 프로그래밍에서 필요한 데이터를 추상화하여 객체를 만들고 객체간 유기적인 상호작용을 통한 로직을 구성하는 프로그래밍 방법론입니다.
장점
단점
클래스는 어떤 대상에 대한 특성(attribute)과 행위(behavior)를 변수와 메소드로 변환하여 정의한 것입니다. 인스턴스는 이렇게 정의된 클래스를 기반으로 실제 메모리에 할당된 것입니다.
추상화란 공통적으로 사용될 수 있을 만한 속성이나 기능을 묶어 정의해둔 것을 말합니다. 예를 들어 선생님에는 교장선생님/교감선생님 뿐만아니라, 과학 선생님, 국어 선생님 등 선생님 마다 전공이 다를 수 있습니다. 이를 ‘선생님’으로 추상화하면 다음과 같습니다.
protocol Teacher {
let name: String
let grade: Int
let subject: String
let manageClass: Class?
func teach() {}
func makeTest() {}
}
간략하게 선생님의 이름, 등급(교장/교감/일반 등), 과목, 담당클래스를 정의했습니다. 모든 선생님들은 학생들을 가르치고, 시험을 만들 수 있습니다.
이렇게 되면 과학 선생님이든, 국어 선생님이든 교장선생님이든 프로토콜을 채택한다면 선생님으로 묶을 수 있습니다.
class MathTeacher: Teacher {}
class ScienceTeacher: Teacher {}
그리고 시험기간엔 모든 선생님들이 시험문제를 만들도록 할 수 있겠죠
let mathTeacher = MathTeacher("김수학")
let scienceTeacher = ScienceTeacher("이과s")
let array = [mathTeacher, scienceTeacher]
array.forEach { teacher in
teacher.makeTest()
}
좀 어거지 코드이긴 하지만, 그렇습니다. 하핳
캡슐화란 객체가 맡은 역할을 수행하기 위한 목적을 묶는 것을 이야기합니다. 예를 들어 선생님이 이제 시험과, 그에 대한 답안을 가지고 있다고 합시다.
protocol Teacher {
...
var questionSheet: QuestionSheet?
var answerSheet: AnswerSheet?
...
}
만약 시험괴 답안지가 외부에서도 접근이 가능하다면 외부에 유출되거나, 다른 주체에 의해서 이 답안지가 변경될 수도 있겠죠. 이를 막기 위해서 외부에서는 이 questionSheet과 answerSheet에 대해 접근하지 못하도록 막고 필요할 때는 함수를 통해서만 접근케 합니다.
class MathTeacher: Teacher {
...
private var questionSheet: QuestionSheet?
private var answerSheet: AnswerSheet?
...
func makeTest() {
self.questionSheet = QuestionSheet()
self.answerSheet = AnswerSheet()
}
func scoreTest(answerOfStudent target: AnswerSheet) {
var score = 0
for i in 0..< answerSheet.questionCount {
let answer = self.answerSheet.answerOfQuestionNumber(i)
let studentAnswer = target.answerSheet.answerOfQuestionNumber(i)
score += (answer == studentAnswer) ? 1 : 0
}
}
}
시험지와 답안지를 private으로 선언함으로써 외부에서는 이 변수에 접근할 수 없도록 막고, 학생의 답변을 채점할 때는 학생의 답을 받아서 내부적으로 점수를 계산하게 했습니다.
이런 식으로 필요한 변수와 함수들을 한데 묶으면서 동시에 적절한 접근제어자를 통해 데이터를 은닉화할 수 있습니다.
상속는 부모클래스의 속성과 기능을 그대로 이어받아 사용함을 이야기 합니다. 필요하다면 자식 클래스에서 변수나 함수를 추가할 수 있습니다.
다중상속은 불가능합니다.
부모클래스에서 물려받은 속성이나 함수를 자식 클래스에서 필요하다면 override하여 재정의하여 사용하는 것입니다.
overriding : 상속관계에서 부모에서 정의한 변수나 함수를 재정의하여 사용하는 것. overloading : 동일한 이름을 가진 함수를 매개변수를 달리하여 여러개를 정의하는 기법.