Skip to content

Instantly share code, notes, and snippets.

@DevAndArtist
Last active February 18, 2020 09:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DevAndArtist/053ac16082442cae14a911a5ec6c9d0b to your computer and use it in GitHub Desktop.
Save DevAndArtist/053ac16082442cae14a911a5ec6c9d0b to your computer and use it in GitHub Desktop.
// SOME OBSERVATIONS:
// * In Xcode 11.3.1 `V_Struct_Representable_ObservedObject` won't update
// which is clearly a bug. This bug is fixed in Xcode 11.4 beta 1.
//
// * `V_Struct` and `V_Struct_Representable` both never update because
// they shouldn't as the framework internal raw-diffing likely won't
// identify any change. (EXPECTED BEHAVIOR)
//
// * `V_Class` and `V_Class_ObservedObject` both produce a runtime crash,
// which might be a bug as well. `View` conforming types shouldn't be
// classes, yet both `UIViewRepresentable` and
// `UIViewControllerRepresentable` can be classes and they don't crash.
// Therefore this seems like another bug.
//
import Combine
import SwiftUI
import UIKit
// Helper
func createUILabel() -> UILabel {
let label = UILabel()
label.textAlignment = .center
return label
}
func log<T>(_ t: T, function: StaticString = #function) {
print("\(function) ๐Ÿ”ธ \(type(of: t))")
}
func log<T>(_ t: T, function: StaticString = #function) where T: AnyObject {
print("\(function) ๐Ÿ”น \(type(of: t)) ๐Ÿ”น \(ObjectIdentifier(t))")
}
protocol P: View {
init(model: Model)
}
class VC: UIViewController {
let label = createUILabel()
override func loadView() {
view = label
}
}
// Model
class Model: ObservableObject {
let objectWillChange = ObservableObjectPublisher()
var count = 0 {
willSet {
objectWillChange.send()
}
}
var _timer: Timer?
init() {
self._timer = Timer.scheduledTimer(
timeInterval: 2,
target: self,
selector: #selector(_countUp),
userInfo: nil,
repeats: true
)
}
@objc
func _countUp() {
count += 1
}
}
// Different view structs
struct V_Struct: View, P {
var model: Model
init(model: Model) {
self.model = model
log(self)
}
var body: some View {
log(self)
return Text("\(model.count)")
}
}
struct V_Struct_ObservedObject: View, P {
@ObservedObject
var model: Model
init(model: Model) {
self.model = model
log(self)
}
var body: some View {
log(self)
return Text("\(model.count)")
}
}
struct V_Struct_Representable: UIViewRepresentable, P {
var model: Model
init(model: Model) {
self.model = model
log(self)
}
func makeUIView(context: Context) -> UILabel {
log(self)
return createUILabel()
}
func updateUIView(_ uiView: UILabel, context: Context) {
log(self)
uiView.text = "\(model.count)"
}
}
struct V_Struct_Representable_ObservedObject: UIViewRepresentable, P {
@ObservedObject
var model: Model
init(model: Model) {
self.model = model
log(self)
}
func makeUIView(context: Context) -> UILabel {
log(self)
return createUILabel()
}
func updateUIView(_ uiView: UILabel, context: Context) {
log(self)
uiView.text = "\(model.count)"
}
}
// Different view classes
final class V_Class: View, P {
var model: Model
init(model: Model) {
self.model = model
log(self)
}
deinit {
log(self)
}
var body: some View {
log(self)
return Text("\(model.count)")
}
}
final class V_Class_ObservedObject: View, P {
@ObservedObject
var model: Model
init(model: Model) {
self.model = model
log(self)
}
deinit {
log(self)
}
var body: some View {
log(self)
return Text("\(model.count)")
}
}
final class V_Class_Representable: UIViewRepresentable, P {
var model: Model
init(model: Model) {
self.model = model
log(self)
}
deinit {
log(self)
}
func makeUIView(context: Context) -> UILabel {
log(self)
return createUILabel()
}
func updateUIView(_ uiView: UILabel, context: Context) {
log(self)
uiView.text = "\(model.count)"
}
}
final class V_Class_Representable_ObservedObject: UIViewRepresentable, P {
@ObservedObject
var model: Model
init(model: Model) {
self.model = model
log(self)
}
deinit {
log(self)
}
func makeUIView(context: Context) -> UILabel {
log(self)
return createUILabel()
}
func updateUIView(_ uiView: UILabel, context: Context) {
log(self)
uiView.text = "\(model.count)"
}
}
final class VC_Class_Representable: UIViewControllerRepresentable, P {
var model: Model
init(model: Model) {
self.model = model
log(self)
}
deinit {
log(self)
}
func makeUIViewController(context: Context) -> VC {
log(self)
return VC()
}
func updateUIViewController(_ uiViewController: VC, context: Context) {
log(self)
uiViewController.label.text = "\(model.count)"
}
}
final class VC_Class_Representable_ObservedObject:
UIViewControllerRepresentable,
P
{
@ObservedObject
var model: Model
init(model: Model) {
self.model = model
log(self)
}
deinit {
log(self)
}
func makeUIViewController(context: Context) -> VC {
log(self)
return VC()
}
func updateUIViewController(_ uiViewController: VC, context: Context) {
log(self)
uiViewController.label.text = "\(model.count)"
}
}
// Test
struct ContentView: View {
@ObservedObject
var model: Model = Model()
func create<T>(_ tType: T.Type) -> some View where T: P {
VStack
.init {
Text(String(describing: tType)).font(.system(size: 10))
tType.init(model: model).frame(width: 100, height: 20)
}
.border(Color.red)
.fixedSize()
}
var body: some View {
print("\n๐ŸŸข", #function, type(of: self), "\n")
return VStack {
Group {
Text("value views")
create(V_Struct.self)
create(V_Struct_ObservedObject.self)
create(V_Struct_Representable.self)
create(V_Struct_Representable_ObservedObject.self)
}
Group {
Text("object views")
// Runtime crash: EXC_BAD_INSTRUCTION
// create(V_Class.self)
// create(V_Class_ObservedObject.self)
create(V_Class_Representable.self)
create(V_Class_Representable_ObservedObject.self)
create(VC_Class_Representable.self)
create(VC_Class_Representable_ObservedObject.self)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
/* SOME CYCLES IN XCODE 11.3.1:
๐ŸŸข body ContentView
init(model:) ๐Ÿ”ธ V_Struct
init(model:) ๐Ÿ”ธ V_Struct_ObservedObject
init(model:) ๐Ÿ”ธ V_Struct_Representable
init(model:) ๐Ÿ”ธ V_Struct_Representable_ObservedObject
init(model:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x000060000025fba0)
init(model:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600000238660)
init(model:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238760)
init(model:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x00006000002382a0)
body ๐Ÿ”ธ V_Struct
body ๐Ÿ”ธ V_Struct_ObservedObject
makeUIView(context:) ๐Ÿ”ธ V_Struct_Representable
updateUIView(_:context:) ๐Ÿ”ธ V_Struct_Representable
makeUIView(context:) ๐Ÿ”ธ V_Struct_Representable_ObservedObject
updateUIView(_:context:) ๐Ÿ”ธ V_Struct_Representable_ObservedObject
makeUIView(context:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x000060000025fba0)
updateUIView(_:context:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x000060000025fba0)
makeUIView(context:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600000238660)
updateUIView(_:context:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600000238660)
makeUIViewController(context:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238760)
updateUIViewController(_:context:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238760)
makeUIViewController(context:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x00006000002382a0)
updateUIViewController(_:context:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x00006000002382a0)
๐ŸŸข body ContentView
init(model:) ๐Ÿ”ธ V_Struct
init(model:) ๐Ÿ”ธ V_Struct_ObservedObject
init(model:) ๐Ÿ”ธ V_Struct_Representable
init(model:) ๐Ÿ”ธ V_Struct_Representable_ObservedObject
init(model:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238da0)
init(model:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600000238f20)
init(model:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238f40)
init(model:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600000238f80)
body ๐Ÿ”ธ V_Struct_ObservedObject
updateUIView(_:context:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238da0)
updateUIView(_:context:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600000238f20)
updateUIViewController(_:context:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238f40)
updateUIViewController(_:context:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600000238f80)
deinit ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x000060000025fba0)
deinit ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600000238660)
deinit ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238760)
deinit ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x00006000002382a0)
๐ŸŸข body ContentView
init(model:) ๐Ÿ”ธ V_Struct
init(model:) ๐Ÿ”ธ V_Struct_ObservedObject
init(model:) ๐Ÿ”ธ V_Struct_Representable
init(model:) ๐Ÿ”ธ V_Struct_Representable_ObservedObject
init(model:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238660)
init(model:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600000239540)
init(model:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238760)
init(model:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x00006000002384c0)
body ๐Ÿ”ธ V_Struct_ObservedObject
updateUIView(_:context:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238660)
updateUIView(_:context:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600000239540)
updateUIViewController(_:context:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238760)
updateUIViewController(_:context:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x00006000002384c0)
deinit ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238da0)
deinit ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600000238f20)
deinit ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600000238f40)
deinit ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600000238f80)
*/
/* SOME CYCLES IN XCODE 11.4 beta 1:
๐ŸŸข body ContentView
init(model:) ๐Ÿ”ธ V_Struct
init(model:) ๐Ÿ”ธ V_Struct_ObservedObject
init(model:) ๐Ÿ”ธ V_Struct_Representable
init(model:) ๐Ÿ”ธ V_Struct_Representable_ObservedObject
init(model:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d8ecc0)
init(model:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d8ec40)
init(model:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d8ed00)
init(model:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d8ece0)
body ๐Ÿ”ธ V_Struct
body ๐Ÿ”ธ V_Struct_ObservedObject
makeUIView(context:) ๐Ÿ”ธ V_Struct_Representable
updateUIView(_:context:) ๐Ÿ”ธ V_Struct_Representable
makeUIView(context:) ๐Ÿ”ธ V_Struct_Representable_ObservedObject
updateUIView(_:context:) ๐Ÿ”ธ V_Struct_Representable_ObservedObject
makeUIView(context:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d8ecc0)
updateUIView(_:context:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d8ecc0)
makeUIView(context:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d8ec40)
updateUIView(_:context:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d8ec40)
makeUIViewController(context:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d8ed00)
updateUIViewController(_:context:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d8ed00)
makeUIViewController(context:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d8ece0)
updateUIViewController(_:context:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d8ece0)
๐ŸŸข body ContentView
init(model:) ๐Ÿ”ธ V_Struct
init(model:) ๐Ÿ”ธ V_Struct_ObservedObject
init(model:) ๐Ÿ”ธ V_Struct_Representable
init(model:) ๐Ÿ”ธ V_Struct_Representable_ObservedObject
init(model:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d94340)
init(model:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d94300)
init(model:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d94440)
init(model:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d943a0)
body ๐Ÿ”ธ V_Struct_ObservedObject
updateUIView(_:context:) ๐Ÿ”ธ V_Struct_Representable_ObservedObject
updateUIView(_:context:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d94340)
updateUIView(_:context:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d94300)
updateUIViewController(_:context:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d94440)
updateUIViewController(_:context:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d943a0)
deinit ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d8ecc0)
deinit ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d8ec40)
deinit ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d8ed00)
deinit ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d8ece0)
๐ŸŸข body ContentView
init(model:) ๐Ÿ”ธ V_Struct
init(model:) ๐Ÿ”ธ V_Struct_ObservedObject
init(model:) ๐Ÿ”ธ V_Struct_Representable
init(model:) ๐Ÿ”ธ V_Struct_Representable_ObservedObject
init(model:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d94800)
init(model:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d94480)
init(model:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d948a0)
init(model:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d948c0)
body ๐Ÿ”ธ V_Struct_ObservedObject
updateUIView(_:context:) ๐Ÿ”ธ V_Struct_Representable_ObservedObject
updateUIView(_:context:) ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d94800)
updateUIView(_:context:) ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d94480)
updateUIViewController(_:context:) ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d948a0)
updateUIViewController(_:context:) ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d948c0)
deinit ๐Ÿ”น V_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d94340)
deinit ๐Ÿ”น V_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d94300)
deinit ๐Ÿ”น VC_Class_Representable ๐Ÿ”น ObjectIdentifier(0x0000600002d94440)
deinit ๐Ÿ”น VC_Class_Representable_ObservedObject ๐Ÿ”น ObjectIdentifier(0x0000600002d943a0)
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment