ian-mcdowell / TabView

Easily add multiple tabs to your iOS app, styled similar to Safari for iPad.
MIT License
190 stars 34 forks source link

Make Storyboard friendly #4

Open Kamik423 opened 6 years ago

Kamik423 commented 6 years ago

Currently it is really badly integrated with storyboard. Everything has to happen programmatically.

Sjoerdjanssenen commented 6 years ago

I'm not too familiar with storyboards - I do most things programmatically. What would you like to see? We can't do custom segues, so I don't really know what the remaining options would be.

Kamik423 commented 6 years ago

The way it would work (I tried that once with a recent build, and it did not work, I think) is, that you have a ViewController In StoryBoard and just write the name of a custom TabViewContainerViewController in the custom class windows. It would then do all the setup itself. You would then obviously be able to write custom code for it in that class. But I think currently it has a problem with launching not programmatically, but from storyboards.

This would for example make it really easy to graphically add buttons to the UINavigationBar.

Kamik423 commented 6 years ago

So, did some experiments just now: This is my example class:

import UIKit
import TabView

class ViewController: TabViewContainerViewController<TabViewController> {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.title = "Tab View"

        let sb = UIStoryboard(name: "MainStoryboard", bundle: nil)
        let tab_a = sb.instantiateViewController(withIdentifier: "tab_a")
        let tab_b = sb.instantiateViewController(withIdentifier: "tab_b")
        let tab_c = sb.instantiateViewController(withIdentifier: "tab_c")

        // Set the tabs in this tab view
        self.primaryTabViewController.viewControllers = [
            tab_a,
            tab_b,
            tab_c
        ]
    }
}

Which is the way how it is usually done with other libraries.

It then crashes with:

TabView was compiled with optimization - stepping may behave oddly; variables may not be available.
* thread #1, queue = 'com.apple.main-thread', stop reason = Fatal error: init(coder:) has not been implemented
    frame #0: 0x000000010427bf40 libswiftCore.dylib`_swift_runtime_on_report
    frame #1: 0x00000001042cc62b libswiftCore.dylib`_swift_stdlib_reportFatalErrorInFile + 123
    frame #2: 0x000000010425c947 libswiftCore.dylib`partial apply forwarder for closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 295
    frame #3: 0x0000000103f93e7d libswiftCore.dylib`function signature specialization <Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @escaping @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <()> of Swift.StaticString.withUTF8Buffer<A>((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A + 61
    frame #4: 0x000000010425c7dd libswiftCore.dylib`merged partial apply forwarder for closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(_: Swift.StaticString, _: Swift.StaticString, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 141
    frame #5: 0x000000010425c747 libswiftCore.dylib`partial apply forwarder for closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 23
    frame #6: 0x0000000103f946e5 libswiftCore.dylib`function signature specialization <Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@error @owned Swift.Error) to @escaping @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out (), @error @owned Swift.Error), Argument Types : [@callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@error @owned Swift.Error)]> of generic specialization <()> of Swift.String._withUnsafeBufferPointerToUTF8<A>((Swift.UnsafeBufferPointer<Swift.UInt8>) throws -> A) throws -> A + 181
    frame #7: 0x000000010425c6f0 libswiftCore.dylib`partial apply forwarder for closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 144
    frame #8: 0x0000000103f93e7d libswiftCore.dylib`function signature specialization <Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @escaping @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <()> of Swift.StaticString.withUTF8Buffer<A>((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A + 61
    frame #9: 0x0000000104184968 libswiftCore.dylib`function signature specialization <Arg[1] = Exploded> of Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 136
    frame #10: 0x0000000103f936c9 libswiftCore.dylib`Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 25
  * frame #11: 0x0000000102aa736d TabView`specialized TabViewContainerViewController.init(coder:) at TabViewContainerViewController.swift:125 [opt]
    frame #12: 0x0000000102aa45f9 TabView`TabViewContainerViewController.init(coder:) at <compiler-generated>:0 [opt]
    frame #13: 0x0000000102aa461a TabView`@objc TabViewContainerViewController.init(coder:) at <compiler-generated>:0 [opt]

It also opens TabViewContainerViewController.swift and at line 125

public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }

throws

Thread 1: Fatal error: init(coder:) has not been implemented
tqml commented 4 years ago

I ran into the same problem. A basic fix (which worked for me) would be by copying the code from the other init()

 public required init?(coder aDecoder: NSCoder) { 
        self.theme = TabViewThemeLight()
        self.tabViewBar = TabViewBar(theme: self.theme)
        self.contentView = UIView()
        super.init(coder: aDecoder)
        tabViewBar.barDataSource = self
        tabViewBar.barDelegate = self
        self.ownNavigationItemObserver = NavigationItemObserver.init(navigationItem: self.navigationItem, self.refreshTabBar)
    }