[Facebook-Tweaks] 간단하게 살펴보기.

Tweaks Framework by FB

이틀 전 (May.24.2014) 페이스북에서 iOS 프래임워크 하나를 Github에 올리면서 공개를 했다. 해당 프래임워크의 주 기능은 간단하다. 완성된 output의 사소한 속성들을 변경하고 싶을 때 개발자의 손에 걸치지 않고 Runtime으로 수정 가능한 기능을 제공해 준다는 것이다. (아마 무슨 뜻인지 이해가 가질 않을 것으로 생각된다.)

 

“Why do I need it?”

예를 들어 개발자가 애니메이션의 Duration을 정해서 컴파일을 할 것이다. 그런데 모션 그래픽 디자이너라든지 기획자가 보기에 너무 길다던가 맘에 안들 수 있다. 그런데 일일이 개발자 옆에 앉아서 테스트 해보거나 혹은 Bug Tracking System 같은 경로를 통해서 이와 같은 다양한 주문을 시도할 것이다. 하지만 이런 과정은 프로젝트 전체를 보았을 때 상당히 값이 비싼 비용이다. 개발자와 디자이너와 신경전을 한 두번 해본 개발자라면 이 프래임워크의 큰 가치를 깨달을 것이다.

 

“What is ‘Tweaks’?”

Tweaks는 이런 문제점을 해결해주는 좋은 대안이 될 수 있다. 프래임워크를 사용하여 디자이너 혹은 기획자가 직접 UI의 속성을 바꿔가면서 테스트해볼 수 있는 대안이 생겼기 때문이다.

from github

위 gif 이미지를 잠시 보자. ‘Tweaks’라는 UILabel 객체가 화면에 있다. 그런데 어떤 이유에서든지 디자이너가 색상이 맘에 들지 않아서 이를 변경하고자 한다. 일반적으로 디자이너는 개발자에게 이메일을 보내거나 가끔은 자리에 찾아와 색상 변경을 요구하며 이것 저것을 테스트 해보길 요구할 것이다. 이럴 때에 개발자에게 있어서는 얼마나 방해가 되는 일인지 모르며 이런 작은 방해들이 점점 모여서 프로젝트의 비용을 점점 비싸게 만드는 것이다. 그런데 (개발하기 나름이겠지만… ) 본 프래임워크를 적용해서 폰을 흔들면 UI 속성을 바꿀수 있는 TableView가 나온다. 그럼 해당 UI의 속성을 바꿈으로 개발자의 손을 빌리지 않고 이것 저것 tweaking을 할 수 있는 길이 생긴 것이다.

 

“How to use?”

github 페이지에 설치 방법 부터 사용 방법이 잘 나와 있다. 가장 간단히 설치할 수 있는 방법은 CocoaPod를 사용하는 것이다. 소스코드의 순서를  간단하게 보면 다음과 같을 것이다.

  1. 프래임워크 Import 함.
  2. FBTweakViewController를 화면에 뿌릴수 있는 장치를 만듬.
  3. UI 객체 인스턴스의 속성에 바인딩 혹은, ‘FBTweaksValue’를 통해  설정 값 할당 함.

 

프래임워크 Import 하기

  1. #import <FBTweak/FBTweak.h> //FBTweak 기본 헤더파일
  2. #import <FBTweak/FBTweakShakeWindow.h> //폰을 흔들어 FBTweaksViewController를 열고 싶을 때 사용하기
  3. #import <FBTweak/FBTweakInline.h> //FBTweakInline 객체 사용할 때 필요
  4. #import <FBTweak/FBTweakViewController.h> //FBTweakViewController를 presentViewController:animated:completion:을 통해 열때 필요

 

FBTweakViewController를 화면에 뿌릴 장치

변경 가능한 UI 속성을 제어할 UITableView를 화면에 나타내주기 위해서 크게 두 가지 방법이 있을 것이다. 첫 번째는 폰을 흔들어서 나타나게 하는 방법과 임시의 버튼을 만들어서 presentViewController:animated:completion: 메서드를 사용하여 FBTweakViewController 객체를 화면서 나타나게 하는 방법이다. 둘 중에 편한 방법으로 사용하면 될 것이라고 생각 되어진다.

 

UI 속성 바인딩 혹은 설정 값을 Tweaks 함수를 통해 할당

이제 자신이 디자이너들이나 타인들에게 Runtime 때에 변경 가능한 UI 속성을 주고자 하는 코드에 FBTweakValue 함수를 통해서 값을 할당 하든지, FBTweakBind 함수를 통해서 값을 바인딩하면 된다.

  1. //#. Binding 예
  2. UILabel *_label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, _window.bounds.size.width, _window.bounds.size.height * 0.75)];
  3. _label.textAlignment = NSTextAlignmentCenter;
  4. _label.numberOfLines = 0;
  5. _label.userInteractionEnabled = YES;
  6. _label.backgroundColor = [UIColor clearColor];
  7. _label.textColor = [UIColor blackColor];
  8.  
  9. //1-a
  10. _label.font = [UIFont systemFontOfSize:FBTweakValue(@"Content", @"Text", @"Size", 60.0)];
  11.  
  12. //1-b. UILabel 객체의 텍스트 속성을 동적인 값으로 바인딩
  13. FBTweakBind(_label, text, @"Content", @"Text", @"String", @"Tweaks");
  14.  
  15. //1-c. UILabel 객체의 알파 속성을 동적인 값으로 바인딩
  16. FBTweakBind(_label, alpha, @"Content", @"Text", @"Alpha", 0.5, 0.0, 1.0);

‘FBTweakBind’ 함수 사용법은 다음과 같다.

  1. FBTweakBind(object_, property_, category_, collection_, name_, …)

  • object: UI 오브젝트 인스턴스
  • property: 객체 속성명
  • category: TableView에 나올 TableViewCell 명
  • collection: grouped tableView에 표시 될 그룹 명
  • name: 해상 TableViewCell에 표시 될 title 명
  • …: 기본 설정 값

‘FBTweakValue’ 함수 사용법은 다음과 같다

  1. FBTweakValue(category_, collection_, name_, …)

  • category: TableView에 나올 TableViewCell 명
  • collection: grouped tableView에 표시 될 그룹 명
  • name: 해상 TableViewCell에 표시 될 title 명
  • …: 기본 설정 값

그리고 나서 뒤에 오는 값들은 기본 설정 값이다. 이 기본 설정에 따라 TableViewCell에 나타날 설정 가능하도록 해주는 UI가 결정이 된다. 1-b에는 NSString인 ‘Tweaks’로 설정되어 있고, 1-c에서는 세개의 값이 있다. 첫 번째 값인 0.5는 디폴트 값이며, 두번째는 설정 가능한 가장 낮은 값, 세번째 값은 설정 가능한 가장 큰 값이다. 이렇게 설정을 하면 UIStepper를 통해 설정이 가능하게 해준다. 만약에 이 값에 YES와 같은 Bool 값이 들어오면 Toggle 가능한 UISwitch가 들어 올 것이다.

Where to go next?

github에 올라온 소스를 자신의 컴퓨터에 클론하여 예제 앱을 사용해 보면 자신의 프로젝트에 어떻게 사용할지 쉽게 알게 될 것이다. 위에 설명한 것들은 정말 기본적이고 쉬운 것들이고, 더 advance한 사용은 github에 나와있는 설명과 stackoverflow를 통해 알아보기 바란다. 혹자도 기존 프로젝트에 적용해보고 추가할 내용이 생기면 추후에 본 블로그를 더 업데이트 하겠다.

개발자을 위한 iOS7 디자인 Tips

Design?

개발자는 개발만 한다?! 비쥬얼 베이직의 아버지 ‘앨랜 쿠퍼‘가 ‘정신병원에서 뛰쳐나온 디자인‘이라는 책에서 주장했던 내용이다.

하지만 iOS 개발자라면 크게 인정하지 못할 이야기일지도 모른다. 많은 개발자가 cool한 애플의 UI/UX에 매료되어서 개발을 시작한 사람들이 많을 것이기 때문이다. 하지만 나는 전적으로 그의 주장에 공감하는 편이었다. 하지만 요즘 드는 생각은 개발자도 기본적인 디자인 요소에 대해서 알아야한다는 것이 내 생각이다. 아는 것과 모르는 것은 분명 고민을 한 결과물과 고민 없이 만든 결과물과 나오는 효과나 반응이 분명 큰 차이가 있다고 생각하기 때문이다.

다음 가이드는 내가 즐겨찾는 블로그에서 본 내용을 정리해 보았다. 조금이나마 도움이 되길 바란다.

출처 Ray Wenderlich

기본에 집중하라

  • Contrast(대조/대비)

    • 하이라이트: 화면에서 중요한 부분은 강조되어야 한다.
    • Eye candy
    • 상태: 각각의 UI가 터치 가능한지 알려줘야 한다.
    • 가독성: 글씨가 잘보이는 확인하라.

 

 

Screen Shot 2014-03-21 at 12.16.43 PM

Screen Shot 2014-03-21 at 12.16.55 PM

  • Repetition(반복)

Screen Shot 2014-03-21 at 12.19.54 PM Screen Shot 2014-03-21 at 12.20.04 PM

  • Alignment(정렬)

alignment

  • Proximity(근접)

Screen Shot 2014-03-21 at 12.24.16 PM

Screen Shot 2014-03-21 at 12.24.28 PM

  • Typography(글꼴)

    • 최대 3가지 다른 글꼴만 써라.
    • 중앙 정렬은 꼭 필요할 때만 사용하라
    • 글꼴 선택은 최대한 심플하게하라.
    • 글자 리사이징에 대한 대비를 하자.
    • 큰 블럭 글자는 ‘serif’ 글꼴을 쓴다.
    • 적은 양의 글자는 ‘sans serif’ 글꼴을 쓴다.
    • 한 화면에서 대비 되는 글꼴을 써라.(Use contrasting font-families on the same screen.)
    • 한 화면에서 글꼴의 특성을 다양하게 쓰고 싶으면, 한 글꼴로 해라. (글꼴 특성이란, 이텔리체, 볼드체, 사이즈, 색깔등을 말한다.)

Screen Shot 2014-03-21 at 12.25.38 PM

Screen Shot 2014-03-21 at 12.25.47 PM

내용에 집중하라

  • 불필요한 디테일은 삭제하라

  • 크롬을 강조하지 마라 (Navigation bar, tool bar, and etc.)

Screen Shot 2014-03-21 at 12.27.32 PM

  • 심플한 배경

  • 필요하면 크롬을 감춰라

Screen Shot 2014-03-21 at 12.28.30 PM

  • UI 요소를 간단히하라

  • 보더 없는 버튼

  • 색깔을 사용하여 터치 가능한지 않한지를 구분하라

  • 현실적인 3D 디자인을 줄여라

Screen Shot 2014-03-21 at 2.12.02 PM

 

컨텐츠에 집중하기

  • 전체 화면을 써라

  • 컨텐츠도 디자인의 일부이다

Screen Shot 2014-03-21 at 2.14.20 PM

  • 시각적으로 재미있게 만들라.

Screen Shot 2014-03-21 at 2.17.03 PM

 

 

마치며…

이 글을 통해 그동안 느낌으로만 디자인 감각에 충실했던 개발자들에게 기본적인 개념을 심어주었으면 좋겠다. 마지막으로 학부 시절 때 들었던 미술 교양 강사님의 말이 생각을 전하며 마무리를 하고 싶어졌다.

‘디자인 감각은 선천적인 것이 아니다. 절대적으로 후천적으로 개발되는 것이다. 그럼 어떻게 해야 감각이 생길까? 많이 봐라!’

옷을 잘 입는 사람이나 디자인을 잘한다고 하는 사람들이 입을 모아서 하는 말이다. 앱을 많이 써보고 어떤 부분에서 이상한지, 어떤 부분에서 느낌이 좋은지 그냥 지나치지 말고 머리로 한번 더 생각을 해보자. 개발자들의 특성상 앱이나 서비스를 보게 되면 어떻게 작동할 것 같은지 혹은 어떤 기술을 썼는지에 관심을 더 갖게 되어 있다. 하지만 우리도 이젠 디자인이라는 포장 및에 모습만 보려하지말고 어떤 포장을 썼는지에도 관심을 가지고 더욱 User-Friendly한 개발자가 되어야겠다.

[iOS7 DynamicAnimator] 샘플 코드

Screen Shot 2014-03-21 at 11.20.01 AM

iOS7에는 비-게임을 위한 물리엔진이 장착되어 있다. UIDynamicAnimator를 사용하여 간단한 실험을 해볼 수 있다. 코드에 대한 설명은 코드 아래 설명을 참조하라.

  1. #pragma mark – Interface of 'ViewController'
  2.  
  3. @interface ViewController ()<UICollisionBehaviorDelegate>
  4. @end
  5.  
  6. #pragma mark – Implementation of 'ViewController'
  7.  
  8. @implementation ViewController
  9. {
  10.     //#0
  11.     UIDynamicAnimator *_animator;
  12.     UIGravityBehavior *_gravity;
  13. }
  14.  
  15. #pragma mark – Life cycle
  16.  
  17. - (void)viewDidLoad
  18. {
  19.     [super viewDidLoad];
  20.  
  21.     //#1
  22.     UIView *red = [self boostupRedRectangle];
  23.     UICollisionBehavior * collision = [self boostupAnimationAndBehaviorApplyToView:red];
  24.  
  25.     //#2
  26.     UIView *yellow = [self boostupYellowRectangle];
  27.     [self addBarrierOnCollision:collision
  28.                 withBarrierView:yellow
  29.           andBoundaryIdentifier:@"yellow"];
  30.  
  31.     //#3
  32.     UIView *blue = [self boostupBlueRectangle];
  33.     [self addBarrierOnCollision:collision
  34.                 withBarrierView:blue
  35.           andBoundaryIdentifier:@"blue"];
  36. }
  37.  
  38. - (void)didReceiveMemoryWarning
  39. {
  40.     [super didReceiveMemoryWarning];
  41.     // Dispose of any resources that can be recreated.
  42. }
  43.  
  44. #pragma mark – Protocol of 'UICollisionBehaviorDelegate'
  45.  
  46. - (void)collisionBehavior:(UICollisionBehavior*)behavior
  47.       beganContactForItem:(id <UIDynamicItem>)item
  48.    withBoundaryIdentifier:(id <NSCopying>)identifier
  49.                   atPoint:(CGPoint)p
  50. {
  51.  
  52. }
  53.  
  54. #pragma mark – Boostup UIs
  55.  
  56. - (UIView *)boostupRedRectangle
  57. {
  58.     CGRect redFrame = CGRectMake(50, 50, 100, 100);
  59.     UIView *redRectangle = [[UIView alloc] initWithFrame:redFrame];
  60.     [redRectangle setBackgroundColor:[UIColor redColor]];
  61.     [self.view addSubview:redRectangle];
  62.  
  63.     return redRectangle;
  64. }
  65.  
  66. - (UIView *)boostupYellowRectangle
  67. {
  68.     CGRect yellowFrame = CGRectMake(0, 300, 90, 20);
  69.     UIView *yelloRectangle = [[UIView alloc] initWithFrame:yellowFrame];
  70.     [yelloRectangle setBackgroundColor:[UIColor yellowColor]];
  71.     [self.view addSubview:yelloRectangle];
  72.  
  73.     return yelloRectangle;
  74. }
  75.  
  76. - (UIView *)boostupBlueRectangle
  77. {
  78.     CGRect blueFrame = CGRectMake(180, 380, 140, 20);
  79.     UIView *blueRectangle = [[UIView alloc] initWithFrame:blueFrame];
  80.     [blueRectangle setBackgroundColor:[UIColor blueColor]];
  81.     [self.view addSubview:blueRectangle];
  82.  
  83.     return blueRectangle;
  84. }
  85.  
  86. - (UICollisionBehavior *)boostupAnimationAndBehaviorApplyToView:(UIView *)view
  87. {
  88.     //#2-1
  89.     _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
  90.     _gravity = [[UIGravityBehavior alloc] init];
  91.     [_gravity addItem:view];
  92.     [_animator addBehavior:_gravity];
  93.     _gravity.magnitude = 4.0f;
  94.  
  95.     //#2-2
  96.     UICollisionBehavior *collision = [[UICollisionBehavior alloc]
  97.                                       initWithItems:@[view]];
  98.     collision.collisionDelegate = self;
  99.     collision.translatesReferenceBoundsIntoBoundary = YES;
  100.     [_animator addBehavior:collision];
  101.  
  102.     return collision;
  103. }
  104.  
  105. - (void)addBarrierOnCollision:(UICollisionBehavior *)collision
  106.               withBarrierView:(UIView *)barrier
  107.         andBoundaryIdentifier:(NSString *)identifier
  108. {
  109.     CGPoint startPoint = barrier.frame.origin;
  110.     CGPoint endPoint = CGPointMake(barrier.frame.origin.x + barrier.frame.size.width, barrier.frame.origin.y);
  111.     [collision addBoundaryWithIdentifier:identifier
  112.                                fromPoint:startPoint
  113.                                  toPoint:endPoint];
  114. }
  115.  
  116. @end

코드 설명

  1. ‘boostupAnimationAndBehaviorApplyToView:’ 메서드에서 보면 _animator가 애니메이션을 적용할 뷰를 넘기며 생성하는 것을 볼 수있다. 그리고 난 다음 UIGravityBehavior 클래스의 인스턴스를 애니메이터에 추가하는 것으로 해당 뷰에 중력 효과를 적용할 수 있다. 그리고 UICollisionBehavior 객체를 통하여서 빨강 네모를 화면안에 가둬넣을 수 있다.
  2. addBarrierOnCollision:WithBarrierView:AndBoundaryIdentifer: 메서드를 통하여서 UICollisionBehavior에 보이지 않는 장벽을 만들 수 있다. 실제로 화면에서 보이는 장애물은 그저 자리만 지키고 있을 뿐이며 UICollisionBehavior의 객체에 보이지 않는 장해물을 세팅하는 메서드이다.

[iOS7 Motion-Effect] UIInterpolatingMotionEffect 샘플 코드

UIInterpolatingMotionEffect

출처: google 이미지 검색 결과

iOS7을 보면 잠금 화면이라든지 바탕화면이 시각에 따라 움직이는 효과를 볼 수 있을 것이다. 애플에서 쉽게 라이브러리로 제공을 하고 있다.

  1. #import "ViewController.h"
  2.  
  3. @interface ViewController ()
  4.  
  5. @end
  6.  
  7. @implementation ViewController
  8.  
  9. - (void)viewDidLoad
  10. {
  11.     [super viewDidLoad];
  12.  
  13.     //1. Lower bg
  14.     UIImage *lowerImg = [UIImage imageNamed:@"bethel_in_carseat.jpg"];
  15.     UIImageView *lowerbg = [[UIImageView alloc] initWithImage:lowerImg];
  16.     lowerbg.frame = CGRectInset(self.view.frame, -50.0f, -50.0f);
  17.  
  18.     [self.view addSubview:lowerbg];
  19.     [self addMotionEffectToView:lowerbg magnitude:50.0f];
  20.  
  21.     //2. mid bg
  22.     UIImage *midImg = [UIImage imageNamed:@"Background-MidLayer.png"];
  23.     UIImageView *midbg = [[UIImageView alloc] initWithImage:midImg];
  24.     [self.view addSubview:midbg];
  25.  
  26.     //3. header bg
  27.     UIImage *headerImg = [UIImage imageNamed:@"Sarnie.png"];
  28.     UIImageView *headerBG = [[UIImageView alloc] initWithImage:headerImg];
  29.     headerBG.center = CGPointMake(220, 190);
  30.     [self.view addSubview:headerBG];
  31.     [self addMotionEffectToView:headerBG magnitude:-20.0f];
  32. }
  33.  
  34. - (void)didReceiveMemoryWarning
  35. {
  36.     [super didReceiveMemoryWarning];
  37. }
  38.  
  39. #pragma mark – Methods
  40.  
  41. - (void)addMotionEffectToView:(UIView *)view magnitude:(CGFloat)magnitude
  42. {
  43.     UIInterpolatingMotionEffect *horMoffec = nil;
  44.     horMoffec = [[UIInterpolatingMotionEffect alloc]
  45.                  initWithKeyPath:@"center.x"
  46.                  type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
  47.     horMoffec.maximumRelativeValue = @(magnitude);
  48.     horMoffec.minimumRelativeValue = @(-magnitude);
  49.  
  50.     UIInterpolatingMotionEffect *verMoffec = nil;
  51.     verMoffec = [[UIInterpolatingMotionEffect alloc]
  52.                  initWithKeyPath:@"center.y"
  53.                  type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
  54.     verMoffec.maximumRelativeValue = @(magnitude);
  55.     verMoffec.minimumRelativeValue = @(-magnitude);
  56.  
  57.     UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc] init];
  58.     group.motionEffects = @[verMoffec, horMoffec];
  59.  
  60.     [view addMotionEffect:group];
  61. }

[Build Setting::Other Linker Flags] -ObjC와 -all_load의 차이점

Other Linker Flag‘는 XCode 프로젝트에서 서드 파티 라이브러리를 사용할 때 흔히 세팅하는 build setting이다. 해당 플래그는 컴파일 타임 때에 서드 파티의 링크하는 과정에 대한 설정인데, 일반적으로 가장 많이 사용되는 Flag는 ‘-ObjC’와 ‘-all_load’ 이다. 언듯 보면 똑같은 역할을 하는 플래그 처럼 보이지만 다음과 같은 차이가 있다고 한다.

-Objc

This flag causes the linker to load every object file in the library that defines an Objective-C class or category.

해당 값은 링커가 Objective-C 클래스나 카테고리로 정의된 라이브러리에 속한 객체 파일들을 모두 적재하게 해주는 플래그이다.

-all_load

For 64-bit and iPhone OS applications, there is a linker bug that prevents -ObjC from loading objects files from static libraries that contain only categories and no classes. The workaround is to use the -all_load or -force_load flags. -all_load forces the linker to load all object files from every archive it sees, even those without Objective-C code

64 비트 프로젝트나 아이폰 OS 응용 프로그램에서 클래스가 없고 카테고리만 있는 Static 라이브러리의 객체를 -ObjC만 사용하여 적재하려고 할 때 정상 작동을 하지 않는 버그가 있다. 그 버그를 위해 대처 안으로 사용할 수 있는 것이 ‘-all_load‘나 ‘-force_load‘  플래그이다. ‘-all_load‘ 플래그는 모든 객체 파일을 링커로 부터 적재할 수 있도록 하는 플래그이다.

Reference Building Objective-C static libraries with categories

from: http://stackoverflow.com/questions/21844824/difference-between-all-load-and-objc

NSOperation VS Grand Central Dispatch

NSOperation vs. Grand Central Dispatch (GCD)

You may have heard of Grand Central Dispatch (GCD). In a nutshell, GCD consists of language features, runtime libraries, and system enhancements to provide systemic and comprehensive improvements to support concurrency on multi-core hardware in iOS and OS X. If you’d like to learn more about GCD, you can read our Multithreading and Grand Central Dispatch on iOS for Beginners Tutorial.

GCD라는 것을 들어봤을 것이다. 간략하게 설명하자면, GCD는 언어 기능과 런타임 라이브러리, 그리고 iOS와 OS X이 작동하는 멀티-코어 하드웨어 위에서 동시성을 지원해주는 시스템 강화 기능등으로 구성되어 있다. 만약 GCD에 대해 더 자세한 것을 알길 원한다면 블로그 ‘Multithreading and Grand Central Dispatch on iOS for Beginners Tutorial.’를 읽어보길 권유한다.

Before Mac OS X v10.6 and iOS 4, NSOperation and NSOperationQueue were different from GCD and used two completely different mechanisms. Starting with Mac OS X v10.6 and iOS 4, NSOperation and NSOperationQueue were built on top of GCD. As a very general rule, Apple recommends using highest-level abstraction, and then dropping down to lower-levels when measurements show they are needed.

OS X 10.6과 iOS 4 이전 버전에서는 NSOperation과 GCD의 메카니즘은 전혀 달랐다. 하지만 Mac OS X 10.6과 iOS 4 버전에서 부터 NSOperation과 NSOperationQueue는 GCD 위에서 설계되었다. 보통 애플은 개발자들에게 상위 레벨에 추상화 된 레이어를 먼저 사용하길 권유하고 있다. 그리고 나서 필요에 따라 낮은 레벨의 추상화된 기능들을 쓰길 권고한다. 

Here’s a quick comparison of the two that will help you decide when and where to use GCD or NSOperation and NSOperationQueue:

그럼 GCD를 써야 할지 혹은 NSOperation과 NSOperationQueue를 써야 할지 고민하는 당신을 돕기 위한 비교한 내용을 살펴보자.

  • GCD is a lightweight way to represent units of work that are going to be executed concurrently. You don’t schedule these units of work; the system takes care of scheduling for you. Adding dependency among blocks can be a headache. Canceling or suspending a block creates extra work for you as a developer! :]
  • GCD는 동시에 실행하려는 작업 단위를 대표 할 수있는 경량의 방법이다. 해당 작업 단위는 개발자가 직접 스케줄하지 않고 시스템이 스케줄 관리를 해준다. 블럭들 사이에서 의존성을 부여하는 것은 쉽지 않은 일이며, 작업 취소 혹은 일시정시 같은 일을 하기 위해서는 각 개발자가 개인별로 추가해야한다.
  • NSOperation and NSOperationQueue add a little extra overhead compared to GCD, but you can add dependency among various operations. You can re-use operations, cancel or suspend them. NSOperation is compatible with Key-Value Observation (KVO); for example, you can have an NSOperation start running by listening to NSNotificationCenter.
  • NSOperation과 NSOperationQueue는 GCD에 비해 추가적인 기능을 제공하며 여러 operation에 의존성을 부여할 수도 있다. 뿐만 아니라 재사용도 가능하며 취소 혹은 일시정지와 같은 기능도 가능하다. NSOperation은 KVO 기술을 완벽하게 사용할 수 있다. 그래서 NSOperation이 실행되기 시작하면 NSNotificationCenter를 통해 상태 변화에 대한 노티를 받을 수 있다. 

from http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues