IQKeyboardManager

컴퓨터공부/iOS 2020. 11. 30. 11:07 Posted by 아는 개발자

 

iOS에서도 소프트 키보드를 토글하면 UI 뷰 화면을 덮어버리는 문제가 있었다. 안드에서는 그래도 activity 단에서 키보드가 뜰때 어떻게 UI 레이아웃을 변형할지 어느정도 조정이 가능한데 ios에서는 그런게 특별히 없는 것 같다. 키보드가 뜰 때 마다 OS에 물어봐서 keyboard의 height를 알아오고 그에 맞춰서 View를 올려줘야 한다고 하는데.. 매번 하기엔 꽤 번거로운 일이다. 

 

다행히 삽질(?)을 미리 해두고 라이브러리 형태로 배포를 해뒀다고 한다. 라이브러리 이름은 IQKeyboardManager 이고 사용방법도 아주 간단하다. 먼저 cocoapod을 이용해 라이브러리를 임포트 하자.

 

platform :ios, '13.0'

target 'Flash Chat iOS13' do
  use_frameworks!

  pod 'IQKeyboardManagerSwift'

end

 

임포트후 AppDelegate라는 파일에 IQKeyboardManager 클래스를 호출해서 관련 속성을 세팅하자.

 

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        IQKeyboardManager.shared.enable = true
        IQKeyboardManager.shared.enableAutoToolbar = false
        IQKeyboardManager.shared.shouldResignOnTouchOutside = true
        
        return true
    }

 

이렇게만 하고 다시 실행하면 keyboard가 올라옴에 따라서 UI가 자동으로 이동하는 것을 확인 할 수 있다.

 

'컴퓨터공부 > iOS' 카테고리의 다른 글

IQKeyboardManager  (0) 2020.11.30
URLSession  (0) 2020.11.30
Pod  (0) 2020.11.30
tableview  (0) 2020.11.24
codable  (0) 2020.11.23
extension  (0) 2020.11.23

URLSession

컴퓨터공부/iOS 2020. 11. 30. 10:42 Posted by 아는 개발자

JAVA나 C, C++과 마찬가지로 swift 언어의 라이브러리를 이용해서 외부 서버랑 통신을 주고 받을 수 있다. 절차도 비슷한데

 

1. 먼저 통신할 주소를 URL 클래스로 생성하고

2. URLSession 을 만든 다음 

3. URLSession에 아까 만든 주소로 task를 할당하고 응답시 처리할 코드를 입력하고

4. task를 실행한다.

 

func performRequest(_ urlString: String) {
    // 1. Create a URL
    
    if let url = URL(string: urlString) {
        // 2. Create a URL session
        
        let session = URLSession(configuration: .default)
        
        // 3. Give the session a task
        
        let task = session.dataTask(with: url) { (data, response, error) in
            if  error != nil {
                self.delegate?.didFailWithError(error!)
                return
            }
            
            if let safeData = data {
                if let weather = self.parseJSON(safeData) {
                    self.delegate?.didUpdateWeather(self, weather)
                }
            }
        }
        
        // 4. Start the task
        task.resume()
    }
}

'컴퓨터공부 > iOS' 카테고리의 다른 글

IQKeyboardManager  (0) 2020.11.30
URLSession  (0) 2020.11.30
Pod  (0) 2020.11.30
tableview  (0) 2020.11.24
codable  (0) 2020.11.23
extension  (0) 2020.11.23

Pod

컴퓨터공부/iOS 2020. 11. 30. 10:32 Posted by 아는 개발자

안드로이드에서 build.gradle 파일을 수정해 파이어베이스나 외부 깃허브 라이브러리를 다운 받을 수 있었던 것처럼 Xcode에서는 cocoapod과 swiftpackage 라는 툴로 이런 기능을 제공하고 있는데 . swiftpackage는 비교적 최근에 애플에서 만들었고 사용하기도 간편하지만 보편화되지 않아서 아직까지는 cocoapod을 상요하는 추세라고 한다. 이번 포스트에서는 cocoapod을 사용해서 외부 라이브러리를 임포트 하는 방법을 다뤄보려고 한다.

 

1. cocoapod 설치하기 

 

맥북에 cocoapod이 설치되지 않았다면 아래 명령어로 터미널을 켜서 cocoapod을 먼저 설치한다.

sudo gem install cocoapods
pod setup --verbose

 

2. 프로젝트에 pod 초기화하기 

 

개발중인 Xcode 프로젝트의 최상단 위치에서 아래 명령어를 수행한다. 최상단 위치는 *.xcodeproj 이런 파일이 있는 곳을 말한다.

pod init // 프로젝트 최상위 위치에서

 

실행하고나면 Podfile 이라는 루비 언어로 작성된 파일이 생긴다. 

 

platform :ios, '13.0'

target 'Flash Chat iOS13' do
  use_frameworks!

  # Pods for Flash Chat iOS13
end

 

3. 추가하고 싶은 라이브러리 넣기 

 

프로젝트에서 사용하려는 Third party 라이브러리 스크립트를 Podfile에 추가한다. 스크립트는 사용하려는 프로젝트 라이브러리의 github에서 확인 할 수 있다.

 

platform :ios, '13.0'

target 'Flash Chat iOS13' do
  use_frameworks!

  # Pods for Flash Chat iOS13
  pod 'Firebase/Auth'
  pod 'Firebase/Core'
  pod 'Firebase/Firestore'
  pod 'IQKeyboardManagerSwift'

end

 

4. 설치 스크립트 실행

 

라이브러리를 추가했다면 아래 코드를 실행해서 파일을 받아온다. 

 

pod install

 

5. 새로운 프로젝트 실행 

 

4번의 작업이 끝나면 아래 그림처럼 xcworkdspace 라는 확장자를 가진 파일이 만들어진다. 이 파일을 실행해서 프로젝트를 다시 실행한다. 프로젝트에 Pod을 설정하는 작업이기 때문에 처음 Pod을 초기화 할 때만 해주면 된다. 

 

'컴퓨터공부 > iOS' 카테고리의 다른 글

IQKeyboardManager  (0) 2020.11.30
URLSession  (0) 2020.11.30
Pod  (0) 2020.11.30
tableview  (0) 2020.11.24
codable  (0) 2020.11.23
extension  (0) 2020.11.23

애드핏 광고 등록

사이드프로젝트/이기적인 총무 2020. 11. 24. 14:25 Posted by 아는 개발자

옛날에는 구글 애드센스로만 광고를 넣을 수 있었는데 요새는 Dable, Tenting 처럼 다양한 플랫폼에서도 블로그나 앱에 광고를 넣을 수 있게됐다. 그중 주변에 나랑 비슷하게 사이드 프로젝트를 진행중이신 분들이 카카오의 애드핏을 많이 추천하셔서 나도 내가 옛날에 열심히 만든 이기적인 총무애 애드핏으로 광고를 넣어봤다. 훌륭한 개발자가 많은 회사라 그런지(?) 넣는 과정은 어렵지 않고 깔끔했는데 이번 포스트에선 애드핏으로 Android 앱 광고를 넣는 방법을 소개해보려고 한다. 

 

1. 애드핏 라이브러리 임포트 

 

애드핏에선 안드로이드에 광고를 넣기 위한 별도의 라이브러리를 만들어줬다. 이 라인들을 추가해서 새로운 라이브러리를 임포트하자.

 

// app 단위 build.gradle

+ implementation 'androidx.ads:ads-identifier:1.0.0-alpha04'
+ implementation "com.kakao.adfit:ads-base:3.5.2"


// project 단위 build.gradle 

allprojects {
    repositories {
        mavenCentral()
        jcenter()
        + maven { url 'http://devrepo.kakao.com:8088/nexus/content/groups/public/' }

 

2. 인터넷 및 보안 설정 

 

AndroidManifest 파일 일부 수정이 필요하다. 아직 인터넷을 허용하지 않은 앱이라면 인터넷과 네트워크 상태 접근 권한을 추가하고 application 단에서는 networkSecurityConfig 파일을 설정해준다. 이 파일이 이미 있다면 아래 network-security-config 옵션을 추가하고 없으면 새롭게 만들어주면 된다. 경로는 아래 코드처럼 app 폴더 내에 넣어주면 된다.

 

// app/src/main/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.cholab.kwony.jochongmu">
 
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
     <application
         android:name=".JochongmuApp"
         android:allowBackup="true"
         android:icon="@drawable/app_icon"
         android:label="@string/app_name"
         android:supportsRtl="true"
+        android:networkSecurityConfig="@xml/network_security_config"
         android:theme="@style/AppTheme">


// app/src/main/res/xml/network_security_config.xml 

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

 

3. Ad UI 뷰 추가

 

광고를 추가하고 싶은 부분에 BannerAdView UI component를 추가한다. 아까 임포트한 라이브러리에서 구현한 클래스다. 여기서 주의할게 있는데 애드핏의 대시보드에서 설정한 크기보다 크기가 작으면 집계가 안된다고 한다. 이기적인 총무에서는 width를 꽉채우고 height 값을 320:50 의 비율에 맞춰서 조정하게 해서 광고의 크기를 맞췄다.

 

<com.kakao.adfit.ads.ba.BannerAdView
    android:id="@+id/fr_party_ad"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    app:layout_constraintDimensionRatio="320:50"
    app:layout_constraintBottom_toBottomOf="parent"/>

 

4. 광고 호출 

 

BannerAdView 까지 넣었으면 이제 실제로 광고를 호출하면 된다. fragment 또는 activity 단에서 광고를 호출하면 된다. 아래 코드를 보면 setCliendId로 대시보드에서 설정한 광고 id를 넣고 loadAd()를 호출하면 된다. setAdListener를 통해서 광고 호출 후의 작업에 리스너를 등록할 수 있는데 이건 옵션기능이다. 

 

fr_party_ad.run {
    setClientId("광고단위id")
    setAdListener(object: AdListener {
        override fun onAdLoaded() {
            JoLog.d("ad loaded")
        }

        override fun onAdFailed(p0: Int) {
            JoLog.d("failed to upload")
        }

        override fun onAdClicked() { }
    })
    loadAd()
}

광고단위는 대쉬보드에서 아래 그림의 빨간색에 있는 값이다. 알파벳과 숫자로 섞여있는 난해한 키 값처럼 생겼다.

광고단위 ID. 타인에게 노출하면 안된다.

5. 생성주기 별로 리스너 등록 

 

왠지는 모르겠으나 안드로이드 생성 주기별로 콜백을 불러줘야한다고 한다. 안그러면 안된다고 한다.

 

override fun onPause() {
    super.onPause()
    fr_main_ad?.pause()
}

override fun onResume() {
    super.onResume()
    fr_main_ad?.resume()
}

override fun onDestroy() {
    super.onDestroy()
    fr_main_ad?.destroy()
}

 

6. 완성 

 

문제 없이 끝내면 아래 그림처럼 광고를 호출하게 된다. 구현하고 승인 전까지는 카카오 비즈니스 광고가 뜨는데 승인 후에는 카카오 애드핏에서 알아서 광고를 내려준다. 몇 일 전까지는 무신사 광고만 나왔었는데 오늘은 스푼라디오 광고가 나오고 있다. 어떤 메커니즘인지 궁금해지네.

 

7. 적용후

 

수입은 얼마 안나오지만(지금까지 편의점 캔커피 만큼도 벌지 못했다) 광고를 넣으니 책임감이 더 막중해진 느낌이다. UX도 개선하고 싶고 사소한 버그들도 어서 고치고 아이콘들도 더 이쁘게 바꿔보고 싶고 ios 버전도 만들어서 다른 유저들한테도 홍보하고 싶다. 역시 돈이 걸려있다면 사람의 마음 가짐이 달라지는걸까? ㅋㅋ

2418 insertion(+), 780 deletions(-)

 

윗 문장의 두 숫자는 2년간 회사에서 소프트웨어 개발하면서 회사 깃허브에 내가 추가하고 삭제한 라인의 수다. 순수히 개발과 관련된 코드만 카운트하고자 리팩토링과 주석을 추가한 커밋, 오픈 소스의 일부 기능을 빌려온 코드, Initial Commit 같은 것은 빼고 기능 추가 또는 버그 픽스를 위한 커밋만 추려냈다. 물론 이중에서도 다른 사람의 코드가 포함될 수 있으나 역으로 다른 사람의 커밋에도 내 코드가 포함돼 있을 것이니 어느 정도 상쇄한다고 보자. 별로 큰 차이는 없을 것이다.

 

제타위키에 따르면 휴가를 고려하지 않고 한국인이 1년간 일하는 날은 249일 정도가 된다고 한다. 여기서 2를 곱하면 난 2년간 최대 458일 일했을 것이다. 이 숫자를 내가 추가하고 삭제한 커밋의 라인 수로 나누면 평균 하루 5.27 라인을 추가하고 1.70 라인을 삭제한 결과가 나온다. 추가와 삭제를 합해서 하루에 7라인을 만들고 줄인 셈이다. 너무 적지 않은가? C언어로 "Hello World"만 출력해도 엔터를 포함해서 다섯 라인은 족히 나온다. 그동안 나는 무엇을 하면서 시간을 보내고 있었던 걸까?

 

프로그래밍을 업무 별로 나누면 코드를 짜고 리뷰 하고 받는 시간은 20~30%에 지나지 않는다. 나머지 시간은 기능을 만드는데 쓴다. 단 단순히 동작하는 코드를 만드는데 그치지 않는다. 기능을 만든다는 것은 퍼포먼스를 최적화하고 추후 변경될 소지가 있는 부분들을 예상하며 보안의 위협이 될만한 부분들을 처리할 수 있는 안정적인 코드를 만드는 것이다. 한 가지 기능을 개발할 때는 예상외로 고려할 것이 많다.

 

스마트폰의 헬스케어 앱을 만드는 개발자를 예로 들어보자. 개발자는 갤럭시 S9 이용해 걸음 수를 측정하는 기능을 만들어야 한다. 걸음수를 측정할 수 있는 알고리즘은 이미 마련되어 있으니 따로 논문을 찾아볼 필요는 없다. 이것을 구현해 스마트폰의 센서로부터 값을 읽어온 후 걸음수를 카운트한 후 메인 모듈에 값을 전달하기만 하면 된다. 아마 안드로이드에 익숙한 개발자라면 한 주 안에 끝낼 수 있을 것이다. 이미 마련된 알고리즘의 의사 코드(pseudo code)를 자바로 옮기고 값에 해당하는 변수에 센서의 값을 읽도록 바꾸면 된다. 노이즈가 좀 있겠지만 이럴 때는 센서 API에서 읽어온 값을 미세하게 조정하면 된다. 2~3일 코드 짜고 하루 이틀 정도 걸어보면서 디버깅하면 충분할 것이다.

 

만약 '디바이스가 바뀌는 경우'가 있다면 어떨까? 개발자의 코드 덕분에 서비스가 번창해서 갤럭시 S9뿐만 아니라 V30에서도 서비스를 제공해야 한다고 해보자. 가장 단순한 방법은 똑같은 코드를 그대로 V30에서 쓸 수 있는 코드로 바꾸면 된다. 단 예전에 갤럭시 S9에서 미세한 오류를 조정하기 위해 넣었던 수식들은 일일이 찾아서 치환해야 한다. 땜빵 코드이기에 이 정도의 삽질은 감수해야 한다. 그런데 중국시장에까지 진출해 샤오미 폰과 하웨이 폰에서도 지원해야 한다면 매번 코드를 바꿔서 끼워 넣을 것인가? 해마다 새로운 모델이 우후죽순으로 나오는데 모두 다 이런 방식으로 바꿔야 한다면 앞이 깜깜하다.

 

눈 앞에 있는 문제만 해결한 소프트웨어는 장기적으로 개발자를 괴롭힌다.

 

이런 삽질을 미연에 방지하기 위해선 개발 초기에 디바이스의 변경 가능성을 검토했어야 했다. 개발 당시에는 갤럭시 S9이 주 타깃이지만 서비스를 제공하는 업체라는 점에서는 헬스케어 앱은 다른 모델도 지원할 가능성이 아주 농후했다. 이점을 고려한 개발자는 알고리즘 함수의 인자에 미세한 오류를 조정한 센서 값을 넣을 수 있게 해 모델에 의존하지 않는 코드를 만들었을 것이다. 매번 똑같은 코드를 만들 필요가 없었다. 디바이스가 추가되면 몇회 디버깅 해본 후 미세 조정한 센서의 값만 수식으로 만들어주면 된다.

 

회의하다보면 칠판은 어느새 그림처럼 변한다

 

OS나 클라우드 서비스처럼 플랫폼의 역할을 하는 소프트웨어는 기능을 구현하는 것도 만만치 않다. 그래서 동료들과 회의를 하며 아이디어를 도출하는 것뿐만 아니라 개발자들은 업무 중에 책과 논문을 읽어가며 공부하고 때론 관련 컨퍼런스에 참가해 다른 개발자에게 조언을 구하기도 한다. 기능 구현 방법에 대한 검토가 끝나면 여기서 파생될 수 있는 문제점들을 검토하는 시간이 된다. 현재 구현하려는 기능이 다른 팀의 모듈에 영향을 줄 수 있지는 않은지, 다른 플랫폼과 통 방법은 적절한지, 추후 외부 모듈 통신 인터페이스가 변경될 소지가 있는지 등 소프트웨어에서 나올 수 있는 모든 복합적인 요소를 고려하는 시간이다. 충분한 검토가 이뤄질수록 완성도 있는 소프트웨어가 만들어진다.

 

코드는 여러 복합적인 요소를 충분히 고려하고 만만의 준비를 마쳤을 때 작성한다. 코드 작성은 여태껏 찾아온 솔루션을 프로그래밍 언어로 옮기는 과정일 뿐이다. 작성한 코드가 버그 없고 가독성이 훌륭하며 의도한대로 동작한다면 라인의 수가 많든 적든 중요하지 않다. 더 안정적이고 더 지속가능하며 더 퍼포먼스가 좋은 소프트웨어일수록 코드 한 줄을 짜는 데는 오랜 시간이 소요된다.

'이런저런생각 > 브런치' 카테고리의 다른 글

코드 한 줄 짜는데 시간이 오래 걸린다  (0) 2020.11.24