Xamarin IOS how to create a Stroy Board from exisitng files? - xamarin

I found this navigation bar that i want to use but a Cant seem to find the story board for it? or am i looking in the wrong place, How would i generate a story board for it?
here is the link to the bar: https://components.xamarin.com/view/flyoutnavigation

You don't generate a storyboard for it. You put a generic view into your storyboard and set it's class to be a custom subclass of FlyoutNavigationController, and set it as the root view. You can then grab all of the ViewControllers that are controlled by the FlyoutNavigationController by using something similar to the following Objective-C code:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"myViewController"];
or, in C#
UIStoryboard sb = UIStoryboard.FromName("MainStoryboard", null);
UIViewController vc = sb.InstantiateViewController("myViewController");
Here's the link for storyboarding
http://developer.xamarin.com/guides/ios/user_interface/introduction_to_storyboards/

Related

NSSplitViewController/NSSplitViewItem support in XIBs

Is there support for NSSplitViewController/NSSplitViewItem for XIBs? I see only NSSplitView
Can I just drag&drop NSViewController and subclass it as NSSplitViewController? How do I add NSSplitViewItem that it mostly works out of the box?
I can easily see support for them in storyboards.
The split view controller is not part of the object library for xib files. The easiest way to use split view controllers is to use storyboards.
If you are unwilling to use storyboards, your best option is to create a subclass of NSSplitViewController and select the checkbox to also create a xib file.
Add a split view to the split view controller xib file. Write code to load the xib file to set up the split view controller.
UPDATE
Look at the NSNib class reference for information on loading a xib file. The File's Owner of the xib file is your NSSplitViewController subclass. You may be able to use that information to set the split view controller. The worst case scenario is that you have to write code to load the split view from the xib file, set the split view controller's split view to the split view you loaded, and add the split view items to the split view controller. See the NSSplitViewController class reference for more information.
Yes it's possible. But it needs some wiring.
First add a custom subclass of NSSplitViewItem and expose viewController property as IBOutlet. Compiler will throw a warning so don't forget to mark property as dynamic.
#interface MySplitViewItem : NSSplitViewItem
#property IBOutlet NSViewController *viewController;
#end
#implementation MySplitViewItem
#dynamic viewController;
#end
In your XIB add 3 NSViewController objects. One of them change to custom class NSSplitViewController. It is important to note that one should NOT add NSSplitView. Wire NSViewControllers to it's views. Also add 2 objects and add custom class of MySplitViewItem which has exposed the viewController and wire it.
Last step. It is important to set property splitItems of NSSplitViewController before the views are loaded! Otherwise you are caught with NSAssert macro.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSNib *nib = [[NSNib alloc] initWithNibNamed:#"Empty" bundle:nil];
NSMutableArray *test = [NSMutableArray new];
NSMutableArray *splitItems = [NSMutableArray new];
NSSplitViewController *controller;
[nib instantiateWithOwner:self topLevelObjects:&test];
for (id object in test) {
if ([object isKindOfClass:[NSSplitViewController class]]) {
controller = object;
}
if ([object isKindOfClass:[NSSplitViewItem class]]) {
[splitItems addObject:object];
}
}
[controller setValue:splitItems forKey:#"splitViewItems"];
[[self window] setContentViewController:controller];
}
Here is a proof that everything is wired correctly. Note that I did not touch delegate in XIB and it is wired. Magic, I know.
PS: XIB has to be set to prefer Coder + auto layout.
Why do I prefer XIB? Because we can create larger XIB which doesn't suffer from data isolation (Easily can do bindings across NSViewControllers).
I have also experimented to add splitViewItems in viewDidLoad or setView or awakeFromNib: in custom subclass of NSSplitViewController (with exposed NSSplitViewItem properties). If someone finds solution here it will be greatly appreciated.
Solution that requires code only:
- (NSSplitViewController *)profilesSVC
{
if (!_profilesSVC) {
NSSplitViewController *splitVC = [[NSSplitViewController alloc] init];
ProfilesViewController *profilesVC = [[ProfilesViewController alloc] initWithNibName:#"Profiles" bundle:nil];
NSSplitViewItem *leftItem = [NSSplitViewItem splitViewItemWithViewController:profilesVC];
[splitVC addSplitViewItem:leftItem];
ProfileViewController *profileVC = [[ProfileViewController alloc] initWithNibName:#"Profile" bundle:nil];
NSSplitViewItem *rightItem = [NSSplitViewItem splitViewItemWithViewController:profileVC];
[splitVC addSplitViewItem:rightItem];
_profilesSVC = splitVC;
}
return _profilesSVC;
}
I too wanted to add a splitView controller to my projet (macOS app) that doesn't use storyboards.
As it turned out, this was rather easy (in XCode 12.4).
As suggested, one has to to add NSViewController objects to the xib and wire each view property to the corresponding 'pane' (subview of the split view) in interface builder.
Then create a subclass of NSSplitViewController (no need to create a xib file).
Add a third NSViewController object to the xib and change its class to your subclass. Then wire both it's view and splitView properties to your splitView. It doesn't load any view if you just wire the splitView property.
Using a subclass of NSSplitViewController may not be required, but it's convenient as you may set the splitViewItems within viewDidLoad (below). Since this object is (automatically) the delegate of the splitView, you can also override delegate methods if you wish.
That object should have outlets leading to the NSViewController objects which you previously wired to the panes in IB.
I set two outlets named leftController and rightController.
My awakeFromNib method looks like this (sorry, I don't use swift):
- (void) viewDidLoad {
self.splitView.wantsLayer = YES; // I think this is required if you use a left sidebar with vibrancy (which I do below). Otherwise appkit complains and forces the use of CA layers anyway
NSSplitViewItem *left =[NSSplitViewItem sidebarWithViewController:leftController];
[self addSplitViewItem:left];
NSSplitViewItem *right =[NSSplitViewItem splitViewItemWithViewController:rightController];
right.minimumThickness = 420;
[self addSplitViewItem:right];
}
VoilĂ !
However, I get crashes if I set thick dividers in IB as appkit calls splitView:shouldHideDividerAtIndex too early, when there is apparently no divider yet. Worse, it may pass a negative divider index (!!). But you may override the method and act accordingly and I have no issue with thin dividers.

SWRevealViewController push Segue

I am trying to use a SWrevealViewController for sidemenu . One of the options on it is "User Profile" . Since I access user's profile from various other views , I would like to have to have a push segue to this VC. However , a push segue is not working from SWRevealViewController to UserProfileVC.
Can anyone suggest how I may use a push sugue from SWRevealVC?
Here's my solution:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil]
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"YOUR_VC_STORYBOARD_ID"];
SWRevealViewControllerSeguePushController *segue = [[SWRevealViewControllerSeguePushController alloc] initWithIdentifier:#"ANY_ID" source:self destination:vc];
[segue perform];
Swift version will be
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("LoginRoot") as! UINavigationController
let segue = SWRevealViewControllerSeguePushController.init(identifier: SWSegueRearIdentifier, source: self, destination: vc)
segue.perform()
Navigation controller is UIViewcontroller. i used navigation controller otherwise use UIViewController object.
Create a custom segue from your Reveal View Controller to your side menu view controller using the storyboard editor. Set the identifier as "sw_rear", kind as "Custom" and class as "SWRevealViewControllerSegueSetController".
With this, if you create ordinary "push" segues from your menu view controller to other view controllers they should be pushed normally.

How to I launch a view controller from a tap gesture

Apologies if this is a basic question but I am new to Xcode and have a storyboard app and in the storyboard (with no segue) I have a view controller with an embedded map view.
On the storyboard screen I have an image with a tap gesture linked, I have tested the tap and it works (NSLog) but I want to know how to launch my mapview view controller and also zoom to an x&y.
My code currently has
-(IBAction)handleMapTap:(UIGestureRecognizer *)sender {
NSLog(#"Tapped");
}
& I have tried;
MMMapViewController *mapViewController = [[MMMapViewController alloc] initWithNibName:#"MapView" bundle:nil];
[self.navigationController pushViewController:mapViewController animated:YES];
My view controller has a class set as MMMapViewController I have given the view controller a storyboard id of MapView (if it's required?).
I've read a lot of stackoverflow articles but can't seem to find an answer. If anyone can help I would be really grateful.
-(IBAction)handleMapTap:(UIGestureRecognizer *)sender
{
MMMapViewController *mapViewController = [[MMMapViewController alloc] initWithNibName:#"MapView" bundle:nil];
//[self.navigationController pushViewController:mapViewController animated:YES];
[self presentModalViewController:mapViewController animated:YES];
[mapViewController release];
}
It would probably help to know what self is, if it is indeed a UIViewController, then
I would make sure that self.navigationController is not nil.
You actually have the right code, as far as I can tell, but depending on your scenario, you could get away with presenting the mapView as a modal view controller.

Launch Storyboard from within Nib?

I am looking at rebuilding the settings section of my app using the new functionality provided by storyboards. Not wanting to touch the rest of my app at this point, so my main NIB will be staying.
Now when going from my NIB'ed tabBar to another NIB I just add a viewController to the tabBar in IB and then set the NIB Name property to the NIB which I want to load when that tab is pressed.
But there is no 'storyboard name' property that I can see, so how is this done?
There is no "official" way to do it at the moment, but you can do it using some tricks.
1) add your view controller to your tabbar in nib in the usual way. Leave the nib field empty.
2) create your storyboard and add your viewcontroller. Set the class and set a storyboard ID (I'll use "theID" for this example)
3) add a static bool var to your .m file, outside implementation or interface
static BOOL aFlag = NO;
4) in your viewcontroller class override this method:
- (id) awakeAfterUsingCoder:(NSCoder *)aDecoder
{
if (!aFlag){
aFlag = YES;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
return [storyboard instantiateViewControllerWithIdentifier:#"theID"];
} else {
return self;
}
}
essentially:
when you load the object from the tab bar nib, a first call to "initWithCoder" is made, and the object loads without nib
after initWithCoder, awakeAfterUsingCoder is called and there you substitute the object with another loaded from storyboard. Object of the same class but archived in the storyboard
when you load the object from the storyboard, another call to both initWithCoder and awakeAfterUsingCoder. You use the flag to avoid a loop and return self (at the second call, the object is loaded from storyboard so returning self is ok)
I tried and it works good ;-)
If you want here is an example project: http://www.lombax.it/files/testTabNib.zip

Design custom UIView using XCode 4

This has been asked before, but I cannot find a definitive answer.
I would like to design a custom UIView class. I would like to do the layout in XCode 4 in a XIB file. Ideally:
I have the files MyView.h, MyView.m and MyView.xib.
The code defines the behavior and the XIB file defines the layout.
The code may have outlets into the XIB file to reference the layout elements.
The loader of the view could be different objects.
I'd like to be able to load the view by:
MyView *v = [MyView myView];
I've tried lots of different methods of setting the File's Owner and loading the XIB via NSBundle, but I keep getting key value coding problems.
Can anyone share the basic method to do this?
I have a repo of my current code here. As you can see, it generates a key value coding error.
Oh, I seem to have figured it out.
Keys are the following:
The XIB file UIView only needs to be a generic UIView. No need to set it to your subclass.
The File's Owner needs to be your subclass.
Outlets go to the File's Owner.
In your custom UIView, load the NIB as follows:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UINib *nib = [UINib nibWithNibName:NSStringFromClass([self class]) bundle:nil];
UIView *v = [[nib instantiateWithOwner:self options:nil] lastObject];
v.frame = self.frame;
[self addSubview:v];
}
return self;
}
How exactly do you instantiate it? In my "container" class I have an outlet for my custom view as a property, but when I try to do self.customView = [[CustomView alloc] init];
the view does not come on screen, even though I know that it's correctly initialized because I can see the NSLog()s I put in my custom view's initWithFrame: method.
From within my main view controller, BEFORE instatiating the new class, the view is as I've defined it in the storyboard: <CustomView: 0x6a83bb0; frame = (38 153; 244 153); autoresize = RM+BM; layer = <CALayer: 0x6a83c60>>
However, inside the custom view's initWithFrame:, the frame is {{0, 0}, {0, 0}} and the view is <UIView: 0x68ca160; frame = (0 0; 0 0); autoresize = W+H; layer = <CALayer: 0x68d1800>>.
After the initialization has taken place, the main view's property for the custom view is barely (null), which baffles me.
I'm sure I'm missing something very simple here. Are you even supposed to define the custom view's within the main view in the storyboard at all?
Thanks!

Resources