2016년 8월 29일 월요일

PHAssetCollection 을 이용한 PhotoLibrary 앨범 정보 로드 @@ in Swift2.x - Xcode 7.3 iOS 9.3


PhotoLibrary 의 앨범 Data Load

*PHAssetCollection.fetchAssetCollectionsWithType 의 파라미터 값 설명참조
let getAlbums : PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype: .Any, options: options)



모바일에 저장된 사진앨범들의 정보(타이틀이름, 이미지파일)를 로드
사진앨범의 타이틀과 사진 수를 가져오는데 PHAssetCollection 사용하였습니다.

func GetAlbums() {
  let options:PHFetchOptions = PHFetchOptions()
  let getAlbums : PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .Any, options: options)
  // 앨범 정보
  print(getAlbums)
  for i in 0 ..< getAlbums.count{
    let collection = getAlbums[i]
    // . localizedTitle = 앨범 타이틀
    let title : String = collection.localizedTitle
      if(collection.estimatedAssetCount != nil){
        // . estimatedAssetCount = 앨범 내 사진 수
        let count : Int = collection.estimatedAssetCount
        print(count)
        print(title)
      }else{
      }
   }
}


위 코딩을 실행하면 자신이 추가한 앨범들의 타이틀과 사진 장수를 확인 할 수 있다
위 코드를 실행하면 앨범들의 타이틀 정보는 제대로 가져오나 사진 수를 가져오는데 
잘못된 값을 가져오는것을 확인 했다.

<앨범 내 사진 수를 가져오는 포스팅은 아래 링크를 참고>
https://swifteyes.blogspot.kr/2016/08/grid-poster-2-phassets-class-2-in.html


*기본 라이브러리 앨범들의 정보를 확인은 .Album -> .SamrtAlbum 으로 수정하면 앨범 타이틀은
출력이 되나 필요없는 앨범 타이틀까지 출력 되며 사진 수가 알 수 없는 숫자들로  "9223xx20368xx5807" 동일하게 나타난다. 



<subtype 을 이용해 자신이 원하는 앨범선택이 가능하다>


case 
albumRegular

An album created in the Photos app.
case albumSyncedEvent
An Event synced to the device from iPhoto.
case albumSyncedFaces
A Faces group synced to the device from iPhoto.
case albumSyncedAlbum
An album synced to the device from iPhoto.
case albumImported
An album imported from a camera or external storage.
case albumMyPhotoStream
The user’s personal iCloud Photo Stream.
case albumCloudShared
An iCloud Shared Photo Stream.
case smartAlbumGeneric
A smart album of no more specific subtype.
case smartAlbumPanoramas
A smart album that groups all panorama photos in the photo library.
case smartAlbumVideos
A smart album that groups all video assets in the photo library.
case smartAlbumFavorites
A smart album that groups all assets that the user has marked as favorites.
case smartAlbumTimelapses
A smart album that groups all time-lapse videos in the photo library.
case smartAlbumAllHidden
A smart album that groups all assets hidden from the Moments view in the Photos app.
case smartAlbumRecentlyAdded
A smart album that groups assets that were recently added to the photo library.
case smartAlbumBursts
A smart album that groups all burst photo sequences in the photo library.
case smartAlbumSlomoVideos
A smart album that groups all Slow-Mo videos in the photo library.
case smartAlbumUserLibrary
A smart album that groups all assets that originate in the user’s own library (as opposed to assets from iCloud Shared Albums).
case smartAlbumSelfPortraits
A smart album that groups all photos and videos captured using the device’s front-facing camera.
case smartAlbumScreenshots
A smart album that groups all images captured using the device’s screenshot function.

case any
A bit mask representing all possible subtypes.



options 파라미터 값을 이용해 앨범에서 이미지 타입의 파일만 가져오기

let options = PHFetchOptions()
// 옵션 값 설정 : 이미지 타입
options.predicate = NSPredicate(format: "mediaType = %d",PHAssetMediaType.Image.rawValue)
options.sortDescriptors = [ NSSortDescriptor(key: "creationDate", ascending: true) ]
let result : PHFetchResult = PHAsset.fetchAssetsWithOptions(options)
  for i in 0 ..< result.count {
    let asset = result[i] as! PHAsset
    print("date = \(asset.creationDate!)")
    print("location = \(asset.location)")
    print("width = \(asset.pixelWidth), height=\(asset.pixelHeight)")
  }

options.predicate 값에 이미지타입의 파일만 가져오도록 할 수 있다.

특정앨범 선택하기

특정 앨범을 선택할땐 아래처럼 format을 title로하여 앨범 이름 값을 넣어주면 된다

let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", named)


<특정 앨범의 정보를 가져오는 내용을 아래 링크를 참조>
https://swifteyes.blogspot.kr/2016/08/grid-poster-3-phassets-class-3-in.html



2016년 7월 22일 금요일

React.js 란? (리액트 소개 )

React 란?

유저 인터페이스를 만들기 위한 라이브러리 


*React 네이티브 : 모바일 네이티브 앱을 리액트로 만들수 있음


정의

React는 페이스북에서 개발한 유저인터페이스 라이브러리로서 개발자로 하여금 재사용 가능한 UI를 생성 할 수 있게 해줍니다. 이 라이브러리는 현재 페이스북, 인스타그램, 야후, 넷플릭스를 포함한 많은 큰 서비스에서 사용되고 있습니다.
이 라이브러리는 Virtual DOM 이라는 개념을 사용하여 상태의 변함에 따라 선택적으로 유저인터페이스를 렌더링합니다.
따라서, 최소한의 DOM 처리로 컴포넌트들을 업데이트 할 수 있게 해줍니다.

핵심

"Virtual Dom" 

//JQuery
$("#content").html("whatever");
//JavaScript
document.getElementById("content").innerHTML = "whatever"

위처럼 "content" div 내용변경 시 실제 DOM을 직접 처리하는것은 성능도 느리고 비효율적이며 관리하기 힘듭니다. 간단한 처리의 경우 상관없지만 처리해야할 데이터가 많을 경우 관리하기 힘들어집니다.
반면, "Virtual Dom" 은 이를 추상화한 시킨것으로 자바스크립트 객체에 불과하며 그안에서 처리하는것은 이미 렌더링된 HTML 을 실제 DOM API 를 사용해서 처리하는것보다 훨씬 빠릅니다.

특징

1. Virtual DOM 을 사용합니다
2. JSX: JSX 는 JavaScript 의 확장 문법입니다. DOM 엘리먼트들을 만들 때 JavaScript 형식으로 작성해야 하는 것을, XML 과 비슷한 형태로 작성할 수 있게 해줍니다. 이를 사용하는것은 권장사항이고 필수는 아닙니다. 하지만 사용하지 않으면 좀 불편합니다.
3. Components React는 모두 Component 에 대한 것 입니다. React 개발을 할 때는 모든 것을 Component 로서 생각해야 합니다. 컴포넌트에 대한 자세한 내용은 앞으로 작성 될 강좌에서 다루겠습니다.


장점

1. "Virtual Dom" 사용
2. 배우기 간단
    : angular.js, ember.js, backbone.js 에서 데이터를 관리하는 controller 나 HTML 조각인 directive 처럼 코드를 분리하지 않고 "Components" 단 하나만 사용
3. 뛰어난 Garbage Collection 메모리관리 와 성능
4. 서버사이드 렌더링(초기구동 딜레이 & 검색엔진 최적화), 클라이언트사이드 렌더링 둘다 지원
5. 매우 간편한 UI 수정 및 재사용
6. 페이스북 개발자가 만들어 지속적인 업데이트 (밀어주고 있음)
7. 다른 프레임워크나 라이브러리와 혼용가능

단점

1. View only  
   : View 즉, 보여지는 부분만 관여하기 때문에 데이트 데이터모델링, 라우팅, AJAX 등의 기능이 없음
2. IE8 이하 지원 X (IE8 이하지원 하는방법 : React 14버전이하 사용)



  

2016년 7월 6일 수요일

"Could not load the "(null)" image referenced from a nib in the bundle with identifier "" 이슈 해결

<이슈>

"Could not load the "(null)" image referenced from a nib in the bundle with identifier "<app bundle>"

<해결>

위 이슈가 발생 하는것은 스토리 보드 의 imageView 이미지 로드 실패하여 나타나는 메세지이다
imageView 삭제 하거나 이미지 이름 확인하여 수정한다

2016년 6월 27일 월요일

AJAX 에 대해


Ajax(Asynchronous JavaScript and XML, 에이잭스)는 대화식 웹 애플리케이션의 제작을 위해 아래와 같은 조합을 이용하는 웹 개발 기법이다.



  • 표현 정보를 위한 HTML (또는 XHTML) 과 CSS
  • 동적인 화면 출력 및 표시 정보와의 상호작용을 위한 DOM, 자바스크립트
  • 웹 서버와 비동기적으로 데이터를 교환하고 조작하기 위한 XML, XSLT, XMLHttpRequest (Ajax 애플리케이션은 XML/XSLT 대신 미리 정의된 HTML이나 일반 텍스트, JSON, JSON-RPC를 이용할 수 있다).

출처 : 위키백과



- Asynchronos?

해석하면 '비동기적'이다.
'비동기적'이라는 것은, 클라이언트에서 서버에 요청을 보낼 때 요청을 보내놓고 프로그램은 계속 돌아간다는 의미이다. 즉, 먼저 요청한 것에 대한 콜백1 함수가 먼저 실행되지 않는다는 것이다.


- Javascript?

자바스크립트는 웹 브라우저에 대한 스크립트 언어로 만들어진 언어이다. 웹 브라우저에서 출발했기 때문에 본래 서버와 소통하는 기능은 없었으나 AJAX는 가능하다.


- XML?

XML은 데이터 형식의 일종이다.
XML은 'Extensible Markup Language'의 준말이다. 즉 확장가능한 '표시' 언어 라는 것이다.
그렇다면 markup language는 무엇인가? 이것은 데이터에 태그로 항목 표시를 해준다는 것이다. HTML도 마크업 랭귀지의 일종이다.
만약 사람의 키, 나이 등을 표현하고 싶다면 XML에서는
<person>
<height></height>
<age></age>
</person>
이런식으로 작성할 것이다.

출처: http://wherethelightis.tistory.com/14 [초보개발자의 공부공간]


요약 정리 
자바스크립트를 이용해서 비동기식으로 서버와 통신하는 방식. 단 이 때 XML을 이용한다.

AJAX 동작 방식

1. 클라이언트(웹브라우저) 에서 XMLHttpRequest 객체 생성 후 서버로 전송
2. 서버에서 메세지를 받고 메시지에 해당하는 정보를 클라이언트에 응답,  callback 함수 실행
3. callback 함수에 의해 클라이언트 정보 업데이트 (refresh)된다


장단점 정리

장점 : ajax 통신후 데이터로 부분 갱신이 가능하며 필요한 부분만 받기
때문에 통신량이 줄어듭니다

단점 : Js 코드가 늘어나고 너무 많은 통신을 할경우 오히려 과부하를 일으킬수 있습니다.

출처: http://ddo-o.tistory.com/92 [공순이의 블로그]






2016년 6월 22일 수요일

Custom Segue animation left to right, right to left @@ in Swift2.x - Xcode 7.3 iOS 9.3


페이지 이동 시 segue를 사용합니다. 기본적으로 포함된 Segue가 아닌Custom Segue 를 만들어 왼쪽에서 오른쪽, 오른쪽에서 왼쪽으로 나오는 효과를 만들도록 하겠습니다.

동영상을 먼저 보고 진행하겠습니다. 



일단 먼저 프로젝트를 생성 후 ViewController를 2개 추가! 총 3개가 되도록 합니다.



뷰를 구분하기 위해 각각 컬러를 넣고 버튼을 넣어줍니다.



추가된 2개의 ViewController 에 적용할 Swift 파일을 생성합니다. 





위 같은 방법으로 RightViewController ,LeftViewController, CustomSegueClass 파일을 생성합니다.
아래처럼 폴더구성이 되어 있어야 합니다.

이제 RightViewController, LeftViewController 에 클래스를 적용합니다

 - RightViewController -


- LeftViewController -



적용이 끝났다면 버튼에 ViewController 에 있는 Left 버튼과 Right 버튼에 Custom Segue
를 추가하여 뷰가 나타나는 효과부터 만들도록 하겠습니다. 

버튼을 우클릭 후 RightViewController 에 드래그 하면 Segue메뉴가 활성화 됩니다. 
"Custom"을 선택해 주세요


ViewController 와  RightViewController 사이에 이상한 화살표 줄이 생깁니다.
같은 방법으로 Left 버튼에도 Custom Segue를 추가합니다.


아래 이미지 처럼 되도록 ..


이제 여기서 코딩작업을 하겠습니다.
전에 만들어놓은  CustomSegueClass.swift 파일을 열어 아래코드를 넣습니다.


import UIKit

// LeftViewController  뷰 이동
class left: UIStoryboardSegue {
    override func perform()
    {
        //ViewContoroller
        let src = self.sourceViewController as UIViewController
        // LeftViewController
        let dst = self.destinationViewController as UIViewController
        src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
        // LeftViewController 초기 위치
        dst.view.transform = CGAffineTransformMakeTranslation(-src.view.frame.size.width, 0)
        //애니메이션 실행
        UIView.animateWithDuration(0.25,
                                   delay: 0.0,
                                   options: UIViewAnimationOptions.CurveEaseInOut,
                                   animations: {
                                    // 이동할 위치
                                    dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
                                     // ViewController 이동할 위치
                                    src.view.transform = CGAffineTransformMakeTranslation(src.view.frame.size.width/3, 0)                       
            },
                                   completion: { finished in
                                    // 애니메이션 완료 후 실행
                                    src.presentViewController(dst, animated: false, completion: nil)
            }
        )
    }
}

// LeftViewController  뷰 닫기 
class Unwind_left: UIStoryboardSegue {
    override func perform()
    {   
         //ViewContoroller
        let src = self.sourceViewController as UIViewController
        //LeftViewController
        let dst = self.destinationViewController as UIViewController
        src.view.superview?.insertSubview(dst.view, belowSubview: src.view)
        // LeftViewController 초기 위치
        src.view.transform = CGAffineTransformMakeTranslation(0, 0)
         // ViewController 초기 위치
        dst.view.transform = CGAffineTransformMakeTranslation(src.view.frame.size.width/3, 0)
        UIView.animateWithDuration(0.25,
                                   delay: 0.0,
                                   options: UIViewAnimationOptions.CurveEaseInOut,
                                   animations: {
 // LeftViewController 이동할 위치
                                    src.view.transform = CGAffineTransformMakeTranslation(-src.view.frame.size.width, 0)
 // ViewController 이동할 위치
                                    dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
            },
                                   completion: { finished in
                                    // 애니메이션 완료 후 LeftViewController 없애기
                                    src.dismissViewControllerAnimated(false, completion: nil)
            }
        )
    }
    
}

// RightViewController  뷰 이동
class right: UIStoryboardSegue {
    override func perform()
    {
        let src = self.sourceViewController as UIViewController
        let dst = self.destinationViewController as UIViewController
        src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
        dst.view.transform = CGAffineTransformMakeTranslation(src.view.frame.size.width, 0)
        UIView.animateWithDuration(0.25,
                                   delay: 0.0,
                                   options: UIViewAnimationOptions.CurveEaseInOut,
                                   animations: {
                                    dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
                                    src.view.transform = CGAffineTransformMakeTranslation(-src.view.frame.size.width/3, 0)
            },
                                   completion: { finished in
                                    src.presentViewController(dst, animated: false, completion: nil)
            }
        )
    }
}


// RightViewController  뷰 닫기
class Unwind_right: UIStoryboardSegue {
    override func perform()
    {
        let src = self.sourceViewController as UIViewController
        let dst = self.destinationViewController as UIViewController
        src.view.superview?.insertSubview(dst.view, belowSubview: src.view)
        src.view.transform = CGAffineTransformMakeTranslation(0, 0)
        dst.view.transform = CGAffineTransformMakeTranslation(-src.view.frame.size.width/3, 0)
        UIView.animateWithDuration(0.25,
                                   delay: 0.0,
                                   options: UIViewAnimationOptions.CurveEaseInOut,
                                   animations: {
                                    src.view.transform = CGAffineTransformMakeTranslation(src.view.frame.size.width, 0)
                                    dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
            },
                                   completion: { finished in
                                    src.dismissViewControllerAnimated(false, completion: nil)
            }
        )
    }
}



이제 이 클래스 값들을 적용해보자
Right 버튼과 RightViewController 사이에있는  segue를 선택하면 우측 메뉴가뜬다



Identifier =  "rightsegue" 입력하고  Class = Right 를 선택 합니다. (Right 는  CustomSegueClass.swift 파일에 만든 클래스중  RightViewController를 이동시켜주는 클래스 값이다)


같은 방법으로 left버튼과 LeftViewController 사이 segue 에도
Identifier =  "leftsegue" 입력하고  Class = left 를 선택 합니다.

여기까지 진행하셨다면 시뮬레이션 으로 앱을 실행해보세요 버튼 클릭시 View 가 이동하는것을 확인
할 수 있습니다. 이제 BACK 버튼 기능을 넣어보자

ViewController.swift 파일을 열어 코딩을 추가해준다 (이미지 참조)

- 추가해 줄 코딩 -
 @IBAction func returnFromSegueActions(segue:UIStoryboardSegue){
        
    }



다시 Main.storyboard 로 돌아와
RightViewController 에 있는 BACK 버튼을  까지 드래그 한다
코딩이 제대로 되었다면 returnFromSegueActions: 이 뜨는것을 확인 할 수 있다. 선택해준다.




LeftViewController 에 있는 BACK 버튼도 동일하게 진행한다



아래 이미지처럼 RightViewController와 LeftViewController 에  Unwind segue to"Exit" 가 추가되었을 것이다.


RightViewController 에 있는 Unwind segue to"Exit" 를 선택하면 우측에 메뉴가 뜬다




Identifier =  "rightUnwindsegue" 입력하고  Class = Unwind_Right 를 선택 합니다.



같은방법으로 LeftViewController 에 있는 Unwind segue to"Exit" 를 선택하면 우측에 메뉴가 뜨면
Identifier =  "leftUnwindsegue" 입력하고  Class = Unwind_Left 를 선택 합니다.



이제 시뮬레이터로 앱을 실행하여 버튼을 눌러보세요 처음에 첨부했던 영상처럼 되는것을 확인 하실 수 있을겁니다.

참고!!

LeftViewController or RightViewController 에 있는 Unwind segue to"Exit" 를 선택하여 Identifier =  "leftUnwindsegue" 입력하고 클래스를 선택하지 않고 코딩으로 처리 하는 방법입니다.
ViewController.swift에 아래 코딩을 추가해줍니다.


 override func segueForUnwindingToViewController(toViewController: UIViewController, fromViewController: UIViewController, identifier: String?) -> UIStoryboardSegue {
        if let id = identifier{
            if id == "rightsegue" {
                let unwindSegue = Unwind_right(identifier: id, source: fromViewController, destination: toViewController, performHandler: { () -> Void in
                    
                })
                return unwindSegue
            }
            
            if id == "leftsegue" {
                let unwindSegue = Unwind_left(identifier: id, source: fromViewController, destination: toViewController, performHandler: { () -> Void in
                    
                })
                return unwindSegue
            }
            
        }
        return UIStoryboardSegue(identifier: identifier, source: fromViewController, destination: toViewController)
    }









추천 게시물

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

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