Skip to content

Commit

Permalink
Merge pull request ReactiveCocoa#1251 from TimurBK/master
Browse files Browse the repository at this point in the history
Added RAC support for UIImagePickerController.
  • Loading branch information
kastiglione committed May 21, 2014
2 parents aa8706f + 301e5aa commit e091e74
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 0 deletions.
12 changes: 12 additions & 0 deletions ReactiveCocoaFramework/ReactiveCocoa.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
1EC06B18173CB04000365258 /* UIGestureRecognizer+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EC06B16173CB04000365258 /* UIGestureRecognizer+RACSignalSupport.m */; };
27A887D11703DC6800040001 /* UIBarButtonItem+RACCommandSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A887C81703DB4F00040001 /* UIBarButtonItem+RACCommandSupport.m */; };
27A887D21703DDEB00040001 /* UIBarButtonItem+RACCommandSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 27A887C71703DB4F00040001 /* UIBarButtonItem+RACCommandSupport.h */; settings = {ATTRIBUTES = (Public, ); }; };
3C163DE218FE843D001AA13E /* UIImagePickerController+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C163DE018FE843D001AA13E /* UIImagePickerController+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; };
3C163DE318FE843D001AA13E /* UIImagePickerController+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C163DE118FE843D001AA13E /* UIImagePickerController+RACSignalSupport.m */; };
3C80F51F18FFCF810018AE41 /* UIImagePickerControllerRACSupportSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C80F51D18FFCF810018AE41 /* UIImagePickerControllerRACSupportSpec.m */; };
4925E806181BCC71000B2FEE /* NSControllerRACSupportSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 4925E805181BCC71000B2FEE /* NSControllerRACSupportSpec.m */; };
554D9E5D181064E200F21262 /* UIRefreshControl+RACCommandSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 554D9E5B181064E200F21262 /* UIRefreshControl+RACCommandSupport.h */; settings = {ATTRIBUTES = (Public, ); }; };
554D9E5E181064E200F21262 /* UIRefreshControl+RACCommandSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 554D9E5C181064E200F21262 /* UIRefreshControl+RACCommandSupport.m */; };
Expand Down Expand Up @@ -625,6 +628,9 @@
1EC06B16173CB04000365258 /* UIGestureRecognizer+RACSignalSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIGestureRecognizer+RACSignalSupport.m"; sourceTree = "<group>"; };
27A887C71703DB4F00040001 /* UIBarButtonItem+RACCommandSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIBarButtonItem+RACCommandSupport.h"; sourceTree = "<group>"; };
27A887C81703DB4F00040001 /* UIBarButtonItem+RACCommandSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIBarButtonItem+RACCommandSupport.m"; sourceTree = "<group>"; };
3C163DE018FE843D001AA13E /* UIImagePickerController+RACSignalSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImagePickerController+RACSignalSupport.h"; sourceTree = "<group>"; };
3C163DE118FE843D001AA13E /* UIImagePickerController+RACSignalSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImagePickerController+RACSignalSupport.m"; sourceTree = "<group>"; };
3C80F51D18FFCF810018AE41 /* UIImagePickerControllerRACSupportSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIImagePickerControllerRACSupportSpec.m; sourceTree = "<group>"; };
4925E805181BCC71000B2FEE /* NSControllerRACSupportSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSControllerRACSupportSpec.m; sourceTree = "<group>"; };
554D9E5B181064E200F21262 /* UIRefreshControl+RACCommandSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIRefreshControl+RACCommandSupport.h"; sourceTree = "<group>"; };
554D9E5C181064E200F21262 /* UIRefreshControl+RACCommandSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIRefreshControl+RACCommandSupport.m"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1083,6 +1089,7 @@
5FAF5261174D4D8E00CAC810 /* UIBarButtonItemRACSupportSpec.m */,
5EE9A79A1760D88500EAF5A2 /* UIButtonRACSupportSpec.m */,
D066C795176D262500C242D2 /* UIControlRACSupportSpec.m */,
3C80F51D18FFCF810018AE41 /* UIImagePickerControllerRACSupportSpec.m */,
5564542318107275002BD2E4 /* UIRefreshControlRACSupportSpec.m */,
);
name = iOS;
Expand Down Expand Up @@ -1378,6 +1385,8 @@
5F70B2AE17AB1829009AEDF9 /* UIDatePicker+RACSignalSupport.m */,
1EC06B15173CB04000365258 /* UIGestureRecognizer+RACSignalSupport.h */,
1EC06B16173CB04000365258 /* UIGestureRecognizer+RACSignalSupport.m */,
3C163DE018FE843D001AA13E /* UIImagePickerController+RACSignalSupport.h */,
3C163DE118FE843D001AA13E /* UIImagePickerController+RACSignalSupport.m */,
554D9E5B181064E200F21262 /* UIRefreshControl+RACCommandSupport.h */,
554D9E5C181064E200F21262 /* UIRefreshControl+RACCommandSupport.m */,
5F70B2B617AB1856009AEDF9 /* UISegmentedControl+RACSignalSupport.h */,
Expand Down Expand Up @@ -1718,6 +1727,7 @@
D077A16E169B740200057BB1 /* RACEvent.h in Headers */,
6EA0C08216F4AEC1006EBEB2 /* NSObject+RACDeallocating.h in Headers */,
27A887D21703DDEB00040001 /* UIBarButtonItem+RACCommandSupport.h in Headers */,
3C163DE218FE843D001AA13E /* UIImagePickerController+RACSignalSupport.h in Headers */,
1EC06B17173CB04000365258 /* UIGestureRecognizer+RACSignalSupport.h in Headers */,
D090768017FBEADE00EB087A /* NSURLConnection+RACSupport.h in Headers */,
5EE9A7931760D61300EAF5A2 /* UIButton+RACCommandSupport.h in Headers */,
Expand Down Expand Up @@ -2043,6 +2053,7 @@
5FAF523E174D4D3200CAC810 /* NSEnumeratorRACSequenceAdditionsSpec.m in Sources */,
5FAF523F174D4D3600CAC810 /* NSNotificationCenterRACSupportSpec.m in Sources */,
D090768B17FBECBF00EB087A /* NSURLConnectionRACSupportSpec.m in Sources */,
3C80F51F18FFCF810018AE41 /* UIImagePickerControllerRACSupportSpec.m in Sources */,
5FAF5240174D4D5600CAC810 /* NSObjectRACDeallocatingSpec.m in Sources */,
5FAF5241174D4D5600CAC810 /* NSObjectRACLiftingSpec.m in Sources */,
5FAF5242174D4D5600CAC810 /* NSObjectRACPropertySubscribingExamples.m in Sources */,
Expand Down Expand Up @@ -2271,6 +2282,7 @@
D0E9678E1641EF9C00FCFF06 /* RACSequence.m in Sources */,
D0E967921641EF9C00FCFF06 /* RACStringSequence.m in Sources */,
D013A3F31807B9690072B6CE /* RACDynamicSignal.m in Sources */,
3C163DE318FE843D001AA13E /* UIImagePickerController+RACSignalSupport.m in Sources */,
D0D487041642550100DD7605 /* RACStream.m in Sources */,
D013A3DA1807B5ED0072B6CE /* RACErrorSignal.m in Sources */,
D0EE284E164D906B006954A4 /* RACSignalSequence.m in Sources */,
Expand Down
1 change: 1 addition & 0 deletions ReactiveCocoaFramework/ReactiveCocoa/ReactiveCocoa.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
#import "UIControl+RACSignalSupport.h"
#import "UIDatePicker+RACSignalSupport.h"
#import "UIGestureRecognizer+RACSignalSupport.h"
#import "UIImagePickerController+RACSignalSupport.h"
#import "UIRefreshControl+RACCommandSupport.h"
#import "UISegmentedControl+RACSignalSupport.h"
#import "UISlider+RACSignalSupport.h"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// UIImagePickerController+RACSignalSupport.h
// ReactiveCocoa
//
// Created by Timur Kuchkarov on 28.03.14.
// Copyright (c) 2014 GitHub. All rights reserved.
//

#import <UIKit/UIKit.h>

@class RACDelegateProxy;
@class RACSignal;

@interface UIImagePickerController (RACSignalSupport)

/// A delegate proxy which will be set as the receiver's delegate when any of the
/// methods in this category are used.
@property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy;

/// Creates a signal for every new selected image.
///
/// When this method is invoked, the `rac_delegateProxy` will become the
/// receiver's delegate. Any previous delegate will become the -[RACDelegateProxy
/// rac_proxiedDelegate], so that it receives any messages that the proxy doesn't
/// know how to handle. Setting the receiver's `delegate` afterward is considered
/// undefined behavior.
///
/// Returns a signal which will send the dictionary with info for the selected image.
/// Caller is responsible for picker controller dismissal. The signal will complete
/// itself when the receiver is deallocated or when user cancels selection.
- (RACSignal *)rac_imageSelectedSignal;

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// UIImagePickerController+RACSignalSupport.m
// ReactiveCocoa
//
// Created by Timur Kuchkarov on 28.03.14.
// Copyright (c) 2014 GitHub. All rights reserved.
//

#import "UIImagePickerController+RACSignalSupport.h"
#import "RACDelegateProxy.h"
#import "RACSignal+Operations.h"
#import "NSObject+RACDeallocating.h"
#import "NSObject+RACDescription.h"
#import <objc/runtime.h>

@implementation UIImagePickerController (RACSignalSupport)

static void RACUseDelegateProxy(UIImagePickerController *self) {
if (self.delegate == self.rac_delegateProxy) return;

self.rac_delegateProxy.rac_proxiedDelegate = self.delegate;
self.delegate = (id)self.rac_delegateProxy;
}

- (RACDelegateProxy *)rac_delegateProxy {
RACDelegateProxy *proxy = objc_getAssociatedObject(self, _cmd);
if (proxy == nil) {
proxy = [[RACDelegateProxy alloc] initWithProtocol:@protocol(UIImagePickerControllerDelegate)];
objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

return proxy;
}

- (RACSignal *)rac_imageSelectedSignal {
RACSignal *pickerCancelledSignal = [[self.rac_delegateProxy
signalForSelector:@selector(imagePickerControllerDidCancel:)]
merge:self.rac_willDeallocSignal];

RACSignal *imagePickerSignal = [[[[self.rac_delegateProxy
signalForSelector:@selector(imagePickerController:didFinishPickingMediaWithInfo:)]
reduceEach:^(UIImagePickerController *pickerController, NSDictionary *userInfo) {
return userInfo;
}]
takeUntil:pickerCancelledSignal]
setNameWithFormat:@"%@ -rac_imageSelectedSignal", [self rac_description]];

RACUseDelegateProxy(self);

return imagePickerSignal;
}

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// UIImagePickerControllerRACSupportSpec.m
// ReactiveCocoa
//
// Created by Timur Kuchkarov on 17.04.14.
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
//

#import "UIImagePickerController+RACSignalSupport.h"
#import "RACSignal.h"

SpecBegin(UIImagePickerControllerRACSupport)

describe(@"UIImagePickerController", ^{
__block UIImagePickerController *imagePicker;

beforeEach(^{
imagePicker = [[UIImagePickerController alloc] init];
expect(imagePicker).notTo.beNil();
});

it(@"sends the user info dictionary after confirmation", ^{
__block NSDictionary *selectedImageUserInfo = nil;
[imagePicker.rac_imageSelectedSignal subscribeNext:^(NSDictionary *userInfo) {
selectedImageUserInfo = userInfo;
}];

NSDictionary *info = @{
UIImagePickerControllerMediaType: @"public.image",
UIImagePickerControllerMediaMetadata: @{}
};
[imagePicker.delegate imagePickerController:imagePicker didFinishPickingMediaWithInfo:info];
expect(selectedImageUserInfo).to.equal(info);
});

it(@"cancels image picking process", ^{
__block BOOL didSend = NO;
__block BOOL didComplete = NO;
[imagePicker.rac_imageSelectedSignal subscribeNext:^(NSDictionary *userInfo) {
didSend = YES;
} completed:^{
didComplete = YES;
}];

[imagePicker.delegate imagePickerControllerDidCancel:imagePicker];
expect(didSend).to.beFalsy();
expect(didComplete).to.beTruthy();
});
});

SpecEnd

0 comments on commit e091e74

Please sign in to comment.