How to use XIB in a Swift project iOS - ios

I had two separate Xcode projects that I have fused into a single one: a speech to text recognizer that is implemented with a XIB file, written in Objective-C, and another project that is just a conventional UI written in Swift with some more stuff. Both projects work flawlessly by themselves.
I have cleaned out all the errors, and created a Bridging header file. So far, both Swift and Objective-C modules coexist, but obviously only the Swift part runs.
I want to open the Objective-C XIB and display it in my swift-coded UI.

According to your screenshot, I assume you are using storyboard for your UI in your Swift application.
As your legacy UI is on XIB files, you need to load it programatically. To do that, you'll have to use loadNibNamed method like in the following example :
var nibs = NSBundle.mainBundle().loadNibNamed("Counter", owner: self, options: nil)
for v in nibs {
if (v is Counter) {
someViewInStoryboard.addSubview(v)
}
}
Here I have a Counter.xib file which contains an custom UIView. Class for this view is Counter, which extends UIView.
So when your XIB is loaded, browse it to find your custom view, then add it as a subview of an existing UIView in your storyboard. Variable someViewInStoryboard in my example is an IBOutlet of this UIView.

Related

How do I hook up a view in Interface Builder to an IBOutlet defined in a superclass from another framework in Xcode 11

Prior to Xcode 11 I could easily attach a view (label, switch, e.t.c) to an IBOutlet defined on a superclass, if I had the inspector window open and command clicked to my view (In this case a subclass of a UITableViewCell subclass it would open the superclass in the inspector window and I could attach to the IBOutlet. In Xcode 11 however it seems that when command clicking through to the "definition" this opens in the LHS panel, which replaces my storyboard or xib file with the views superclass.
Is there any way to open the superclass alongside the xib/storyboard any more in Xcode 11? My framework is a pre-compiled framework so I can't access the source files to open them in a new panel in Xcode.
Thought it might be wise to include a class hierarchy
LargeHeaderTableViewCell -> TableViewCell -> UITableViewCell
TableViewCell is within a pre-compiled framework (Installed using Carthage)
Edit:
To frustrate matters further... I can get the class definition of TableViewCell open next to my xib file (In a panel), however it seems you can only attach to IBOutlets in the assistant editor, not in a standard Xcode panel/tab/whatever you call it.
Found an answer (eventually) in here
I realize that this question was posted a while ago, but since I just
struggled with the same issue and finally came up with a solution, I
figured I would still post my findings...
I understand the problem to be as follows (at least that's the one I
solved):
How to have class A inherit from class B, with each class having its
own XIB file with the some common IBOutlet properties? The goal being
to be able to have the super class handle the actions related to the
IBOutlets that are common to its subclass(es), while still being able
to use Interface Builder to design the interface for the
subclass(es).*
In order to do so:
Make the IBOutlet connections in the superclass from the superclass'
XIB files Make the IBOutlet connections in the subclass from the
subclass' XIB files, with the same IBOutlet property names as in the
superclass for the ones you need to inherit. Delete the declaration of
the IBOutlet variables in the subclass

Custom ui component from framework not rendered to story board

I am creating a swift framework which has some reusable UI components.
When I am importing this framework in another application, I am able to add custom component programmatically.
But, if I add UIView on storyboard and change its class to customComponent, I am not able to see its preview on storyboard. Due to this i cannot distribute this framework to other developers as they can't visualize the component in InterfaceBuilder.
Though, I can see the component at run-time, it reduces the effectiveness of using framework in storyboard.
I have followed a link to develop swift framework.
Thre are two projects Library and SampleApp.
Libray : This is a swift framework which as one custom ui component as MyButton. its very basic ui just to avoid any confusion.
SampleApp : This application uses Library to show MyButton on sample screen
Please let me know the way i can see the preview of custom UI component from framework in any other application.
Edit1:
I have uploaded my sample code where I have applied the suggestions, but not able to resolve this.
Code
Edit 2:
Rectified the broken link of tutorial. I have not used outlets just to make it simpler.
Edit 3:
There are two projects: Library and SampleApp
I have MyButton.swift as a custom widget in Library project.
I have added UIView in StoryBoard and changed its class to MyButton(from library Framework)
Certainly there is!
After you import your framework:
import MyFramework
In IB, select the framework module:
EDIT:
Of course, I'm assuming you've made the custom components IBDesignable.
EDIT #2:
There should be no need to "import" into your storyboard. All you want to do is make sure that your view controller code has the import in it and that your storyboard's view controller is that subclass. For instance, here's a view controller named MainViewController:
And to set your view to be controlled by it:

Can I connect a custom xib to a class in a framework?

I've got a class and xib that are fairly generic. The xib has a base UI that I've included in a framework. Is it possible for me to add the framework to a project, and create a custom xib to customize my framework xib based on the new project UI needs?
|------------------------|
| MyFrameworkClass | MyCustomXib
| MyFrameworkXib |
|------------------------|
In MyCustomXib i've set the custom class of the files owner to MyFrameworkClass. I notice that I can wire up all my IBOutlets by right clicking on file's owner and dragging to the subviews to make the connections, however I cannot click on the view and drag to file's owner. Also When I go into split view mode I'm not seeing MyFrameworkClass as the code side of the split view?
Right now i'm trying to initialize it with:
MyFrameworkClass *mfc = [MyFrameworkClass alloc] initWithNibName:#"MyCustomXib" bundle:nil];
I'm confused because I'm seeing labels that are created dynamically in MyFramework class showing up in the custom UI, also newly modified button images are replacing old ones, however the buttons are not responding to touches, and the xib resizing is not working correctly.
Edit:
I just went through and compared the xib in the framework and my custom one and found that I could connect all my Outlets to the proper UI elements, however I could not connect any received actions using interface builder. By that I mean when I ctrl+click on a button and drag the connector up to File's Owner, I do not get the glow around File's Owner or a prompt to connect to any methods.
Yes. As long as the class is loaded into the runtime when the XIB file is read, it will work perfectly fine.
It will work. :-) Post additional details of what you mean by "framework" if it doesn't.

Global hook for showing UIViews

I have an iOS app I'm working on using Xamarin and MVVMCross, but I am also using a third-party native library which includes some views of it's own (loaded from .xib files with the implementation in the library). What I need to do is set some properties on those native views and I'm trying to see if there's a way to do it that doesn't involve jumping into xcode and trying to recompile that whole thing (because I can't get that working at the moment).
So my question is, is there a way to intercept, application-wide, all attempts to load a view so that I can examine the view and if it's one of those from the third-party library, set some properties on it before it's displayed?
MvvmCross has a MvxTouchViewPresenter which has a ChangePresentation property, but it seems to only apply to MvxViewController loaded by MvvmCross itself.
You can very easily intercept all attempts to access a viewmodel by overriding the Show() method on your MvxTouchPresenter. For example:
public override void Show(MvxViewModelRequest request)
{
IMvxTouchView view = this.CreateViewControllerFor(request);
UIViewController viewController = (UIViewController) view;
this.Show(view);
}
You can then examine all Views in the UIView heirarchy by using something similar to the Objective-C code in this post. You just need to walk through all the UIViews in the viewController property and identify your view (perhaps by "smelling it" with respondsToSelector; I can't figure out exactly how you'd use isKindOfClass if Xamarin doesn't know it).
I hope I understood your question. Let me know if there's anything else missing.

monotouch - reusable iOS custom view

OK, so this one is probably a bit challenging, as it is monotouch...
I have a reusable custom toolbar that that I plan to reuse on multiple screens.
I want to create the toolbar in Interface Builder
I want to be able to update labels on the toolbar from ANY view controller. So I might have five different view controllers that all have this toolbar, and can update labels on it.
So my question is:
How do I even begin to subclass UIView in MonoTouch? If I create a new "iPhone View", all it gives me is a nib. I have no place to hook up outlets or actions.
Given that you are able to tell me how to set up MonoTouch to have C# code files for subclassing UIView so I can handle events and access properties, how do I hook it up to the nib? I see a lot of people saying to use initWithFrame to call loadNibNamed in Objective-C, but this doesn't correctly translate to MonoTouch. How would I do that in MonoTouch?
Given that #1 and #2 are fulfilled, how do I load this custom toolbar into any viewcontroller, and add it at specific coordinates on the screen? Doing the initWithFrame CGRect stuff doesn't seem to have a simple path in MonoTouch
If anyone is able to figure this out, you are amazing!!!!
Thanks you in advance!
So after a lot of digging, I finally found the answer.
The most informative tutorial was here:
http://sgmunn.com/blog/2012/03/using-loadnib-to-load-a-view/
Essentially, you need to create custom subviews, set them up in the interface builder, then do some simple mapping on the MonoTouch side. But the key point that was throwing me off from the example was this:
You must, when subclassing UIView, implement the base constructor for IntPtr
When you do that, everything falls into place. You have your Outlets and Actions hooked up, and can manipulate them at will.
EDIT: To be more descriptive than just linking...
How do I even begin to subclass UIView in MonoTouch? If I create a new
"iPhone View", all it gives me is a nib. I have no place to hook up
outlets or actions.
Create a new iPhone view, it'll create a nib. Open the nib, set the "custom class" to your custom class. MonoTouch should generate it automatically. If it doesn't, create a new C# class and subclass UIView, but make sure you create the constructor for IntPtr. If you use Storyboards, when you call Storyboard.InstantiateViewController() it'll fill in the IntPtr value for you. Note that if you DO use Storyboard.InstantiateViewController, you need to set the identifier as well to your custom class' name.
Once you create that iPhone view, you should be able to open up "code view" in IB and hook up your outlets and actions.
Given that you are able to tell me how to set up MonoTouch to have C#
code files for subclassing UIView so I can handle events and access
properties, how do I hook it up to the nib? I see a lot of people
saying to use initWithFrame to call loadNibNamed in Objective-C, but
this doesn't correctly translate to MonoTouch. How would I do that in
MonoTouch?
There is no initWithFrame: or CGRect in MonoTouch, you use RectangleF. If you load the nib programmatically, you can use the constructor that takes in a RectangleF and use that to set x, y, width, height.
Given that #1 and #2 are fulfilled, how do I load this custom toolbar
into any viewcontroller, and add it at specific coordinates on the
screen? Doing the initWithFrame CGRect stuff doesn't seem to have a
simple path in MonoTouch
For Storyboards use Storyboard.InstantiateViewController (make sure you set the identifier in IB). For everything else, use:
var nibObjects = NSBundle.MainBundle.LoadNib("YourViewName", theController, null);
var instantiatedView = (YourClassName)Runtime.GetNSObject(nibObjects.ValueAt(0));
as depicted in the above link.
Enjoy! - Allison.
Instead of loading Nib files from iOS 9 onwards you can use container views and storyboard reference to achieve the same.
You can check here

Resources