|
2 | 2 |
|
3 | 3 | 本章的其他部分将把Functional Reactive Pixels Demo的其他代码迁移到MVVM架构中。我们将添加一个新的库到Podfile文件里。Github上创作了ReactiveCocoa的黑客,也同时创建了一个ViewModel的基类:ReactiveViewModel.我们将要使用它的0.1.1版本。更新Podfile之后立即运行`pod install`以安装该库。 |
4 | 4 |
|
| 5 | +重构的第一个类是高清图片视图控制器。从这儿开始是因为它的业务逻辑比较少,抽象成viewModel时相对简单。我们循序渐进,慢慢来。 |
| 6 | + |
| 7 | +目前,我们的`FRPFullSizePhotoViewController`包含一个图片数组和当前图片(在数组中)的下标值。我们将把他们抽象到我们的视图模型中来。 |
| 8 | + |
| 9 | +从头文件中移除自定义初始化,追加`FRPFullSizePhotoViewModel`的预申明。然后在这个新类中追加一个属性。 |
| 10 | + |
| 11 | +``` |
| 12 | +@property (nonatomic ,strong ) FRPFullSizePhotoViewModel *viewModel; |
| 13 | +``` |
| 14 | + |
| 15 | +在实现文件里,#import这个新的视图模型(别担心,我们很快就会创建它), |
| 16 | + |
| 17 | +``` |
| 18 | +#import "FRPFullSizePhotoViewModel.h" |
| 19 | +``` |
| 20 | + |
| 21 | +然后,移除`photoModelArray`私有属性的申明。重写我们的初始化方法以移除对`photoModelArray`实例的引用。代码看起来应该像下面这样: |
| 22 | + |
| 23 | +```Objective-C |
| 24 | +- (instancetype)init { |
| 25 | + self = [super init]; |
| 26 | + if(!self) return nil; |
| 27 | + |
| 28 | + //ViewControllers |
| 29 | + self.pageViewController = [UIPageViewController alloc] |
| 30 | + initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll |
| 31 | + navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal |
| 32 | + options:@{ UIPageViewControllerOptionInterPageSpacingKey : @30 }; |
| 33 | + |
| 34 | + self.pageViewController.dataSource = self; |
| 35 | + self.pageViewController.delegate = self; |
| 36 | + [self addChildViewController:self.pageViewController]; |
| 37 | + |
| 38 | + return self; |
| 39 | +} |
| 40 | +``` |
| 41 | + |
| 42 | +在你的`ViewDidLoad:`中添加如下代码: |
| 43 | + |
| 44 | +```Objective-C |
| 45 | +//Configure child view controllers |
| 46 | +[self.pageViewController \ |
| 47 | + setViewControllers: @[ [self photoViewControllerForIndex:self.viewModel.initialPhotoIndex] ] |
| 48 | + direction:UIPageViewControllerNavigationDirectionForward |
| 49 | + animated:NO |
| 50 | + completion:nil ]; |
| 51 | + |
| 52 | +//Configure self |
| 53 | +self.title = [self.viewModel.initialPhotoModel photoName]; |
| 54 | + |
| 55 | +``` |
| 56 | +
|
| 57 | +我们将要写的这个我们提到的方法,对于veiwModel中发生的事情,给你一种XX感。最后,进到`photoViewControllerForIndex`方法中,它应用了已经解除分配的`photoModelArray`,用下面的实现替代它。 |
| 58 | +
|
| 59 | +```Objective-C |
| 60 | +- (FRPPhotoViewController *)photoViewControllerForIndex:(NSInteger)index { |
| 61 | + if (index >= 0 && index < self.viewModel.photoArray.coung ) { |
| 62 | + FRPPhotoModel *photoModel = self.viewModel.model[index]; |
| 63 | + |
| 64 | + FRPPhotoViewController *photoViewController = \ |
| 65 | + [[FRPPhotoViewController alloc] initWithPhotoModel:photoModel index:index]; |
| 66 | + |
| 67 | + return photoViewController; |
| 68 | + } |
| 69 | + |
| 70 | + // Index was out of bounds, return nil |
| 71 | + return nil; |
| 72 | +} |
| 73 | +
|
| 74 | +``` |
| 75 | +好了!现在轮到我们的视图模型本身了。创建一个新的`RVMViewModel`的子类,并将其命名为`FRPFullSizedPhotoViewModel`.基于它将要封装的信息,以及我们在视图控制器中的需求,我们知道,我们的头文件看起来应该是下面这样: |
| 76 | + |
| 77 | +```Objective-C |
| 78 | +@class FRPPhotoModel; |
| 79 | + |
| 80 | +@interface FRPFullSizePhotoViewModel : RVMViewModel |
| 81 | + |
| 82 | +- (instancetype)initWithPhotoArray:(NSArray *)photoArray initialPhotoIndex:(NSInteger)initialPhotoIndex; |
| 83 | +- (FRPPhotoModel *)photoModelAtIndex:(NSInteger)index; |
| 84 | + |
| 85 | +@property (nonatomic , readonly, strong) NSArray *model; |
| 86 | +@property (nonatomic, readonly) NSInteger initialPhotoIndex; |
| 87 | +@property (nonatomic, readonly) NSString *initialPhotoName; |
| 88 | + |
| 89 | +@end |
| 90 | + |
| 91 | +``` |
| 92 | +
|
| 93 | +`model`属性在`RVMViewModel`中被定义为`id`类型,我们把它重定义为`NSArray`. 我们也勾住了(即使用全局变量记录)我们最初照片的索引(下标)并且给我们最初的照片名属性定义了只读属性。这种微不足道的逻辑我们可以放到我们的视图控制器中,但很快我们就会看到更为复杂的情况。 |
| 94 | +
|
| 95 | +我们来完成实现文件里的东西。第一件事就是:我们需要#import `FRPPhotoModel`类的头文件。然后,我们将打开私有属性的读写访问权限。 |
| 96 | +
|
| 97 | +```Objective-C |
| 98 | +
|
| 99 | +
|
| 100 | +
|
| 101 | +``` |
| 102 | + |
| 103 | + |
0 commit comments