2016년 11월 25일 금요일

MFMailComposeViewController 로 이메일 보내기 (Send Email) @@ in Swift3 - Xcode 8.0 iOS 10

MFMailComposeViewController 를 이용해 이메일 보내기 !

//import MessageUI 하기
  import UIKit
  import MessageUI

// MFMailComposeViewControllerDelegate 추가 
class OptionpageViewController: UIViewController, MFMailComposeViewControllerDelegate {

    override func viewDidLoad() {
         super.viewDidLoad()

    }
     ...
}


//Email Send 함수 설정
func EmailSend(_ sender: AnyObject){
     let mailVC = MFMailComposeViewController()
     mailVC.mailComposeDelegate = self
     mailVC.setToRecipients(["yourEmail@xxx.xx"])
     mailVC.setSubject("")
     mailVC.setMessageBody("Your messagge", isHTML: false)
     present(mailVC, animated: true, completion: nil)
// 2016.12.2 수정  앱 심사중에  네트워크 충돌로 거부사유 됨 아래코드 활용
    if MFMailComposeViewController.canSendMail(){
       self.present(mailVC, animated: true, completion: nil)
    }
        }

       
}


// mailComposeController 델리게이트 메소드 활용하여 창 닫기 함수 설정

func mailComposeController(_ controller: MFMailComposeViewController,
didFinishWith result: MFMailComposeResult, error: Error?) {
     controller.dismiss(animated: true, completion: nil)
}



2016년 11월 21일 월요일

UIActivityViewController 를 이용한 데이터 share @@ in Swift3 - Xcode 8.0 iOS 10

UIActivityViewController

// 데이터를 배열에 담는다
let  textToShare  = "share Text"
let  shareimg  : UIImage = UIImage(named: "image1.png")!


let shareItems : Array = [shareimg!!, textToShare] as [Any]  // <- 서로 타입이 달라 Any 가 붙는다

let activityViewController:UIActivityViewController = UIActivityViewController(activityItems: shareItems, applicationActivities: nil)

// share 타입 추가 하기 ( 타입을 지정해주지 않아도 기본적인건 추가되는듯..)
activityViewController.excludedActivityTypes = [UIActivityType.print, UIActivityType.postToWeibo, UIActivityType.copyToPasteboard, UIActivityType.addToReadingList, UIActivityType.postToVimeo]



self.present(activityViewController, animated: true, completion: nil)


* 타입 참조

유형 이름요약
UIActivityType.postToFacebookFacebook에 올리기
UIActivityType.postToTwitterTwitter에 올리기
UIActivityType.message메시지 보내기
UIActivityType.mail이메일 보내기
UIActivityType.print프린트 대화를 시작
UIActivityType.copyToPasteboard클릭 보드에 붙여 넣기
UIActivityType.assignToContact연락처를 호출
UIActivityType.saveToCameraRoll카메라 롤에 저장
UIActivityType.addToReadingListSafari의 읽기 목록에 추가
UIActivityType.postToFlickrFlickr에 게시
UIActivityType.postToVimeoVimeo에 게시
UIActivityType.postToWeiboWeibo 에 게시
UIActivityType.postToTencentWeiboTencent 에 게시

2016년 11월 15일 화요일

Swift3 AdMob (애드몹) 적용 @@ in Swift3 - Xcode 8.0 iOS 10

앱에 AdMob 적용 시 준비해야할 사항

1. AdMob 가입 

2. AdMob 적용할 앱

3. GoogleMobileAds.framework

AdMob 가입 절차를 따르다 보면 GoogleMobileAds.framework 다운로드까지 할 수 있다.
AdMob에 가입했으면 앱을 등록 하고 광고를 만들어준다.

제대로 했다면 아래 이미지 처럼 광고가 추가 되었음을 확인 할 수 있다.



Xcode 에 GoogleMobileAds.framework 를 추가하고 코드를 입력한다


import UIKit
// GoogleMobileAds 추가
import GoogleMobileAds
// Delegate 추가


class ViewController: UIViewController, GADBannerViewDelegate {
// Main.storyboard 에서 뷰를 생성하여 아울렛을 사용해도 상관 없다
let bannerView: GADBannerView = GADBannerView(adSize: kGADAdSizeSmartBannerPortrait)
// adSize의 경우 여러모드를 제공하니 확인하여 필요한 모드를 사용한다

  override func viewDidLoad() {
    super.viewDidLoad()
    bannerView.delegate = self
    // 광고 단위 ID 를 넣으면 된다
    bannerView.adUnitID = "ca-app-pub-6xxxxxxxx60/1xxxxxxx34"
    bannerView.rootViewController = self
    let gadRequest:GADRequest = GADRequest()
    gadRequest.testDevices = [kGADSimulatorID]
    bannerView.load(gadRequest)
    // 배너뷰 사이즈 설정
    bannerView.frame = CGRect(x: 0, y: view.bounds.height - bannerView.frame.size.height, width: bannerView.frame.size.width, height: bannerView.frame.size.height)
    self.view.addSubview(bannerView)
  }
}


2016년 11월 10일 목요일

guard 구문 사용 @@ Swift3.0

guard 구문

if 구문과 마찬가지로 주어진 표현식의 결과가 참인지 거짓인지에 따라 구문의 실행 여부를 결정짓는 방식의 조건문입니다.
if 구문과의 차이점은  guard 구문에는  else 블록이 필수이지만, 표현식의 결과가 참일 때 실행되는 블록이 없다는 점입니다.

guard 구문은 주로 후속 코드들이 실행되기 전에 반드시 특정 조건을 만족하는지 확인하는 용도로 사용합니다. 다시 말해 guard 구문은 특정 조건을 만족하지 않은 채 후속 코드를 실행하면 심각한 오류가 발생하는 경우, 그 대신 전체 구문을 조기 종료하기 위한 목적으로 사용됩니다.
따라서 guard 구문의 else 블록을 작성할 때에는 이후의 코드가 더 진행되지 않게 처리하는 작업이 필요합니다. 주로 함수나 메소드에서 return 구문이 이 역할을 합니다

<표현식>
guard 특정 조건 또는 표현식 else{
        실행할 구문(조건 또는 표현식의 결과가 false일 때)
}
 
<예제 코드>
func divide(base:Int){
    
    guard base != 0 else{
     print("x")
        return
    }
    let resutl  = 100 / base
    print(resutl)
    
}
divide(base: 0// "x"

divide(base: 20) // 5

2016년 11월 9일 수요일

Today Extension (widget) 연결된 App 열기 @@ in Swift3.0

Today Extension (widget)이 실행되고 storyboard 가 나타났을때
View 나 button 을 클릭하여 연결된 앱을 열고자 할때 사용하는 방법이다.

일단 extensionContext 속성을 사용해야한다
일단 Today Extension 을 생성 했다는 가정하에 설명하도록 하겠다
Today Extension에서 앱을 실행하기 위해선  해당 앱의 CFBundleURLSchemes 값을 정의 해야한다
일단 해당앱의 Info.plist 파일을 Source Code 로 연다




위 이미지 처럼 코드를 추가해준다
설명하자면  앱을 식별할 수 있도록 App 의 URLName 과  URLSchemes 을 선언해주는 것이다
Today Extension 에서 아래 함수 (openApp()를 호출할 수 있도록 버튼이나 뷰를 만들고
TodayViewController 에 아래 메소드를 추가한다

func openApp(_ sender: AnyObject) {
    // UrlName = com.Tester.openApp    <ㄱ
    // URLSchemes = openApp            <-  두값이 같아야함
    let url:NSURL? = NSURL(string: "openApp:")  
    // : <- 잊지말고 붙여넣자

    if let appurl = url{

    self.extensionContext!.open(appurl as URL, completionHandler: nil)

    }

}

다시 빌드하여 View 나 button을 터치하여 테스트하면 앱이 열리는 것을 확인 할 수 있다.



2016년 11월 8일 화요일

Today Extension View(.compact, .expanded) Size Change (Widget Extension height 값 바꾸는 방법) @@ in Swift3 - Xcode 8.0 iOS 10

swift 3에서는 widget의 DisplayMode 에 따라 높이 값이 조절 된다
모드는 2가지로 나뉜다 

.compact (defult) : 높이값이 정해져 있어 조절 불가능 (110px)
.expanded : 자신이 높이값을 정할수 있다  단, Show more / less 버튼이 활성화 된다

 DisplayMode 를 expanded 로 하고 싶다면 TodayViewController.swift 에 아래 코드를 추가 해준다

override func viewDidLoad() {
  super.viewDidLoad()
  self.extensionContext?.widgetLargestAvailableDisplayMode = NCWidgetDisplayMode.expanded
}

그리고 아래 메소드를 추가해준다


func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize){
  if (activeDisplayMode == NCWidgetDisplayMode.compact) {
  // Show less
  self.preferredContentSize = maxSize; // 110 px
  } else {
  // Show more
  self.preferredContentSize = CGSize(width: maxSize.width, height: 200)
} }

                  

빌더해서 Show Less / Show More 버튼을 눌러서 뷰 사이즈가 바뀌는것을
확인해보자

2016년 11월 1일 화요일

photoLibrary 접근 시 발생하는 이슈 @@ in Swift3 - Xcode 8.0 iOS 10

iOS 10으로  업데이트 되면서 사용자 데이터 접근 시 변경된 내용이 있다

예를 들어 사용자의 photoLibrary 에 접근 시  이슈가 발생 한다

<이슈 내용>
This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app uses this data.This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app uses this data. 



업데이트가 되면서 사용자 데이터 접근하려면 사용목적을 따로 입력해야 한다

photoLibrary 경우 접근을 하려면 NSPhotoLibraryUsageDescription키를 사용한다.

Info.plist파일을 열어
위 이미지 처럼 Key 값을 추가 하고 사용목적을 입력한다

앱을 실행하여 photoLibrary 에 접근 하면 이슈가 해결되고 알럿창이 뜬다

photoLibrary 외에도  미디어 라이브러리, 카메라, 연락처, 위치정보 등 사용자 데이터에 접근 시 필수적으로 사용목적을 입력해야한다.



아직 정확한 원인이 파악되지 않았으나 Library 접근하는 view에서  디버깅 시 아래 같은  이슈가 발생하는 경우가 있다

<이슈 내용>
Class PLBuildVersion is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/AssetsLibraryServices.framework/AssetsLibraryServices (0x1198125910) and /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/PhotoLibraryServices.framework/PhotoLibraryServices (0x11c77c210). One of the two will be used

임시방편으로 아래코드처럼  AssetsLibrary framework를 import 해주면 디버깅에서 아래오류를 없앨수 있다

import AssetsLibrary 



추천 게시물

애플 개발자 등록방법 2016년 5월 8일 기준!!

애플 개발자 등록 절차 1. 개발자 등록 페이지 이동    애플 개발자 로그인 > Account 페이지 이동 > 하단 영역 클릭 (이미지 참조)   >> Enroll 클릭 >> 무조건 승인!! ...