달력

42024  이전 다음

  • 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

'모바일 개발/iOS-Swift'에 해당되는 글 2건

  1. 2017.12.14 WKWebVIew 에서 쿠키 2
  2. 2017.10.25 초기화에 대해서..

일단, 나는 UIWebView 를 써보지 않았다. WKWebVIew만 써봤다. Android에 WebView랑 비슷한 듯.


하이브리드 앱에 홈페이지 로그인 할 때 자동 로그인 체크하고, 로그인을 하게 되면 앱이 종료되면 쿠키 삭제ㅋ 됨ㅋ 자동 로그인 안됌ㅋ 뭐지... 하고 이런저런 테스트를 해봤는데, WKWebView에는 php에 setcookie가 안 먹히드라. 결국 자동로그인 쿠키가 생성이 안됨ㅋ

안되면 되게 하라... 스크립트로 처리를 함.

AppDelegate에서


func applicationWillResignActive(_ application: UIApplication) {
    web.evaluateJavaScript("document.cookie", completionHandler: {(object, error) in
        if let string: String = object as? String {
            UserDefaults.standard.set(string, forKey: "cookie")
        }
    })
}

이렇게 앱이 foreground에서 벗어나게 되면 쿠키를 수시로 저장시키자. 아, 근데 php setcookie로 생성된 쿠키는 저기에서 확인이 안된다.ㅋ

 일단 WKWebView에 WKUserContentController() 를 통해서 자바스크립트 인터페이스(안드로이드에서는 이렇게 부른다 swift에서는 콘텐츠컨트롤러라고하는건가...?)를 등록하고, 로그인 처리하는 페이지에서 스크립트로 실행 한 후에 UserDefault에다가 자동로그인 체크를 했다는 정보를 넘겨주어서 앱에서 자동으로 쿠키를 생성시켜서 처리를 했다.



let contentController = WKUserContentController();
let config = WKWebViewConfiguration();
contentController.add(self, name: "javascriptInterfaceName"); // name 에다가 원하는 자바스크립트인터페이스 이름을 입력하면 되시겠다.
config.userContentController = contentController;
let webview = WKWebView(frame: uiController.view.frame, configuration: configurate!)

그리고 웹페이지에서 어떻게 실행을 시키는 고하면

webkit.messageHandlers.javascriptInterfaceName.postMessage( { key1 : value1, key2 : value2, key3 : [ value3_1, value3_2 ] } );

위 소스를 실행시키면 된다.


위 소스를 실행시키게 되면, 

@available(iOS 8.0, *)
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
// message.name 이녀석이 javascriptInterfaceName 이랑 매칭이 된다. 요녀석으로 용도별로 처리하면된다.
// 보안 문제가 발생 할 경우가 있으니까 꼭 if message.name != "javascriptInterfaceName" {return} 이런 식으로 지정한  스크립트가 아니라면 막길 권한다.

    guard let mbody = message.body as? Dictionary<String,Any> else {return} // json 형식으로 파라미터 값을 넘겼으니까 Dictionary로 변환 가능하다.
    let value1 = mbody["key1"] as? Any
    let value2 = mbody["key2"] as? Any
    let value3 = mbody["key3"] as? Array<Any> // 마지막은 리스트형식이니까,
}

WKWebView 내의 이런 소스에서 실행이 된다. 참고로 iOS8 부터 사용 가능하다.

이렇게 아무튼 저기서 자동로그인 체크를 했다는 것을 앱으로 전달해서 UserDefault에 다가 저장했다가 앱 실행시마다 자동로그인 쿠키값을 생성해주면 되겠다. 어떻게?? 아래처럼 참고하자.


아래 setCookie에 해당하는 메소드는 구글링을 통해서 찾았으나, 출처를 따로 안적어놨네..........죄송합니다..

webview.evaluateJavaScript("document.setCookie = function (name, value, expiredays) {var cookie = name + \"=\" + escape(value) + \"; 
path=/;\"; if (typeof expiredays != 'undefined') {var todayDate = new Date(); todayDate.setDate(todayDate.getDate() + expiredays); cookie += \"expires=\" +todayDate.toGMTString() + \";\"; } 
document.cookie = cookie;}",completionHandler: nil)

WKWebView에다가 저렇게 하고

webview.evaluateJavaScript("document.setCookie('\(key)','\(value)', '\(expiredays)')", completionHandler: {
    (o,e) in web.reload()
})

이렇게 key(쿠키 명), value(쿠키 값), expiredays(저장 기간) 값을 넣어서 쿠키를 생성시키고, 페이지 새로고침을 해줘야 제대로 인식을 한다.

마지막으로 저기 document에 체이닝 되어진 setCookie 메소드를 제거해주자.

webview.evaluateJavaScript("delete document.setCookie", completionHandler: nil)


이렇게 하면 깔끔하게 처리가 된다.

'모바일 개발 > iOS-Swift' 카테고리의 다른 글

초기화에 대해서..  (0) 2017.10.25
Posted by
|

class 초기화만 해당된다.

class SomeClass : NSObject{
    let someValue1 : TempObject;
    let someValue2 : TempObject2?
    var someValue3 : Int;
    init( _ someParam : TempObject){
        someValue1 = someParam;
        someValue2 = TempObject2();
        super.init();
        someValue3 = 5;
    }
}


일단 지정 초기화, 편의 초기화 설명 보다 먼저,
let 으로 선언된 변수는 super.init() 이전에 초기화가 이루어 져야한다.
그리고 나중에 설명 하겠지만 let 변수는 꼭 (designed)정의 초기화에서 초기화가 되어야 한다.
일단 옵셔널로 정의된 건 nil 로 초기화가 가능한데, let 변수이니, nil로 선언되면 변경이 안되니 nil로 초기화 할 거면 let 이 아니라 var 로 선언 하는게 좋을듯 한다.

편의 초기화 접두어는 convenience 를 사용 하면 된다. 뭣 하는 녀석인고 하면

class SomeClass {
    init(v1 : Int, v2 : Int, v3 Int){
        //someCode
    }
    convenience init(v1 : Int){
        self.init(v1 : v1, v2 : 5, v3 : 3)
    }
}

요런거에 사용 되는 녀석이다. 딸랑 요것만 있음 뭔지 모르지.. 아래에 있는 걸 다시 보자.

class SomeClass {
    init(v1 : Int, v2 : Int? = nil, v3 : Int? = nil){ //지정 초기화
        //someCode
    }
    convenience init(v1 : Int){ // 편의 초기화
        self.init(v1 : v1, v2 : nil, v3 : nil)
    }
}

//초기화
let someClass : SomeClass = SomeClass(1);

v1 파라미터만 넘기고 싶을때 사용하면 된다.
내부적으로 v2, v3 에는 nil 이 지정 초기화로 넘어가게 된다.

여기서 조금 생소한 부분이 나온다.
편의 초기화는 내부에 꼭 다른 초기화 내용이 있어야 한다. 위의 self.init(v1 : v1, v2 : nil, v3 : nil) 과 같이 말이다.
여기서 편의 초기화에서 편의 초기화를 호출 해도 된다.

class SomeClass {
    init(v1 : Int, v2 : Int? = nil, v3 : Int? = nil){ // 마지막 호출
        //someCode
    }
    convenience init(v1 : Int){ //최초 호출
        self.init(v1 : v1, v2 : nil)
    }
    convenience init(v1 : Int , v2 : Int){ //두번쨰 호출
        self.init(v1 : v1, v2 : v2, v3 : nil);
    }
}
// 초기화
let someClass : SomeClass = SomeClass(v1 : 3);

여기서 상속 받을 경우는 어떻게 되는가를 궁금해 하는 사람이 있을 것 같아 제일 위에 있는 소스를 참고해서 보자.

class SomeClass : NSObject{
    let someValue1 : TempObject;
    let someValue2 : TempObject2?
    var someValue3 : Int;

    override init(_ someParam : TempObject , someParam2 : TempObject2){
        someValue1 = someParam;
        someValue2 = someParam2;
    }

    convenience init(_ someParam : TempObject, someParam2 : TempObject2){
        self.init(someParam, someParam);
        someValue3 = 5;
    }

    convenience init( _ someParam : TempObject){
        let someParam2 = TempObject2();
        self.init(someParam, someParam2);
    }
}
//초기화
let someParam : TempObject = TempObject();
let someClass : SomeClass = SomeClass(someParam);

위에서 설명했듯이 let 변수는 정의 초기화 함수 내에서 초기화가 이루어져야 한다.
위에 정의 초기화를 super class의 init을 오버라이드 했다.
오버라이드 하지 않고 쓰기 위해서는 아래 처럼 간단하게 사용 하면된다.

class SomeClass : NSObject{
    let someValue1 : TempObject;
    let someValue2 : TempObject2?
    var someValue3 : Int;

    init(_ someParam : TempObject, someParam2 : TempObject2){
        someValue1 = someParam;
        someValue2 = someParam2;
        super.init();
        someValue3 = 5;
    }

    convenience init( _ someParam : TempObject){
        let someParam2 = TempObject2();
        self.init(someParam, someParam2);
    }
}
//초기화
let someParam : TempObject = TempObject();
let someClass : SomeClass = SomeClass(someParam);

마찬가지로 정의 초기화에서 let을 초기화 시켜주어야 한다.

첫 초기화로 호출 되어 초기화가 이루어진다. 두번째 호출이라고 주석 단 부분에 또한 편의 초기화이다.
ㅇㅇ 쉽게 convenience -> convenience 가 된다. 그리고 그 끝은 designed(지정) 초기화가 있어야만 한다.
구글링 해보면 몇 가지 법칙이라고 정리 되어 있던데, 난 그런 법칙은 모르겠구, 내 수준으로 정리를 하면
1. let 변수는 super.init() 호출 전에 초기화가 되어야 하며, 정의(Designed) 초기화내부에서만 초기화가 가능하다.
2. 편의->편의->지정 같이 초기화의 마무리는 항상 지정 초기화가 되어야 한다.

Java 스타일의 초기화랑 비교를 하면, Java 의 경우 초기화 함수를 여럿 만들어 주면 된다. 그냥 입맛에 맞게 만들어서 사용하면된다. 그리고, super 클래스 초기화를 부르고 싶으면 쓰고, 안쓰고 싶으면 안 쓰면 된다.
super class의 초기화도 오버라이드 하든 말든 마음대로 내키는 대로 하면 된다. 초기화 선언이 없으면 고냥 자동으로 만들어 준다.
Swift는 조금 색다르게 표현했다. 편의(convenience) 초기화는 말 그대로 편의를 위해서 만들어지는 정식적인 초기화는 아니고, 정의(Designed)초기화를 통해서만 모든 초기화가 이루어진다고 보면 된다.

'모바일 개발 > iOS-Swift' 카테고리의 다른 글

WKWebVIew 에서 쿠키  (2) 2017.12.14
Posted by
|