Programming/iOS2016.10.25 23:46

앱을 실행해면 전면 광고를 실행해서 보여주게 하였다. 


그러던 중 admob 으로 부터 메일 한통을 받았다.



경고를 받은 앱은 Android 앱이었지만 iOS에서도 동일한 방식으로 나오고 있었다. 


iOS도 수정이 필요한 상황이었다. 그래서 정책을 알아 보기로 했다. 여러 가지 정책이 있어서 모든 것을 다 소개할 수도 없고 내가 필요한 것은 기존 상태를 유지하면서 고칠 수 있는 방법이었다.


https://support.google.com/admob/answer/6201362?hl=ko&ref_topic=2745287


`예기치 않게 실행되는 삽입 광고` > `허용되지 않는 광고 구현의 예: 앱을 열 때 삽입 광고 실행` 


이 경우가 경고를 받았을 때의 경우이다. 


이걸 이제 어떻게 수정해야 할까..



이 방법대로 해보자~!!!


iOS Launch screen 이 나오고 메인 화면이 나오기 전에 광고가 떠야 한다.


그렇다면... AppDelegate 의 didFinishLaunchingWithOptions 에서 띄우면 될것 같아!


1. AppDelegate 에서 전면광고 띄우기


import GoogleMobileAds

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GADInterstitialDelegate {

    var window: UIWindow?
    var interstitial: GADInterstitial?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        interstitial = GADInterstitial(adUnitID: "********")

        let request = GADRequest()
        // Requests test ads on test devices.
        interstitial?.load(request)

        return true
    }

    func interstitialDidReceiveAd(_ ad: GADInterstitial!){
        guard let viewController = window?.rootViewController else { return }
        ad.present(fromRootViewController: viewController)
    }
}

앱 실행시 광고를 띄우는 코드는 모두 작성되었다. 이제 실행을 해보자~!



음...? 메인화면이 먼저 뜨고 전면광고가 뜬다. 위에 안 되는 경우가 바로 이런 경우이다.


이렇게 하면 정지를 받을게 뻔하다... 이건 아님...



전면광고를 로딩하는 시간 때문에 어쩔 수 없이 메인 화면이 노출되는 것 같다. 그러면... 만족스럽지 못하지만 자주 쓰는 방법으로 페이크 LaunchScreen 을 이용해 보자. 


Launch screen 과 같은 VC를 바로 띄워서 전면고를 보여주면...? 문제가.. 없겠는데?!! 그리고 전면광고를 닫을때 메인 화면으로 이동해주자.


2. Fake launch screen 을 이용하여 전면광고 띄우기


import GoogleMobileAds

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GADInterstitialDelegate {

    var window: UIWindow?
    var interstitial: GADInterstitial?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        if let viewController = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController() {
            window?.rootViewController = viewController
        }

        interstitial = GADInterstitial(adUnitID: "******")
        interstitial?.delegate = self

        let request = GADRequest()
        interstitial?.load(request)

        return true
    }

    func interstitialDidReceiveAd(_ ad: GADInterstitial!){
        guard let viewController = window?.rootViewController else { return }
        ad.present(fromRootViewController: viewController)
    }

    func interstitialWillDismissScreen(_ ad: GADInterstitial!) {
        if let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() {
            window?.rootViewController = viewController
        }
    }
}

이렇게 하면 완벽히 동작할 것이다. 이제 전면광고로 부터 자유로워 질 것이다.


실행을 해보자. 밑에 동영상을 확인해 보자.




우리가 원하는 동작이다!! 와우~!!


그런데 뭔가가... 좀... 부족하다..


전면 광고가 사라지는 애니메이션이 사라졌다. willDismiss에서 rootViewController를 변경해서 그런가 보다..


그렇다고 didDismiss 에서 rootViewController 를 변경하면 애니메이션이 끝나기 전까지 전면광고가 보인다. 이렇게 하면 다음과 같은 경우로 허용되지 않는다.



Launch screen에서 광고를 띄워야 하는 것은 유지되어야 하고 광고가 사라지는 애니메이션이 유지되면서 메인화면이 보여야 한다. 


일단 window의 rootViewController를 변경하면 애니메이션을 유지하지 못한다. rootViewController를 변경하는 방법을 제외한다.


그럼... Launch screen 을 VC 형태로 하는게 아니라 view 로 보여주는건 어떨까? view면 바로 추가하고 제거하면 되지 않을까?


음? 그럴듯하다. 한번 해보자. 생각하면 답이 안 나온다. 일단 삽질하다 보면 답이 나오겠지. 어서 해보자.


import GoogleMobileAds

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GADInterstitialDelegate {

    var window: UIWindow?
    var interstitial: GADInterstitial?
    var launchScreenView: UIView?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        if let view = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController()?.view {
            launchScreenView = view
            view.translatesAutoresizingMaskIntoConstraints = false
            
            if let rootView = window?.rootViewController?.view {
                rootView.addSubview(view)
                
                var constraints = [NSLayoutConstraint]()
                constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", options: [], metrics: nil, views: ["view": view])
                constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", options: [], metrics: nil, views: ["view": view])
                rootView.addConstraints(constraints)
            }
        }

        interstitial = GADInterstitial(adUnitID: "******")
        interstitial?.delegate = self

        let request = GADRequest()
        interstitial?.load(request)

        return true
    }

    func interstitialDidReceiveAd(_ ad: GADInterstitial!){
        guard let viewController = window?.rootViewController else { return }
        ad.present(fromRootViewController: viewController)
    }

    func interstitialWillDismissScreen(_ ad: GADInterstitial!) {
        launchScreenView?.removeFromSuperview()
    }
}


후후 코드는 완벽하다.


이제 실행 동영상을 보자.





완벽하게 내가 원했던 동작이다.


축하~ 축하!!



여러분의 광고 수익에 조금이나마 도움이 되었으면 좋겠다.





신고
Posted by 초프(초보 프로그래머)
Programming/iOS2016.10.21 00:41

Swift build를 하다가 컴파일이 끝나지 않고 계속되는 현상을 발견했다.





Appcode로 build 중이었는데 swift의 메모리가 끝없이 계속 증가했다.


의심가는 코드를 제거해 보니 빌드가 잘 된다.


아.. 엄청나다.


의심가는 코드를 Playground로 재작성해보았다.


?? 를 남발해서 그런것으로 보이는데... 이래도 되는건가?

let optionalString: String? = nil

let abc: [String:Int] = [
    "a": Int(optionalString ?? "") ?? 0,
    "B": Int(optionalString ?? "") ?? 0,
    "c": Int(optionalString ?? "") ?? 0,
    "d": Int(optionalString ?? "") ?? 0,
    "e": Int(optionalString ?? "") ?? 0
]
print(abc)


관련링크 : http://stackoverflow.com/questions/26151954/sourcekitservice-consumes-cpu-and-grinds-xcode-to-a-halt

신고
Posted by 초프(초보 프로그래머)
TAG Build, swift
Programming/Backend2016.10.18 23:14

프로젝트도 생성했으니 이제 뭔가 해보자. 


음.. 아무래도 Backend 이고 하니... DB가 있어야 겠다. 많이 쓰는 Mysql 로 해보자.


MySQL 을 사용하려면 MySQL용 Database connector 를 추가해야 한다. 


package.swift 의 dependency로 추가 가능하다.

import PackageDescription
 
let package = Package(
    name: "FirstPerfectProject",
    dependencies: [
        .Package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", majorVersion: 2, minor: 0),
        .Package(url:"https://github.com/PerfectlySoft/Perfect-MySQL.git", majorVersion: 2, minor: 0)
    ]
)


Xcode에서 build를 해보자. (xcode에서 실행하는 방법은 이전 글에서 생략했다.... 실수로..)




왜.. 오류지?!


음.. 그럼.. 처음에 했던 swift build를 해보자.

$ swift build
Cloning https://github.com/PerfectlySoft/Perfect-MySQL.git
HEAD is now at 53ef1af Fixes ISS-269 - numRows always returns 0
Resolved version: 2.0.1
Cloning https://github.com/PerfectlySoft/Perfect-mysqlclient.git
HEAD is now at 60a82d5 A little cleanup
Resolved version: 2.0.0
Compile Swift Module 'MySQL' (1 sources)
Compile Swift Module 'PerfectLib' (10 sources)
Compile Swift Module 'PerfectHTTP' (9 sources)
Compile CHTTPParser http_parser.c
Linking CHTTPParser
Compile Swift Module 'PerfectHTTPServer' (5 sources)
Compile Swift Module 'FirstPerfectProject' (1 sources)
Linking ./.build/debug/FirstPerfectProject

오!! 빌드했더니 Perfect-MySQL 을 다운로드 받는다~!


이제 run 할 수 있겠다.  Xcode에서 실행해보자.





또 같은 오류!!!!!!


무엇이 문제일까?  Xcode에서 실행하지 말고 터미널에서 실행해볼까?

$ swift build Compile Swift Module 'MySQL' (1 sources) Compile Swift Module 'PerfectLib' (10 sources) Compile Swift Module 'PerfectHTTP' (9 sources) Compile Swift Module 'PerfectHTTPServer' (5 sources) Compile Swift Module 'FirstPerfectProject' (1 sources) Linking ./.build/debug/FirstPerfectProject

오! MySQL이 빌드 되었다. (역시 내 잘못이 아니야... Xcode.. 망할)


MySQL 이 잘 되는지 확인하기 위해 기존 코드에서 MySQL 을 import 해보자.

import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
import MySQL
 
// Create HTTP server.
let server = HTTPServer()
 
// Register your own routes and handlers
var routes = Routes()
routes.add(method: .get, uri: "/", handler: {
        request, response in
        response.setHeader(.contentType, value: "text/html")
        response.appendBody(string: "<html><title>Hello, world!<title><body>Hello, world!</body></html>")
        response.completed()
    }
)
 
// Add the routes to the server.
server.addRoutes(routes)
 
// Set a listen port of 8181
server.serverPort = 8181
 
do {
    // Launch the HTTP server.
    try server.start()
} catch PerfectError.networkError(let err, let msg) {
    print("Network error thrown: \(err) \(msg)")
}

직접 사용하지는 않지만 import 했으니 오류 없이 잘 실행 되어야 겠지? MySQL이 제대로 연결 안 되었다면 오류가 뜰거야. (아마도..)


빌드 후 실행해 보자.

build/debug/FirstPerfectProject
[INFO] Starting HTTP server on 0.0.0.0:8181 with document root ./webroot

오오오오... 성공!


이렇게 package.swift 에 dependency 를 추가하고 빌드만 하면 잘 된다.


그럼 xcode 에서는 왜 안 될까?


Xcode 프로젝트는 구성이 좀 까다롭다. project 파일을 지우지 말고 다시 생성해 보자.

$ swift package generate-xcodeproj
generated: ./FirstPerfectProject.xcodeproj

프로젝트 재생성도 했으니 실행을 해보자~



많은 삽질 끝에 방법을 찾았다.



문서를 읽으면 한번 봤을 내용입니다. Xcode 프로젝트를 생성하고 target이 아닌 project 의 build setting 에 추가로 설정을 해줘야 한다.

Library Search Paths 에 $(PROJECT_DIR) recursive 로 설정한다.



이제 빌드하면 성공적으로 완료한다. 


문제는 이게 dependency 를 추가하고 xcode project를 생성할 때마다 설정해줘야 한다는 것이다.

왜 저 설정을 default로 넣지 않는지 모르겠다..


잊지 말자 $(PROJECT_DIR)



dependency 설정 끝~




Getting Started From Scratch https://www.perfect.org/docs/gettingStartedFromScratch.html


Building with Swift Package Manager https://www.perfect.org/docs/buildingWithSPM.html

신고
Posted by 초프(초보 프로그래머)
Programming/Backend2016.10.15 21:12

Swift 서버 프레임워크가 몇가지 있는데 그중에 가장 먼저 접하게 된 것이 Perfect(https://www.perfect.org) 이다. 처음에는 문서도 부족해서 자세히 알아 볼 기회가 없었다. 오늘 새로운 서버 기능을 추가하기 위해 어떤 프레임워크를 써볼까 하다 갑자기 Perfect가 떠올라 문서를 읽어 보기로 했다.


새로 프로젝트를 시작하는 것은 어려운 일이 아니다. 알고 보니 정말 간단하다. 그 간단한것을 다시 한번  정리해 본다.


Swift3 에 맞춰 Perfect 2가 출시되었다. 이 내용도 Swift3, Perfect2 에 맞춰 작성한다.


새로운 프로젝트를 생성하는 방법에는 크게 2가지가 있다.

두가지 방법도 해보았지만 그래도 역시 처음은 새로 작성하는 것이 좋다고 생각한다. 그래서 그 방법에 따라 작성한다.

프로젝트 폴더를 생성한다. 

$ mkdir FirstPerfectProject
$ cd FirstPerfectProject


Package.swift 파일을 생성한다.

$ vi Package.swift

다음 코드를 붙여 넣는다.

import PackageDescription
 
let package = Package(
    name: "FirstPerfectProject",
    dependencies: [
        .Package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", majorVersion: 2, minor: 0)
    ]
)

name 은 프로젝트 이름이며 빌드 후 생성되는 실행파일 명이다.


dependencies 는 다른 라이브러리를 추가하는 부분이다. 아직 예제에 나온 라이브러리들만 추가해 봤음. gradle, cocoapods 를 사용해봤다면 낯설지 않은 부분이다.


이제 소스 파일을 작성할 폴더를 만들고 간단한 코드를 작성해 보자.

$ mkdir Sources
$ echo 'print("Well hi there!")' >> Sources/main.swift

이제 실행 가능한 조건은 모두 충족되었다. 이제 실행을 해보자.

$ swift build
$ .build/debug/MyAwesomeProject

swift build 를 통해서 프로젝트를 빌드한다. 빌드를 하게 되면 .build 폴더가 생기며 실행 파일은 package 의 name으로 생성된다.

빌드를 하면 dependecies 에 설정된 git에서 소스 파일들을 다운로드 받아서 빌드를 하게 된다. 빌드가성공하면 실행해 보자.

$ .build/debug/FirstPerfectProject
Well hi there!

실행이 되었다. 그런데 이건 REST 가 아니네? 물론 테스트를 위한 코드입니다.

이제 REST 를 테스트해보자.  main.swift를 다시 수정하자.

$ vi Sources/main.swift

기존 코드는 지우고 다음 코드를 붙여넣는다. 

import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
 
// Create HTTP server.
let server = HTTPServer()
 
// Register your own routes and handlers
var routes = Routes()
routes.add(method: .get, uri: "/", handler: {
        request, response in
        response.setHeader(.contentType, value: "text/html")
        response.appendBody(string: "Hello, world!Hello, world!</body></html>")
        response.completed()
    }
)
 
// Add the routes to the server.
server.addRoutes(routes)
 
// Set a listen port of 8181
server.serverPort = 8181
 
do {
    // Launch the HTTP server.
    try server.start()
} catch PerfectError.networkError(let err, let msg) {
    print("Network error thrown: \(err) \(msg)")
}

1초만에 코드를 다 작성했으니 이제 빌드를 해보자.

$ swift build
$ .build/debug/FirstPerfectProject
[INFO] Starting HTTP server on 0.0.0.0:8181 with document root ./webroot

오..! 서버가 실행됐다! localhost:8181 로 접속해 보자.



오.... 코드에 나와 있는 대로 uri 가 / 일때  Hello, world! 가 출력됐다.



이제 문서를 더 읽고 제대로 만들어 보자!!


https://www.perfect.org/docs/handlingRequests.html


https://github.com/PerfectlySoft/Perfect


문서 내용을 다 읽는데 많은 시간이 걸리지 않는다. 2~3시간이면 모든 내용을 읽을 수 있다.


아직 초기 단계라 아쉬운 부분이 많이 있다. ORM, auth 라든지 여러 부분이 아직 지원되지 않는다.


하지만 없다고 사용 못할 수준은 아니다. 마이크로 프레임워크라고 생각하고 사용하자.


실제 프로젝트에 적용할 수 있을지 없을지... 제가 한번 해보겠습니다.


후후....



오늘 내용이 많이 도움이 되었나요? 

더 자세한 내용은...


당신의 몫



신고
Posted by 초프(초보 프로그래머)
Programming/iOS2016.06.22 00:51

ENABLE_BITCODE 설정때문에 발생하는 오류입니다.


coocapods를 사용할 경우 pods안의 프로젝트들의 ENABLE_BITCODE가 true로 설정되어 발생합니다.


podfile 안에 다음 코드를 추가하면 해결됩니다.


post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['ENABLE_BITCODE'] = 'NO'
    end
  end
end

신고
Posted by 초프(초보 프로그래머)
Programming2016.06.17 12:06

Google I/O 에서 Firebase 에 대한 발표 후 Firebase에 대한 언급이 많아지고 있네요.


테스트를 해보니 채팅을 구현하기 정말 쉬울 것 같아서 한번 만들어 보겠습니다.


채팅 구현에 여러가지 기능을 넣을 수 있겠지만 텍스트 대화와 푸시없이 구현하도록 하겠습니다.


사용하는 Firebase의 기능은 Realtime database, Authentication 입니다.



Firebase 프로젝트 설정


https://console.firebase.google.com 접속

`새로만들기` 클릭


프로젝트 `이름`과 `국가/지역` 선택



iOS 앱에 Firebase 추가



`iOS 번들 ID` 입력 (실제 iOS  bundle id 와 같아야 합니다.)



`앱 추가` 버튼을 클릭하면 `GoogleService-info.plist` 파일을 다운로드 받게 됩니다. 나중에 xcode(appcode) project 생성 후에 추가해야 하니 보관해두세요.


이후 나오는 `계속`, `완료` 버튼을 눌러 `iOS 앱에 Firebase 추가` 과정을 끝냅니다.


앱이 추가되었습니다.




회원 인증 설정


어떤 채팅이든 유저를 구분할 수 있는 로그인이 필요하죠.


Firebase에서는 Auth를 이용해 쉽게 회원기능(회원가입/ 로그인)을 구현할 수 있습니다.


Authentication (https://firebase.google.com/docs/auth/)


Authentication 에서는 이메일 인증부터 구글, 페이스북등 다양한 소셜 로그인 기능과 익명 기능이 제공됩니다.

우리 프로젝트는 익명 채팅으로 구현할거에요. 


Anonymous Authentication (https://firebase.google.com/docs/auth/ios/anonymous-auth)


콘솔 메뉴에서 Auth 를 선택합니다.




로그인 방법 설정을 클릭합니다.



  1. Anonymous 선택
  2. 사용 설정 켜기
  3. 저장



사용 설정 완료~!!!




Firebase에서 프로젝트 설정은 끝났습니다. 



iOS 프로젝트 설정


Xcode의 프로젝트 생성은 많이 해보셨을테니 저는 Appcode로 하겠습니다. ㅋ


(사용하는 Appcode의 버전은 2016.2 EAP 입니다.)


앱코드(Appcode) 실행

New project




iOS > Application > Single View Application 선택 후 Next

`Product Name`, `Organization Name`, `Organization Identifier` 입력

언어는 Objective-C, Swift 둘중 편한걸 선택하세요. 저는  Swift입니다

설정이 끝났다면 Finish




Appcode는 cocoapods이 통합되어 있어서 IDE안에서 cocoapods을 사용 가능합니다.

cocoapods podfile 생성



podfile 작성 후 pod install (cocoapods 에서 확인하세요)

platform :ios, '9.0'
use_frameworks!

target 'Shouting' do
  pod 'Firebase/Auth'
  pod 'Firebase/Database'
end


AppDelegate.swift


import UIKit
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
        FIRApp.configure()
        return true
    }
}

Firebase console 에서 받은 GoogleService-Info.plist 를 Shouting 프로젝트에 추가합니다.



빌드하고 실행하면 오류 없이 정상 실행됩니다.


다음은 iOS 앱에서 채팅을 구현해 볼까요?

신고
Posted by 초프(초보 프로그래머)
Programming/iOS2016.03.24 17:14

Extension 사용하는 앱을 upload to app store 할때  90205, 90206 에러가 동시에 발생하는 경우

cocoapods가 원인..


1. Open the (Your App).xcodeproj file (this is the first file on the project navigator pane).
2. Switch to the target for your app extension (on the top left of the middle pane).
3. Go to the Build Phases tab
4. Click the X after "Embed Pod Frameworks"

https://github.com/CocoaPods/CocoaPods/issues/4203

신고
Posted by 초프(초보 프로그래머)
Programming/iOS2016.02.12 11:30

XCode, AppCode 등에서 iOS 앱 개발을 하다가 새로운 오류를 경험했습니다.

시뮬레이터에서 잘 되는데 실제 디바이스에서는 실행이 되지 않고 다음과 같은 오류가 발생했습니다.

AppCode

failed installing application, reason: Error Domain=JBDeviceKitErrprDomain Code=-402620392 "AMDeviceSecureUpgradeApplication failed with err = -402620392(The identity used to sign the executable is no longer valid.)" UserInfo={NSLocalizedDescription=AMDeviceSecureUpgradeApplication failed with err = -402620392(The identity used to sign the executable is no longer valid.)}. Reason: AMDeviceSecureUpgradeApplication failed with err = -402620392(The identity used to sign the executable is no longer valid.)


Xcode

The identity used to sign the executable is no longer valid.
Please verify that your device's clock is properly set, and that your signing certificate is not expired. (0xE8008018).


Device의 시간은 자동설정으로 되어 있었고 현재 시간을 표시하고 있었습니다.

Derived Data를 삭제하고 clean build 를 해봐도 같은 오류만 나올 뿐입니다.

실행 중에 발생한 오류라 인증서 문제를 생각해 볼 수 있는데요. '키체인 접근' 앱에서 확인해 보니 1년뒤 만료였습니다.

그럼 왜 안될까요....


'키체인 접근' 에서 인증서를 자세히 보니 만료된 인증서가 몇개 있었습니다. 같은 Developer의 인증서인데 만료된것과 유효한 것이 같이 있었죠.

만료된 것을 모두 지웠습니다. 그리고 XCode에서 실행하니 인증서 문제가 있다고 fix it 이 떴습니다.

fix 한 후에 실행해 보니 정상 실행됩니다~!


디바이스 실행이 안되는 오류가 있을 때에는 항상 인증서를 확인하자~!

만료된 인증서는 지워버리자~!

신고
Posted by 초프(초보 프로그래머)
Programming/Android2015.12.23 23:27

callback lambda 를 function의 parameter로 넘겨서 사용하려고 합니다.

lambda의 정의는 간단하죠.


함수 정의

fun saveFile(value: Int, callback: (value: Int) -> Void) {

}


함수 사용

functionName(10, { value -> 

})


이렇게 하면 당연히 될줄 알았습니다. 대부분의 언어에서 return 값이 없으면 void 또는 빈값을 해서요...


https://kotlinlang.org/docs/reference/functions.html#unit-returning-functions

return 값이 없을 때는 Unit type 으로 return type 을 지정해야 한다고 되어 있습니다.


함수 정의

fun saveFile(value: Int, callback: (value: Int) -> Unit) {

}


이제 문제 없이 잘 build 됩니다.

Kotlin 에서는 void return 이 아니라 Unit return 해야 합니다.


신고
Posted by 초프(초보 프로그래머)
Programming/Android2015.12.23 11:27

최근에 안드로이드 프로젝트를 새로 시작했습니다.

혼자하고 작은 프로젝트라서 Kotlin으로 하고 있습니다. (유지보수는 누가하지...)

Swift와 비슷해서 시작했는데 다른 부분이 더 많네요.

여러 부분에서 막히고 문서 보고를 반복하다가 방금 찾아 본 것을 남겨봅니다.


Android 에서 새로운 Activity를 실행하려고 할때 Activity 의 class type을 넣어줘야 하는데요.

Java

Intent intent = new Intent(this, MainActivity.Class);


Kotlin

val intent = Intent(this, javaClass())


위 방법은 현재 deprecated 입니다. 

현재 버전에서는 다음과 같이 사용해야 합니다.


Kotlin

val intent = Intent(this, MainActivity:class.java)


https://kotlinlang.org/docs/reference/java-interop.html#getclass

신고
Posted by 초프(초보 프로그래머)