mirror of
https://github.com/zhigang1992/FunctionalReactivePixels.git
synced 2026-01-12 22:47:31 +08:00
Merge pull request #24 from AshFurrow/reactiveviewmodel
[WIP] Reactive View Model Refactoring & Testing
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
5E730B0E1815F3E4003FCB43 /* FRPGalleryViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E730B0D1815F3E4003FCB43 /* FRPGalleryViewModel.m */; };
|
||||
5E730B101815F78B003FCB43 /* FRPGalleryViewModelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E730B0F1815F78B003FCB43 /* FRPGalleryViewModelTests.m */; };
|
||||
5E730B141815FE97003FCB43 /* FRPFullSizePhotoViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E730B131815FE97003FCB43 /* FRPFullSizePhotoViewModel.m */; };
|
||||
5E93AD9A186C781000795C9E /* FRPFullSizePhotoViewModelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E93AD99186C781000795C9E /* FRPFullSizePhotoViewModelTests.m */; };
|
||||
5E93AD9C186C80DE00795C9E /* FRPPhotoViewModelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E93AD9B186C80DE00795C9E /* FRPPhotoViewModelTests.m */; };
|
||||
5EAD1F5818173A3200C67860 /* FRPPhotoViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EAD1F5718173A3200C67860 /* FRPPhotoViewModel.m */; };
|
||||
5EAD1F5C18173F1500C67860 /* FRPLoginViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EAD1F5B18173F1500C67860 /* FRPLoginViewModel.m */; };
|
||||
5EAD1F601817418800C67860 /* FRPPhotoDetailViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EAD1F5F1817418800C67860 /* FRPPhotoDetailViewModel.m */; };
|
||||
@@ -63,6 +65,8 @@
|
||||
5E730B0F1815F78B003FCB43 /* FRPGalleryViewModelTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FRPGalleryViewModelTests.m; sourceTree = "<group>"; };
|
||||
5E730B121815FE97003FCB43 /* FRPFullSizePhotoViewModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FRPFullSizePhotoViewModel.h; sourceTree = "<group>"; };
|
||||
5E730B131815FE97003FCB43 /* FRPFullSizePhotoViewModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FRPFullSizePhotoViewModel.m; sourceTree = "<group>"; };
|
||||
5E93AD99186C781000795C9E /* FRPFullSizePhotoViewModelTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FRPFullSizePhotoViewModelTests.m; sourceTree = "<group>"; };
|
||||
5E93AD9B186C80DE00795C9E /* FRPPhotoViewModelTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FRPPhotoViewModelTests.m; sourceTree = "<group>"; };
|
||||
5EAD1F5618173A3200C67860 /* FRPPhotoViewModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FRPPhotoViewModel.h; sourceTree = "<group>"; };
|
||||
5EAD1F5718173A3200C67860 /* FRPPhotoViewModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FRPPhotoViewModel.m; sourceTree = "<group>"; };
|
||||
5EAD1F5A18173F1500C67860 /* FRPLoginViewModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FRPLoginViewModel.h; sourceTree = "<group>"; };
|
||||
@@ -282,6 +286,8 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5E730B0F1815F78B003FCB43 /* FRPGalleryViewModelTests.m */,
|
||||
5E93AD99186C781000795C9E /* FRPFullSizePhotoViewModelTests.m */,
|
||||
5E93AD9B186C80DE00795C9E /* FRPPhotoViewModelTests.m */,
|
||||
5EBE2B1A180B07D0007B6BF3 /* Supporting Files */,
|
||||
);
|
||||
path = FRPTests;
|
||||
@@ -482,7 +488,9 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
5E93AD9A186C781000795C9E /* FRPFullSizePhotoViewModelTests.m in Sources */,
|
||||
5E730B101815F78B003FCB43 /* FRPGalleryViewModelTests.m in Sources */,
|
||||
5E93AD9C186C80DE00795C9E /* FRPPhotoViewModelTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
@interface FRPFullSizePhotoViewModel : RVMViewModel
|
||||
|
||||
-(instancetype)initWithPhotoArray:(NSArray *)photoArray initialPhotoIndex:(NSInteger)initialPhotoIndex;
|
||||
-(FRPPhotoModel *)photoModelAtIndex:(NSInteger)index;
|
||||
|
||||
@property (nonatomic, readonly, strong) NSArray *model;
|
||||
@property (nonatomic, readonly) NSInteger initialPhotoIndex;
|
||||
|
||||
@property (nonatomic, readonly) NSString *initialPhotoName;
|
||||
-(FRPPhotoModel *)photoModelAtIndex:(NSInteger)index;
|
||||
|
||||
@end
|
||||
|
||||
@@ -30,9 +30,14 @@
|
||||
}
|
||||
|
||||
-(NSString *)initialPhotoName {
|
||||
return [self.model[self.initialPhotoIndex] photoName];
|
||||
FRPPhotoModel *photoModel = [self initialPhotoModel];
|
||||
return [photoModel photoName];
|
||||
}
|
||||
|
||||
//-(NSString *)initialPhotoName {
|
||||
// return [self.model[self.initialPhotoIndex] photoName];
|
||||
//}
|
||||
|
||||
-(FRPPhotoModel *)photoModelAtIndex:(NSInteger)index {
|
||||
if (index < 0 || index > self.model.count - 1) {
|
||||
// Index was out of bounds, return nil
|
||||
@@ -42,4 +47,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private Methods
|
||||
|
||||
-(FRPPhotoModel *)initialPhotoModel {
|
||||
return [self photoModelAtIndex:self.initialPhotoIndex];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// FRPGalleryViewModel.m
|
||||
// FRP
|
||||
//
|
||||
@@ -21,9 +21,13 @@
|
||||
self = [super init];
|
||||
if (!self) return nil;
|
||||
|
||||
RAC(self, model) = [[[FRPPhotoImporter importPhotos] logError] catchTo:[RACSignal empty]];
|
||||
RAC(self, model) = [self importPhotosSignal];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(RACSignal *)importPhotosSignal {
|
||||
return [[[FRPPhotoImporter importPhotos] logError] catchTo:[RACSignal empty]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -107,9 +107,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
+(NSString *)urlForImageSize:(NSInteger)size inDictionary:(NSDictionary *)dictionary {
|
||||
+(NSString *)urlForImageSize:(NSInteger)size inDictionary:(NSArray *)array {
|
||||
/*
|
||||
images = (
|
||||
(
|
||||
{
|
||||
size = 3;
|
||||
url = "http://ppcdn.500px.org/49204370/b125a49d0863e0ba05d8196072b055876159f33e/3.jpg";
|
||||
@@ -117,7 +117,7 @@
|
||||
);
|
||||
*/
|
||||
|
||||
return [[[[[dictionary rac_sequence] filter:^BOOL(NSDictionary *value) {
|
||||
return [[[[[array rac_sequence] filter:^BOOL(NSDictionary *value) {
|
||||
return [value[@"size"] integerValue] == size;
|
||||
}] map:^id(id value) {
|
||||
return value[@"url"];
|
||||
|
||||
@@ -38,8 +38,7 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)viewDidLoad
|
||||
{
|
||||
-(void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
// Configure self's view
|
||||
@@ -47,18 +46,22 @@
|
||||
|
||||
// Configure subviews
|
||||
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
|
||||
RAC(imageView, image) = self.viewModel.photoImageSignal;
|
||||
RAC(imageView, image) = RACObserve(self.viewModel, photoImage);
|
||||
imageView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
[self.view addSubview:imageView];
|
||||
self.imageView = imageView;
|
||||
|
||||
[self.viewModel.didBecomeActiveSignal subscribeNext:^(id x) {
|
||||
[SVProgressHUD dismiss];
|
||||
|
||||
[RACObserve(self.viewModel, loading) subscribeNext:^(NSNumber *loading){
|
||||
if (loading.boolValue) {
|
||||
[SVProgressHUD show];
|
||||
} else {
|
||||
[SVProgressHUD dismiss];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
-(void)viewDidAppear:(BOOL)animated {
|
||||
[super viewDidAppear:animated];
|
||||
-(void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
self.viewModel.active = YES;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
|
||||
@property (nonatomic, readonly) FRPPhotoModel *model;
|
||||
|
||||
@property (nonatomic, readonly) RACSignal *photoImageSignal;
|
||||
@property (nonatomic, readonly) UIImage *photoImage;
|
||||
@property (nonatomic, readonly, getter = isLoading) BOOL loading;
|
||||
|
||||
-(NSString *)photoName;
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
|
||||
@interface FRPPhotoViewModel ()
|
||||
|
||||
@property (nonatomic, strong) RACSignal *photoImageSignal;
|
||||
@property (nonatomic, strong) UIImage *photoImage;
|
||||
@property (nonatomic, assign, getter = isLoading) BOOL loading;
|
||||
|
||||
@end
|
||||
|
||||
@@ -27,22 +28,35 @@
|
||||
@weakify(self);
|
||||
[self.didBecomeActiveSignal subscribeNext:^(id x) {
|
||||
@strongify(self);
|
||||
[[FRPPhotoImporter fetchPhotoDetails:self.model] subscribeError:^(NSError *error) {
|
||||
NSLog(@"Could not fetch photo details: %@", error);
|
||||
} completed:^{
|
||||
NSLog(@"Fetched photo details.");
|
||||
}];
|
||||
[self downloadPhotoModelDetails];
|
||||
}];
|
||||
|
||||
self.photoImageSignal = [RACObserve(self.model, fullsizedData) map:^id(id value) {
|
||||
RAC(self, photoImage) = [RACObserve(self.model, fullsizedData) map:^id(id value) {
|
||||
return [UIImage imageWithData:value];
|
||||
}];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Public Methods
|
||||
|
||||
-(NSString *)photoName {
|
||||
return self.model.photoName;
|
||||
}
|
||||
|
||||
#pragma mark - Private Methods
|
||||
|
||||
-(void)downloadPhotoModelDetails {
|
||||
self.loading = YES;
|
||||
|
||||
@weakify(self);
|
||||
[[FRPPhotoImporter fetchPhotoDetails:self.model] subscribeError:^(NSError *error) {
|
||||
NSLog(@"Could not fetch photo details: %@", error);
|
||||
} completed:^{
|
||||
@strongify(self);
|
||||
self.loading = NO;
|
||||
NSLog(@"Fetched photo details.");
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
77
FRPTests/FRPFullSizePhotoViewModelTests.m
Normal file
77
FRPTests/FRPFullSizePhotoViewModelTests.m
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// FRPFullSizePhotoViewModelTests.m
|
||||
// FRP
|
||||
//
|
||||
// Created by Ash Furrow on 12/26/2013.
|
||||
// Copyright (c) 2013 Ash Furrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Specta/Specta.h>
|
||||
#define EXP_SHORTHAND
|
||||
#import <Expecta/Expecta.h>
|
||||
#import <OCMock/OCMock.h>
|
||||
|
||||
#import "FRPFullSizePhotoViewModel.h"
|
||||
#import "FRPPhotoModel.h"
|
||||
|
||||
@interface FRPFullSizePhotoViewModel ()
|
||||
|
||||
-(FRPPhotoModel *)initialPhotoModel;
|
||||
|
||||
@end
|
||||
|
||||
SpecBegin(FRPFullSizePhotoViewModel)
|
||||
|
||||
describe(@"FRPFullSizePhotomodel", ^{
|
||||
it (@"should assign correct attributes when initialized", ^{
|
||||
NSArray *model = @[];
|
||||
NSInteger initialPhotoIndex = 1337;
|
||||
|
||||
FRPFullSizePhotoViewModel *viewModel = [[FRPFullSizePhotoViewModel alloc] initWithPhotoArray:model initialPhotoIndex:initialPhotoIndex];
|
||||
|
||||
expect(model).to.equal(viewModel.model);
|
||||
expect(initialPhotoIndex).to.equal(viewModel.initialPhotoIndex);
|
||||
});
|
||||
|
||||
it (@"should return nil for an out-of-bounds photo index", ^{
|
||||
NSArray *model = @[[NSObject new]];
|
||||
NSInteger initialPhotoIndex = 0;
|
||||
|
||||
FRPFullSizePhotoViewModel *viewModel = [[FRPFullSizePhotoViewModel alloc] initWithPhotoArray:model initialPhotoIndex:initialPhotoIndex];
|
||||
|
||||
id subzeroModel = [viewModel photoModelAtIndex:-1];
|
||||
expect(subzeroModel).to.beNil();
|
||||
|
||||
id aboveBoundsModel = [viewModel photoModelAtIndex:model.count];
|
||||
expect(aboveBoundsModel).to.beNil();
|
||||
});
|
||||
|
||||
it (@"should return the correct model for photoModelAtIndex:", ^{
|
||||
id photoModel = [NSObject new];
|
||||
NSArray *model = @[photoModel];
|
||||
NSInteger initialPhotoIndex = 0;
|
||||
|
||||
FRPFullSizePhotoViewModel *viewModel = [[FRPFullSizePhotoViewModel alloc] initWithPhotoArray:model initialPhotoIndex:initialPhotoIndex];
|
||||
|
||||
id returnedModel = [viewModel photoModelAtIndex:0];
|
||||
expect(returnedModel).to.equal(photoModel);
|
||||
});
|
||||
|
||||
it (@"should return the correct initial photo model", ^{
|
||||
NSArray *model = @[[NSObject new]];
|
||||
NSInteger initialPhotoIndex = 0;
|
||||
|
||||
FRPFullSizePhotoViewModel *viewModel = [[FRPFullSizePhotoViewModel alloc] initWithPhotoArray:model initialPhotoIndex:initialPhotoIndex];
|
||||
id mockViewModel = [OCMockObject partialMockForObject:viewModel];
|
||||
|
||||
[[[mockViewModel expect] andReturn:model[0]] photoModelAtIndex:initialPhotoIndex];
|
||||
|
||||
id returnedObject = [mockViewModel initialPhotoModel];
|
||||
|
||||
expect(returnedObject).to.equal(model[0]);
|
||||
|
||||
[mockViewModel verify];
|
||||
});
|
||||
});
|
||||
|
||||
SpecEnd
|
||||
@@ -10,22 +10,24 @@
|
||||
#import <OCMock/OCMock.h>
|
||||
|
||||
#import "FRPGalleryViewModel.h"
|
||||
#import "FRPPhotoImporter.h"
|
||||
|
||||
@interface FRPGalleryViewModel ()
|
||||
|
||||
-(RACSignal *)importPhotosSignal;
|
||||
|
||||
@end
|
||||
|
||||
SpecBegin(FRPGalleryViewModel)
|
||||
|
||||
describe(@"FRPGalleryViewModel", ^{
|
||||
beforeAll(^{
|
||||
// This is run once and only once before all of the examples
|
||||
// in this group and before any beforeEach blocks.
|
||||
});
|
||||
|
||||
beforeEach(^{
|
||||
// This is run before each example.
|
||||
});
|
||||
|
||||
it(@"should be initialized and call importPhotos", ^{
|
||||
STAssertTrue(false, @"Test not implemented.");
|
||||
id mockObject = [OCMockObject mockForClass:[FRPGalleryViewModel class]];
|
||||
[[[mockObject expect] andReturn:[RACSignal empty]] importPhotosSignal];
|
||||
|
||||
mockObject = [mockObject init];
|
||||
|
||||
[mockObject verify];
|
||||
[mockObject stopMocking];
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
84
FRPTests/FRPPhotoViewModelTests.m
Normal file
84
FRPTests/FRPPhotoViewModelTests.m
Normal file
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// FRPPhotoViewModelTests.m
|
||||
// FRP
|
||||
//
|
||||
// Created by Ash Furrow on 12/26/2013.
|
||||
// Copyright (c) 2013 Ash Furrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Specta/Specta.h>
|
||||
#define EXP_SHORTHAND
|
||||
#import <Expecta/Expecta.h>
|
||||
#import <OCMock/OCMock.h>
|
||||
|
||||
#import "FRPPhotoViewModel.h"
|
||||
#import "FRPPhotoModel.h"
|
||||
|
||||
@interface FRPPhotoViewModel ()
|
||||
|
||||
-(void)downloadPhotoModelDetails;
|
||||
|
||||
@end
|
||||
|
||||
SpecBegin(FRPPhotoViewModel)
|
||||
|
||||
describe(@"FRPPhotoViewModel", ^{
|
||||
it (@"should return the photo's name property when photoName is invoked", ^{
|
||||
NSString *name = @"Ash";
|
||||
|
||||
id mockPhotoModel = [OCMockObject mockForClass:[FRPPhotoModel class]];
|
||||
[[[mockPhotoModel stub] andReturn:name] photoName];
|
||||
|
||||
FRPPhotoViewModel *viewModel = [[FRPPhotoViewModel alloc] initWithModel:nil];
|
||||
id mockViewModel = [OCMockObject partialMockForObject:viewModel];
|
||||
[[[mockViewModel stub] andReturn:mockPhotoModel] model];
|
||||
|
||||
id returnedName = [mockViewModel photoName];
|
||||
|
||||
expect(returnedName).to.equal(name);
|
||||
|
||||
[mockPhotoModel stopMocking];
|
||||
});
|
||||
|
||||
it (@"should download photo model details when it becomes active", ^{
|
||||
FRPPhotoViewModel *viewModel = [[FRPPhotoViewModel alloc] initWithModel:nil];
|
||||
|
||||
id mockViewModel = [OCMockObject partialMockForObject:viewModel];
|
||||
[[mockViewModel expect] downloadPhotoModelDetails];
|
||||
|
||||
[mockViewModel setActive:YES];
|
||||
|
||||
[mockViewModel verify];
|
||||
});
|
||||
|
||||
it (@"should correctly map image data to UIImage", ^{
|
||||
UIImage *image = [[UIImage alloc] init];
|
||||
NSData *imageData = [NSData data];
|
||||
|
||||
id mockImage = [OCMockObject mockForClass:[UIImage class]];
|
||||
[[[mockImage stub] andReturn:image] imageWithData:imageData];
|
||||
|
||||
FRPPhotoModel *photoModel = [[FRPPhotoModel alloc] init];
|
||||
photoModel.fullsizedData = imageData;
|
||||
|
||||
__unused FRPPhotoViewModel *viewModel = [[FRPPhotoViewModel alloc] initWithModel:photoModel];
|
||||
|
||||
[mockImage verify];
|
||||
[mockImage stopMocking];
|
||||
});
|
||||
|
||||
it (@"should return the correct photo name", ^{
|
||||
NSString *name = @"Ash";
|
||||
|
||||
FRPPhotoModel *photoModel = [[FRPPhotoModel alloc] init];
|
||||
photoModel.photoName = name;
|
||||
|
||||
FRPPhotoViewModel *viewModel = [[FRPPhotoViewModel alloc] initWithModel:photoModel];
|
||||
|
||||
NSString *returnedName = [viewModel photoName];
|
||||
|
||||
expect(name).to.equal(returnedName);
|
||||
});
|
||||
});
|
||||
|
||||
SpecEnd
|
||||
6
Podfile
6
Podfile
@@ -16,8 +16,8 @@ pod 'ReactiveCocoa', '2.1.4'
|
||||
pod 'ReactiveViewModel', '0.1.1'
|
||||
pod 'libextobjc', '0.3'
|
||||
pod '500px-iOS-api', '1.0.5'
|
||||
pod 'Specta', '~> 0.1.11'
|
||||
pod 'Specta', '~> 0.2.1'
|
||||
pod 'Expecta', '~> 0.2'
|
||||
pod 'OCMock', '~> 2.0.1'
|
||||
pod 'OCMock', '~> 2.2.2'
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
18
Podfile.lock
18
Podfile.lock
@@ -86,7 +86,7 @@ PODS:
|
||||
- libextobjc/RuntimeExtensions (0.3)
|
||||
- libextobjc/UmbrellaHeader (0.3)
|
||||
- libffi (3.0.13)
|
||||
- OCMock (2.0.1)
|
||||
- OCMock (2.2.2)
|
||||
- ReactiveCocoa (2.1.4):
|
||||
- ReactiveCocoa/Core
|
||||
- ReactiveCocoa/no-arc
|
||||
@@ -94,18 +94,18 @@ PODS:
|
||||
- ReactiveCocoa/no-arc
|
||||
- ReactiveCocoa/no-arc (2.1.4)
|
||||
- ReactiveViewModel (0.1.1):
|
||||
- ReactiveCocoa (= 2.1.4)
|
||||
- Specta (0.1.11)
|
||||
- ReactiveCocoa (~> 2.1)
|
||||
- Specta (0.2.1)
|
||||
- SVProgressHUD (0.9)
|
||||
|
||||
DEPENDENCIES:
|
||||
- 500px-iOS-api (= 1.0.5)
|
||||
- Expecta (~> 0.2)
|
||||
- libextobjc (= 0.3)
|
||||
- OCMock (~> 2.0.1)
|
||||
- OCMock (~> 2.2.2)
|
||||
- ReactiveCocoa (= 2.1.4)
|
||||
- ReactiveViewModel (= 0.1.1)
|
||||
- Specta (~> 0.1.11)
|
||||
- Specta (~> 0.2.1)
|
||||
- SVProgressHUD (= 0.9)
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
@@ -113,10 +113,10 @@ SPEC CHECKSUMS:
|
||||
Expecta: dbc4a27fabb853bdd2e907e33f11ee43a9a47d0c
|
||||
libextobjc: 820a79dbbbc498611e04fffd07d2d52a5588e7ac
|
||||
libffi: 64ef39353e747bb2b25e1026afd96a157bf9231c
|
||||
OCMock: f0c099603f851d07f8d7f2efe26d05da721ec43f
|
||||
OCMock: ffba68873fd32cfd35d885bddad23bfa816da4a3
|
||||
ReactiveCocoa: 0e8725dd3c609128144c15192f4dbdab827f54ae
|
||||
ReactiveViewModel: 43714642e73dc029f4a23ca28cad6f4c57eb8487
|
||||
Specta: 82746c6fd70b104c5d37cfbadb7bf15a2cbc4da0
|
||||
ReactiveViewModel: e6cba4e138cfdaac19ea326bf42f6d6a61245f2c
|
||||
Specta: 2d06220591110c6d9757d8be8ecf8e63aa40dc2a
|
||||
SVProgressHUD: 03d4845ec8e64591726428a08236c6a5489d45f8
|
||||
|
||||
COCOAPODS: 0.26.2
|
||||
COCOAPODS: 0.29.0
|
||||
|
||||
Reference in New Issue
Block a user