Skip to content
This repository was archived by the owner on Aug 21, 2021. It is now read-only.

Commit 468cc9b

Browse files
committed
Migrate ViewModel to Swift 3
1 parent bdb69b2 commit 468cc9b

9 files changed

+94
-109
lines changed

ExampleViewModel/ImageDetailViewModel.swift

+35-34
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,36 @@
66
// Copyright © 2015 Swinject Contributors. All rights reserved.
77
//
88

9-
import ReactiveCocoa
9+
import ReactiveSwift
10+
import Result
1011
import ExampleModel
1112

1213
public final class ImageDetailViewModel: ImageDetailViewModeling {
13-
public var id: AnyProperty<UInt64?> { return AnyProperty(_id) }
14-
public var pageImageSizeText: AnyProperty<String?> { return AnyProperty(_pageImageSizeText) }
15-
public var tagText: AnyProperty<String?> { return AnyProperty(_tagText) }
16-
public var usernameText: AnyProperty<String?> { return AnyProperty(_usernameText) }
17-
public var viewCountText: AnyProperty<String?> { return AnyProperty(_viewCountText) }
18-
public var downloadCountText: AnyProperty<String?> { return AnyProperty(_downloadCountText) }
19-
public var likeCountText: AnyProperty<String?> { return AnyProperty(_likeCountText) }
20-
public var image: AnyProperty<UIImage?> { return AnyProperty(_image) }
14+
public var id: Property<UInt64?> { return Property(_id) }
15+
public var pageImageSizeText: Property<String?> { return Property(_pageImageSizeText) }
16+
public var tagText: Property<String?> { return Property(_tagText) }
17+
public var usernameText: Property<String?> { return Property(_usernameText) }
18+
public var viewCountText: Property<String?> { return Property(_viewCountText) }
19+
public var downloadCountText: Property<String?> { return Property(_downloadCountText) }
20+
public var likeCountText: Property<String?> { return Property(_likeCountText) }
21+
public var image: Property<UIImage?> { return Property(_image) }
2122

22-
private let _id = MutableProperty<UInt64?>(nil)
23-
private let _pageImageSizeText = MutableProperty<String?>(nil)
24-
private let _tagText = MutableProperty<String?>(nil)
25-
private let _usernameText = MutableProperty<String?>(nil)
26-
private let _viewCountText = MutableProperty<String?>(nil)
27-
private let _downloadCountText = MutableProperty<String?>(nil)
28-
private let _likeCountText = MutableProperty<String?>(nil)
29-
private let _image = MutableProperty<UIImage?>(nil)
23+
fileprivate let _id = MutableProperty<UInt64?>(nil)
24+
fileprivate let _pageImageSizeText = MutableProperty<String?>(nil)
25+
fileprivate let _tagText = MutableProperty<String?>(nil)
26+
fileprivate let _usernameText = MutableProperty<String?>(nil)
27+
fileprivate let _viewCountText = MutableProperty<String?>(nil)
28+
fileprivate let _downloadCountText = MutableProperty<String?>(nil)
29+
fileprivate let _likeCountText = MutableProperty<String?>(nil)
30+
fileprivate let _image = MutableProperty<UIImage?>(nil)
3031

31-
internal var locale = NSLocale.currentLocale() // For testing.
32-
private var imageEntities = [ImageEntity]()
33-
private var currentImageIndex = 0
34-
private var (stopSignalProducer, stopSignalObserver) = SignalProducer<(), NoError>.buffer()
32+
internal var locale = Locale.current // For testing.
33+
fileprivate var imageEntities = [ImageEntity]()
34+
fileprivate var currentImageIndex = 0
35+
fileprivate var stop = MutableProperty<Void>()
3536

36-
private let network: Networking
37-
private let externalAppChannel: ExternalAppChanneling
37+
fileprivate let network: Networking
38+
fileprivate let externalAppChannel: ExternalAppChanneling
3839

3940
public init(network: Networking, externalAppChannel: ExternalAppChanneling) {
4041
self.network = network
@@ -43,19 +44,19 @@ public final class ImageDetailViewModel: ImageDetailViewModeling {
4344

4445
public func openImagePage() {
4546
if let currentImageEntity = currentImageEntity {
46-
externalAppChannel.openURL(currentImageEntity.pageURL)
47+
externalAppChannel.openURL(url: currentImageEntity.pageURL)
4748
}
4849
}
4950

50-
private var currentImageEntity: ImageEntity? {
51+
fileprivate var currentImageEntity: ImageEntity? {
5152
return imageEntities.indices.contains(currentImageIndex) ? imageEntities[currentImageIndex] : nil
5253
}
5354
}
5455

5556
extension ImageDetailViewModel: ImageDetailViewModelModifiable {
56-
public func update(imageEntities: [ImageEntity], atIndex index: Int) {
57-
stopSignalObserver.sendNext(())
58-
(stopSignalProducer, stopSignalObserver) = SignalProducer<(), NoError>.buffer()
57+
public func update(_ imageEntities: [ImageEntity], atIndex index: Int) {
58+
stop.value = ()
59+
stop = MutableProperty<Void>()
5960

6061
self.imageEntities = imageEntities
6162
currentImageIndex = index
@@ -64,23 +65,23 @@ extension ImageDetailViewModel: ImageDetailViewModelModifiable {
6465
self._id.value = imageEntity?.id
6566
self._usernameText.value = imageEntity?.username
6667
self._pageImageSizeText.value = imageEntity.map { "\($0.pageImageWidth) x \($0.pageImageHeight)" }
67-
self._tagText.value = imageEntity.map { $0.tags.joinWithSeparator(", ") }
68+
self._tagText.value = imageEntity.map { $0.tags.joined(separator: ", ") }
6869
self._viewCountText.value = imageEntity.map { formatInt64($0.viewCount) }
6970
self._downloadCountText.value = imageEntity.map { formatInt64($0.downloadCount) }
7071
self._likeCountText.value = imageEntity.map { formatInt64($0.likeCount) }
7172

7273
_image.value = nil
7374
if let imageEntity = imageEntity {
74-
_image <~ network.requestImage(imageEntity.imageURL)
75-
.takeUntil(stopSignalProducer)
75+
_image <~ network.requestImage(url: imageEntity.imageURL)
76+
.take(until: stop.producer)
7677
.map { $0 as UIImage? }
7778
.flatMapError { _ in SignalProducer<UIImage?, NoError>(value: nil) }
78-
.observeOn(UIScheduler())
79+
.observe(on: UIScheduler())
7980
}
8081
}
8182

82-
private func formatInt64(value: Int64) -> String {
83-
return NSNumber(longLong: value).descriptionWithLocale(locale)
83+
fileprivate func formatInt64(_ value: Int64) -> String {
84+
return NSNumber(value: value as Int64).description(withLocale: locale)
8485
}
8586

8687
// This method can be used if you add next and previsou buttons on image detail view

ExampleViewModel/ImageDetailViewModeling.swift

+10-10
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@
66
// Copyright © 2015 Swinject Contributors. All rights reserved.
77
//
88

9-
import ReactiveCocoa
9+
import ReactiveSwift
1010
import ExampleModel
1111

1212
public protocol ImageDetailViewModeling {
13-
var id: AnyProperty<UInt64?> { get }
14-
var pageImageSizeText: AnyProperty<String?> { get }
15-
var tagText: AnyProperty<String?> { get }
16-
var usernameText: AnyProperty<String?> { get }
17-
var viewCountText: AnyProperty<String?> { get }
18-
var downloadCountText: AnyProperty<String?> { get }
19-
var likeCountText: AnyProperty<String?> { get }
20-
var image: AnyProperty<UIImage?> { get }
13+
var id: Property<UInt64?> { get }
14+
var pageImageSizeText: Property<String?> { get }
15+
var tagText: Property<String?> { get }
16+
var usernameText: Property<String?> { get }
17+
var viewCountText: Property<String?> { get }
18+
var downloadCountText: Property<String?> { get }
19+
var likeCountText: Property<String?> { get }
20+
var image: Property<UIImage?> { get }
2121

2222
func openImagePage()
2323
}
2424

2525
public protocol ImageDetailViewModelModifiable: ImageDetailViewModeling {
26-
func update(imageEntities: [ImageEntity], atIndex index: Int)
26+
func update(_ imageEntities: [ImageEntity], atIndex index: Int)
2727
}

ExampleViewModel/ImageSearchTableViewCellModel.swift

+11-10
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
// Copyright © 2015 Swinject Contributors. All rights reserved.
77
//
88

9-
import ReactiveCocoa
9+
import ReactiveSwift
10+
import Result
1011
import ExampleModel
1112

1213
// Inherits NSObject to use rac_willDeallocSignal.
@@ -15,14 +16,14 @@ public final class ImageSearchTableViewCellModel: NSObject, ImageSearchTableView
1516
public let pageImageSizeText: String
1617
public let tagText: String
1718

18-
private let network: Networking
19-
private let previewURL: String
20-
private var previewImage: UIImage?
19+
fileprivate let network: Networking
20+
fileprivate let previewURL: String
21+
fileprivate var previewImage: UIImage?
2122

2223
internal init(image: ImageEntity, network: Networking) {
2324
id = image.id
2425
pageImageSizeText = "\(image.pageImageWidth) x \(image.pageImageHeight)"
25-
tagText = image.tags.joinWithSeparator(", ")
26+
tagText = image.tags.joined(separator: ", ")
2627

2728
self.network = network
2829
previewURL = image.previewURL
@@ -32,18 +33,18 @@ public final class ImageSearchTableViewCellModel: NSObject, ImageSearchTableView
3233

3334
public func getPreviewImage() -> SignalProducer<UIImage?, NoError> {
3435
if let previewImage = self.previewImage {
35-
return SignalProducer(value: previewImage).observeOn(UIScheduler())
36+
return SignalProducer(value: previewImage).observe(on: UIScheduler())
3637
}
3738
else {
38-
let imageProducer = network.requestImage(previewURL)
39-
.takeUntil(self.racutil_willDeallocProducer)
40-
.on(next: { self.previewImage = $0 })
39+
let imageProducer = network.requestImage(url: previewURL)
40+
.take(until: self.reactive.lifetime.ended)
41+
.on(value: { self.previewImage = $0 })
4142
.map { $0 as UIImage? }
4243
.flatMapError { _ in SignalProducer<UIImage?, NoError>(value: nil) }
4344

4445
return SignalProducer(value: nil)
4546
.concat(imageProducer)
46-
.observeOn(UIScheduler())
47+
.observe(on: UIScheduler())
4748
}
4849
}
4950
}

ExampleViewModel/ImageSearchTableViewCellModeling.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
// Copyright © 2015 Swinject Contributors. All rights reserved.
77
//
88

9-
import ReactiveCocoa
9+
import ReactiveSwift
10+
import Result
1011

1112
public protocol ImageSearchTableViewCellModeling {
1213
var id: UInt64 { get }

ExampleViewModel/ImageSearchTableViewModel.swift

+25-24
Original file line numberDiff line numberDiff line change
@@ -6,65 +6,66 @@
66
// Copyright © 2015 Swinject Contributors. All rights reserved.
77
//
88

9-
import ReactiveCocoa
9+
import ReactiveSwift
10+
import Result
1011
import ExampleModel
1112

1213
public final class ImageSearchTableViewModel: ImageSearchTableViewModeling {
13-
public var cellModels: AnyProperty<[ImageSearchTableViewCellModeling]> { return AnyProperty(_cellModels) }
14-
public var searching: AnyProperty<Bool> { return AnyProperty(_searching) }
15-
public var errorMessage: AnyProperty<String?> { return AnyProperty(_errorMessage) }
14+
public var cellModels: Property<[ImageSearchTableViewCellModeling]> { return Property(_cellModels) }
15+
public var searching: Property<Bool> { return Property(_searching) }
16+
public var errorMessage: Property<String?> { return Property(_errorMessage) }
1617

17-
private let _cellModels = MutableProperty<[ImageSearchTableViewCellModeling]>([])
18-
private let _searching = MutableProperty<Bool>(false)
19-
private let _errorMessage = MutableProperty<String?>(nil)
18+
fileprivate let _cellModels = MutableProperty<[ImageSearchTableViewCellModeling]>([])
19+
fileprivate let _searching = MutableProperty<Bool>(false)
20+
fileprivate let _errorMessage = MutableProperty<String?>(nil)
2021

2122
/// Accepts property injection.
2223
public var imageDetailViewModel: ImageDetailViewModelModifiable?
2324

2425
public var loadNextPage: Action<(), (), NoError> {
2526
return Action(enabledIf: nextPageLoadable) { _ in
2627
return SignalProducer { observer, disposable in
27-
if let (_, observer) = self.nextPageTrigger.value {
28+
if let observer = self.nextPageTrigger.value {
2829
self._searching.value = true
29-
observer.sendNext(())
30+
observer.value = ()
3031
}
3132
}
3233
}
3334
}
34-
private var nextPageLoadable: AnyProperty<Bool> {
35-
return AnyProperty(
36-
initialValue: false,
37-
producer: searching.producer.combineLatestWith(nextPageTrigger.producer).map { searching, trigger in
35+
fileprivate var nextPageLoadable: Property<Bool> {
36+
return Property(
37+
initial: false,
38+
then: searching.producer.combineLatest(with: nextPageTrigger.producer).map { searching, trigger in
3839
!searching && trigger != nil
3940
})
4041
}
41-
private let nextPageTrigger = MutableProperty<(SignalProducer<(), NoError>, Observer<(), NoError>)?>(nil) // SignalProducer buffer
42+
fileprivate let nextPageTrigger = MutableProperty<MutableProperty<Void>?>(nil) // SignalProducer buffer
4243

43-
private let imageSearch: ImageSearching
44-
private let network: Networking
44+
fileprivate let imageSearch: ImageSearching
45+
fileprivate let network: Networking
4546

46-
private var foundImages = [ImageEntity]()
47+
fileprivate var foundImages = [ImageEntity]()
4748

4849
public init(imageSearch: ImageSearching, network: Networking) {
4950
self.imageSearch = imageSearch
5051
self.network = network
5152
}
5253

5354
public func startSearch() {
54-
func toCellModel(image: ImageEntity) -> ImageSearchTableViewCellModeling {
55+
func toCellModel(_ image: ImageEntity) -> ImageSearchTableViewCellModeling {
5556
return ImageSearchTableViewCellModel(image: image, network: self.network) as ImageSearchTableViewCellModeling
5657
}
5758

5859
_searching.value = true
59-
nextPageTrigger.value = SignalProducer<(), NoError>.buffer()
60-
let (trigger, _) = nextPageTrigger.value!
60+
nextPageTrigger.value = MutableProperty()
61+
let trigger = nextPageTrigger.value!.producer
6162

6263
imageSearch.searchImages(nextPageTrigger: trigger)
6364
.map { response in
6465
(response.images, response.images.map { toCellModel($0) })
6566
}
66-
.observeOn(UIScheduler())
67-
.on(next: { images, cellModels in
67+
.observe(on: UIScheduler())
68+
.on(value: { images, cellModels in
6869
self.foundImages += images
6970
self._cellModels.value += cellModels
7071
self._searching.value = false
@@ -74,7 +75,7 @@ public final class ImageSearchTableViewModel: ImageSearchTableViewModeling {
7475
})
7576
.on(event: { event in
7677
switch event {
77-
case .Completed, .Failed, .Interrupted:
78+
case .completed, .failed, .interrupted:
7879
self.nextPageTrigger.value = nil
7980
self._searching.value = false
8081
default:
@@ -84,7 +85,7 @@ public final class ImageSearchTableViewModel: ImageSearchTableViewModeling {
8485
.start()
8586
}
8687

87-
public func selectCellAtIndex(index: Int) {
88+
public func selectCellAtIndex(_ index: Int) {
8889
imageDetailViewModel?.update(foundImages, atIndex: index)
8990
}
9091
}

ExampleViewModel/ImageSearchTableViewModeling.swift

+6-5
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66
// Copyright © 2015 Swinject Contributors. All rights reserved.
77
//
88

9-
import ReactiveCocoa
9+
import ReactiveSwift
10+
import Result
1011

1112
public protocol ImageSearchTableViewModeling {
12-
var cellModels: AnyProperty<[ImageSearchTableViewCellModeling]> { get }
13-
var searching: AnyProperty<Bool> { get }
14-
var errorMessage: AnyProperty<String?> { get }
13+
var cellModels: Property<[ImageSearchTableViewCellModeling]> { get }
14+
var searching: Property<Bool> { get }
15+
var errorMessage: Property<String?> { get }
1516

1617
func startSearch()
1718
var loadNextPage: Action<(), (), NoError> { get }
1819

19-
func selectCellAtIndex(index: Int)
20+
func selectCellAtIndex(_ index: Int)
2021
}

ExampleViewModel/LocalizedString.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
// Copyright © 2015 Swinject Contributors. All rights reserved.
77
//
88

9-
internal func LocalizedString(key: String, comment: String?) -> String {
9+
internal func LocalizedString(_ key: String, comment: String?) -> String {
1010
struct Static {
11-
static let bundle = NSBundle(identifier: "com.github.Swinject.SwinjectMVVMExample.ExampleViewModel")!
11+
static let bundle = Bundle(identifier: "com.github.Swinject.SwinjectMVVMExample.ExampleViewModel")!
1212
}
1313
return NSLocalizedString(key, bundle: Static.bundle, comment: comment ?? "")
1414
}

ExampleViewModel/RACUtil.swift

-19
This file was deleted.

0 commit comments

Comments
 (0)