Skip to content

Commit

Permalink
Merge pull request #19 from cats-oss/add-workaround
Browse files Browse the repository at this point in the history
Add workaround for SR-12081
  • Loading branch information
marty-suzuki committed Jan 29, 2020
2 parents 3f59358 + 442bdea commit b90925c
Show file tree
Hide file tree
Showing 11 changed files with 6,229 additions and 35 deletions.
67 changes: 67 additions & 0 deletions Documentation/Unio0_9_0MigrationGuide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Unio 0.9.0 Migration Guide

Unio 0.9.0 introduces some breaking changes.

Those changes are related [SR-12081](https://bugs.swift.org/browse/SR-12081).

## Classes

- [ADD] `AnyLogicBasedStream<Input: InputType, Output: OutputType>`

## Typealias

- [REPLACE] `typealias UnioStream<Logic: LogicType> = PrimitiveStream<Logic> & LogicType` -> `typealias UnioStream<Logic: LogicType> = AnyLogicBasedStream<Logic.Input, Logic.Output> & LogicType`

## Note

- Previous `UnioStream<Logic: LogicType>` (less than 0.8.0) had `init(input: Input, state: State, extra: Extra)` as the designated initializer. Current `UnioStream<Logic: LogicType>` (greater than 0.9.0) also has `init(input: Input, state: State, extra: Extra)` but it is the convenience initializer. So, you should fix initializers like that.

Before
```swift
init(extra: Extra) {
super.init(input: Input(), state: State(), extra: extra)
}
```

After
```swift
convenience init(extra: Extra) {
self.init(input: Input(), state: State(), extra: extra)
}
```

If you defined some properties in UnioStream subclasses, you must change initializers to like that.

Before
```swift
class NumberStream: UnioStream<NumberStream> {
let number: Int

init(number: Int, extra: Extra) {
self.number = number
super.init(input: Input(), state: State(), extra: extra)
}
}
```

After
```swift
class NumberStream: UnioStream<NumberStream> {
let number: Int

init(number: Int, extra: Extra) {
self.number = number
super.init(input: Input(), state: State(), extra: extra, logic: NumberStream.self)
}

@available(*, unavailable)
init<Logic: LogicType>(input: Logic.Input,
state: Logic.State,
extra: Logic.Extra,
logic _: Logic.Type) where Input == Logic.Input, Output == Logic.Output {
fatalError("could not be called anymore")
}
}
```

- If you want to use existing UnioStream initializer (less than 0.8.0), please define `typealise UnioSteram<Logic: LogicType> = SR12081.UnioSteram<Logic>` in your Application Target.
3 changes: 3 additions & 0 deletions Example/UnioSample/GitHub.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import Foundation
import Unio

enum GitHub {

Expand All @@ -20,3 +21,5 @@ enum GitHub {
let htmlUrl: URL
}
}

typealias UnioStream<Logic: LogicType> = SR12081.UnioStream<Logic>
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ Be able to define a subclass of UnioStream like this.
```swift
final class GitHubSearchViewStream: UnioStream<GitHubSearchViewStream> {

init() {
super.init(input: Input(), state: State(), extra: Extra())
convenience init() {
self.init(input: Input(), state: State(), extra: Extra())
}
}
```
Expand All @@ -251,8 +251,8 @@ protocol GitHubSearchViewStreamType: AnyObject {

final class GitHubSearchViewStream: UnioStream<GitHubSearchViewStream>, GitHubSearchViewStreamType {

init() {
super.init(input: Input(), state: State(), extra: Extra())
convenience init() {
self.init(input: Input(), state: State(), extra: Extra())
}

typealias State = NoState
Expand Down Expand Up @@ -319,6 +319,7 @@ The documentation which does not use `KeyPath Dynamic Member Lookup` is [here](h

- [Unio 0.5.0 Migration Guide](./Documentation/Unio0_5_0MigrationGuide.md)
- [Unio 0.6.0 Migration Guide](./Documentation/Unio0_6_0MigrationGuide.md)
- [Unio 0.9.0 Migration Guide](./Documentation/Unio0_9_0MigrationGuide.md)

### Xcode Template

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ protocol ___VARIABLE_productName___ViewStreamType: AnyObject {

final class ___VARIABLE_productName___ViewStream: UnioStream<___VARIABLE_productName___ViewStream>, ___VARIABLE_productName___ViewStreamType {

init(extra: Extra = .init()) {
super.init(input: Input(),
state: State(),
extra: extra)
convenience init(extra: Extra = .init()) {
self.init(input: Input(),
state: State(),
extra: extra)
}
}

Expand Down
8 changes: 4 additions & 4 deletions Tools/UnioStream.xctemplate/___FILEBASENAME___Stream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ protocol ___VARIABLE_productName___StreamType: AnyObject {

final class ___VARIABLE_productName___Stream: UnioStream<___VARIABLE_productName___Stream>, ___VARIABLE_productName___StreamType {

init(extra: Extra = .init()) {
super.init(input: Input(),
state: State(),
extra: extra)
convenience init(extra: Extra = .init()) {
self.init(input: Input(),
state: State(),
extra: extra)
}
}

Expand Down
12 changes: 12 additions & 0 deletions Unio.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,16 @@
9DA555D52241FC6600EC8CC3 /* ValueAccessible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DA555D42241FC6600EC8CC3 /* ValueAccessible.swift */; };
E9A6617E23839933007D4AEC /* AnyUnioStreamTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9A6617D23839933007D4AEC /* AnyUnioStreamTests.swift */; };
E9A6618223839952007D4AEC /* AnyUnioStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9A6618123839952007D4AEC /* AnyUnioStream.swift */; };
ED4D482A23DC1B01004868D9 /* AnyLogicBasedStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED4D482923DC1B01004868D9 /* AnyLogicBasedStream.swift */; };
ED4D482C23DC2BC2004868D9 /* SR12081Check.Streams.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED4D482B23DC2BC2004868D9 /* SR12081Check.Streams.swift */; };
ED6897C122B184EE00B04DA0 /* PrimitiveProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6897C022B184EE00B04DA0 /* PrimitiveProperty.swift */; };
ED74A63D2243C2EE00D4E99C /* PrimitivePropertyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED74A63C2243C2EE00D4E99C /* PrimitivePropertyTests.swift */; };
ED74A6402243C3DB00D4E99C /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D2E26A82240D1F200C9EDF7 /* RxSwift.framework */; };
ED74A6432243C43400D4E99C /* RxSwift.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 9D2E26A82240D1F200C9EDF7 /* RxSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
ED74A7382243D99D00D4E99C /* WrappersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED74A7372243D99D00D4E99C /* WrappersTests.swift */; };
ED74A73A2243E0CC00D4E99C /* DependencyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED74A7392243E0CC00D4E99C /* DependencyTests.swift */; };
ED74A73C2243E43D00D4E99C /* UnioStreamTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED74A73B2243E43D00D4E99C /* UnioStreamTests.swift */; };
ED82DE2C23DC2FF9003B6855 /* SR12081Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED82DE2B23DC2FF9003B6855 /* SR12081Tests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -87,11 +90,14 @@
9DA5623F2362DB760048F2B9 /* Unio.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Unio.xcconfig; sourceTree = "<group>"; };
E9A6617D23839933007D4AEC /* AnyUnioStreamTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyUnioStreamTests.swift; sourceTree = "<group>"; };
E9A6618123839952007D4AEC /* AnyUnioStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyUnioStream.swift; sourceTree = "<group>"; };
ED4D482923DC1B01004868D9 /* AnyLogicBasedStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyLogicBasedStream.swift; sourceTree = "<group>"; };
ED4D482B23DC2BC2004868D9 /* SR12081Check.Streams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SR12081Check.Streams.swift; sourceTree = "<group>"; };
ED6897C022B184EE00B04DA0 /* PrimitiveProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrimitiveProperty.swift; sourceTree = "<group>"; };
ED74A63C2243C2EE00D4E99C /* PrimitivePropertyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrimitivePropertyTests.swift; sourceTree = "<group>"; };
ED74A7372243D99D00D4E99C /* WrappersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappersTests.swift; sourceTree = "<group>"; };
ED74A7392243E0CC00D4E99C /* DependencyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DependencyTests.swift; sourceTree = "<group>"; };
ED74A73B2243E43D00D4E99C /* UnioStreamTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnioStreamTests.swift; sourceTree = "<group>"; };
ED82DE2B23DC2FF9003B6855 /* SR12081Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SR12081Tests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -141,6 +147,7 @@
isa = PBXGroup;
children = (
9DA555C92241DE5F00EC8CC3 /* RxTypes */,
ED4D482923DC1B01004868D9 /* AnyLogicBasedStream.swift */,
E9A6618123839952007D4AEC /* AnyUnioStream.swift */,
9D2E269C2240D1CA00C9EDF7 /* Dependency.swift */,
9D2E26972240D1CA00C9EDF7 /* ExtraType.swift */,
Expand All @@ -162,6 +169,7 @@
children = (
ED74A63E2243C2F200D4E99C /* TestCases */,
9D2E26892240D18500C9EDF7 /* Info.plist */,
ED4D482B23DC2BC2004868D9 /* SR12081Check.Streams.swift */,
);
path = UnioTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -202,6 +210,7 @@
E9A6617D23839933007D4AEC /* AnyUnioStreamTests.swift */,
ED74A7392243E0CC00D4E99C /* DependencyTests.swift */,
ED74A63C2243C2EE00D4E99C /* PrimitivePropertyTests.swift */,
ED82DE2B23DC2FF9003B6855 /* SR12081Tests.swift */,
ED74A73B2243E43D00D4E99C /* UnioStreamTests.swift */,
ED74A7372243D99D00D4E99C /* WrappersTests.swift */,
);
Expand Down Expand Up @@ -325,6 +334,7 @@
9DA555CB2241DE8400EC8CC3 /* BehaviorSubjectType.swift in Sources */,
9D2E26A62240D1CA00C9EDF7 /* Dependency.swift in Sources */,
9D2E26A12240D1CA00C9EDF7 /* ExtraType.swift in Sources */,
ED4D482A23DC1B01004868D9 /* AnyLogicBasedStream.swift in Sources */,
9D2E26A22240D1CA00C9EDF7 /* InputType.swift in Sources */,
9D2E269F2240D1CA00C9EDF7 /* LogicType.swift in Sources */,
9D2E26A52240D1CA00C9EDF7 /* OutputType.swift in Sources */,
Expand All @@ -342,6 +352,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
ED82DE2C23DC2FF9003B6855 /* SR12081Tests.swift in Sources */,
ED4D482C23DC2BC2004868D9 /* SR12081Check.Streams.swift in Sources */,
ED74A73A2243E0CC00D4E99C /* DependencyTests.swift in Sources */,
E9A6617E23839933007D4AEC /* AnyUnioStreamTests.swift in Sources */,
ED74A63D2243C2EE00D4E99C /* PrimitivePropertyTests.swift in Sources */,
Expand Down
64 changes: 64 additions & 0 deletions Unio/AnyLogicBasedStream.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//
// AnyLogicBasedStream.swift
// Unio
//
// Created by marty-suzuki on 2020/01/25.
// Copyright 漏 2020 tv.abema. All rights reserved.
//

/// Makes possible to implement Unidirectional input / output stream and be able to implement LogicType to its self.
///
/// ```
/// // Usage Example
/// class GithubSearchStream: UnioStream<GithubSearchStream> {
/// struct Input: InputType {}
///
/// struct Output: OutputType {}
///
/// struct State: StateType {}
///
/// struct Extra: ExtraType {}
///
/// convenience init() {
/// self.init(input: Input(), state: State(), extra: Extra())
/// }
///
/// static func bind(from dependency: Dependency<Input, State, Extra>, disposeBag: DisposeBag) -> Output {
/// return Output()
/// }
/// }
/// ```
public typealias UnioStream<Logic: LogicType> = AnyLogicBasedStream<Logic.Input, Logic.Output> & LogicType

/// A type which have LogicType based initializer.
public protocol AnyLogicBasedStreamType: UnioStreamType {
init<Logic: LogicType>(input: Logic.Input,
state: Logic.State,
extra: Logic.Extra,
logic _: Logic.Type) where Input == Logic.Input, Output == Logic.Output
}

extension AnyLogicBasedStreamType where Self: LogicType {
public init(input: Input, state: State, extra: Extra) {
self.init(input: input, state: state, extra: extra, logic: Self.self)
}
}

/// A type-erased wrapper which have LogicType based initializer.
open class AnyLogicBasedStream<Input: InputType, Output: OutputType>: AnyLogicBasedStreamType {
public let input: InputWrapper<Input>
public let output: OutputWrapper<Output>

/// Strong reference to the actual stream for preventing it being released.
private let _stream: AnyObject

required public init<Logic: LogicType>(input: Logic.Input,
state: Logic.State,
extra: Logic.Extra,
logic _: Logic.Type) where Input == Logic.Input, Output == Logic.Output {
let stream = PrimitiveStream<Logic>(input: input, state: state, extra: extra)
self.input = stream.input
self.output = stream.output
self._stream = stream
}
}
48 changes: 29 additions & 19 deletions Unio/UnioStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,35 @@ public protocol UnioStreamType: AnyObject {
var output: OutputWrapper<Output> { get }
}

/// Makes possible to implement Unidirectional input / output stream and be able to implement LogicType to its self.
///
/// ```
/// // Usage Example
/// class GithubSearchStream: UnioStream<GithubSearchStream> {
/// struct Input: InputType {}
///
/// struct Output: OutputType {}
///
/// struct State: StateType {}
///
/// struct Extra: ExtraType {}
///
/// static func bind(from dependency: Dependency<Input, State, Extra>, disposeBag: DisposeBag) -> Output {
/// return Output()
/// }
/// }
/// ```
public typealias UnioStream<Logic: LogicType> = PrimitiveStream<Logic> & LogicType & UnioStreamType
/// A namespace of a swift bug.
/// - seealso: https://bugs.swift.org/browse/SR-12081
@available(*, deprecated, message: "These is a possibility of runtime crash on greater than iOS 13 if defined hundreds of SR12081.UnioStream subclasses.")
public enum SR12081 {

/// Makes possible to implement Unidirectional input / output stream and be able to implement LogicType to its self.
///
/// ```
/// // Usage Example
/// class GithubSearchStream: UnioStream<GithubSearchStream> {
/// struct Input: InputType {}
///
/// struct Output: OutputType {}
///
/// struct State: StateType {}
///
/// struct Extra: ExtraType {}
///
/// init() {
/// super.init(input: Input(), state: State(), extra: Extra())
/// }
///
/// static func bind(from dependency: Dependency<Input, State, Extra>, disposeBag: DisposeBag) -> Output {
/// return Output()
/// }
/// }
/// ```
public typealias UnioStream<Logic: LogicType> = PrimitiveStream<Logic> & LogicType & UnioStreamType
}

/// Makes possible to implement Unidirectional input / output stream.
open class PrimitiveStream<Logic: LogicType> {
Expand Down

0 comments on commit b90925c

Please sign in to comment.