Does Swift Package not support Xib files - swift

I am currently trying to add a xib file for a custom popup to my Swift Package. However, it won't says:
'Could not load NIB in bundle: 'NSBundle </private/var/containers/Bundle/Application/--/testingSDK.app> (loaded)' with name 'consentViewModal''
I have seen around people discussing that Swift Packages doesn't support anything but source code and I was wondering if this was still true. Below is the code that we are using to instantiate the custom view.
let nib = UINib(nibName: "consentViewModal", bundle: Bundle(for: consentViewModal.classForCoder()))
guard let view = nib.instantiate(withOwner: self, options: nil).first as? UIView else {
fatalError("Failed to instantiate nib \(nib)")
}
self.addSubview(view)
view.frame = self.bounds
view.autoresizingMask = [.flexibleHeight, .flexibleWidth]

When the .xib is inside of a Swift Package, you must use Bundle.module
The "module" bundle "Returns the resource bundle associated with the current Swift module."
For example:
let loadedNib = Bundle.module.loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)
guard let contentView = loadedNib?.first as? UIView else {
return nil
}
Also, ensure that within the .xib itself, that you update the "module" name to be that of your Swift Package on the right hand side "Identity Inspector". It should not say "None" as shown below:
3. Also, although I'm not sure if necessary, place the `.xib` file within the "Resources" folder under the root directory of your target folder.

Related

Could not load Main.Storyboard in XCUITest

I am try to make UITestCase for UIViewcontrollers, But when I load main storyboard in my QuizAppUITests, It could not identify from Bundle and it's gives below error
Could not find a storyboard named 'Main' in bundle NSBundle </Users/mac/Library/Developer/CoreSimulator/Devices/CC199C69-F398-4A7C-882E-BFD3E72B95D3/data/Containers/Bundle/Application/BCC3F88D-E08C-4491-8340-699EAF98AB28/QuizAppUITests-Runner.app> (loaded) (NSInvalidArgumentException)
I have added Main Storyboard in QuizAppUITests Target as well
And below is my code for test
import XCTest
#testable import QuizApp
class QuizViewControllerUITests: XCTestCase {
func makeSUT() -> QuizViewController {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: type(of: self)))
let sut = storyboard.instantiateViewController(withIdentifier: "QuizViewController") as! QuizViewController
_ = sut.view
return sut
}
func test_loadQuizViewController() {
let sut = makeSUT()
sut.headerQuestion = "Q1"
XCTAssertEqual(sut.headerQuestion, "Q1")
}
}
Is there any required to change in BuildSetting of QuizAppUITests Target?
None of this makes sense for a UI test. Instead, put your code into your unit test target, which is QuizAppTests.
My book iOS Unit Testing by Example has a chapter called "Load View Controllers". Looking there for what it says about storyboard-based view controllers:
Don't include the storyboard in your test target. Put it only in your app target.
Then you can load the storyboard with UIStoryboard(name: "Main", bundle: nil)
There's a new way to instantiate the view controller that doesn't require force-casting. Instead of instantiateViewController(withIdentifier:), use instantiateViewController(identifier:) and assign it to an explicitly typed variable.
Like this:
let sut: QuizViewController = storyboard.instantiateViewController(
identifier: "QuizViewController"
)
Since you use the name of the class as the identifier, we can even get rid of the string. This protects us from typos, at compile time:
let sut: QuizViewController = storyboard.instantiateViewController(
identifier: String(describing: QuizViewController.self)
)
Finally, instead of _ = sut.view, we can be more explicit about loading the view:
sut.loadViewIfNeeded()
This hooks up the outlet connections.
Again, all this belongs in your unit test target QuizAppTests, not your UI test target QuizAppUITests.
For your actual tests, don't just assign a property in your system under test and check that it was assigned. That doesn't prove anything. Instead, I'd focus on testing:
That outlets are not nil
That interacting with controls does what you want
That navigation works
That view appearance hasn't changed from an approved snapshot
This can all be done with TDD.

Quicklook always displays "no file to preview" error (url is valid)

I'm trying to use QuickLookController subclass as a child controller, setting its view as a subview in the parent. However, it always displays "no file to preview" message in the opening window. URL in the data source is valid, but the controller is never trying to get it! func previewItemAt index is never invoked!
func "numberOfPreviewItems" invokes always.
Please, help!
I get it. driven by example in article https://williamboles.me/hosting-viewcontrollers-in-cells/ I loaded my controller from bundle:
static func createFromStoryBoard() -> PreviewControler {
let storyboard = UIStoryboard(name: "PreviewControler", bundle: Bundle(for: PreviewControler.self))
guard let viewController = storyboard.instantiateViewController(withIdentifier: "PreviewControler") as? PreviewControler else {
fatalError("PreviewControler should be present in storyboard")
}
return viewController
}
But QuickLook controller must be created with it's constructor, so change to
let viewController = PreviewController()
solved the problem. Now all is fine.

How to call XIB in my existing XIB?

Description:- I am coding for a custom framework, For this I am using XIB everywhere, Now I want to call another XIB in my existing XIB, Its calling very fine But unable to perform button action of called XIB. Thanks in advance Here is code.
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "WelcomeVC", bundle: bundle)
self.contentView = nib.instantiate(withOwner: self, options: nil).first as! UIView
self.addSubview(self.contentView)
MVC - is global iOS concept. Learn it again.
xib - is view "V", "V" - cant been as controller "C".
if you can call xib - make it in a controller.

Cannot Programmatically Switch Storyboards

I'm attempting to switch storyboards when a button only if a condition (The textfield not being empty) is met. I found this piece of code as an answer to a similar question, and it doesn't seem to be working. My program crashes with "'Storyboard () doesn't contain a view controller with identifier 'Avatar Controller''"
I'm not completely sure as to where to find the view controller identifies, or whether or not I have to add '.storyboard' at the end of the storyboard name.
let storyboard = UIStoryboard(name: "Avatar", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "Avatar Controller")
self.navigationController!.pushViewController(vc, animated: true)
To make it works, Use Storyboard ID has to be checked
This could be happening for 2 reasons.
1) Because in your Avatar.storyboard you are referencing a view controller with the id Avatar Controller but you have not set that value on any of the view controllers in the storyboard file. Go into your Avatar.storyboard, click on the view controller you want to show and go to this panel:
Make sure that the Storyboard ID for your viewController matches what value you use in storyboard.instantiateViewController(withIdentifier: "Avatar Controller")
2) Because you are not providing a bundle when you are loading your storyboard. You are calling this
let storyboard = UIStoryboard(name: "Avatar", bundle: nil);
but because you specify bundle as nil it doesn't know where to look for the Avatar.storyboard file. To fix it, specify bundle as Bundle.main:
let storyboard = UIStoryboard(name: "Avatar", bundle: Bundle.main);

Add storyboard in Swift

How do you create multiple storyboards in the same project using Swift? I know I have to go to File -> New -> File and then choose Storyboard, but how do I integrate that storyboard into my project and navigate to the new storyboard's views in Swift code?
You need to get a reference to the desired storyboard
let aStoryboard = UIStoryboard(name: "storyboardName", bundle: nil)
Then instantiate desired view controller
let vc = aStoryboard.instantiateViewControllerWithIdentifier("viewControllerIdentifier") as! UIViewController