Switching from a UITableview controller to a viewcontroller - xcode

I'm just learning and playing with the apple Seismic XML example
http://developer.apple.com/library/ios/#samplecode/SeismicXML/Introduction/Intro.html
I've got most of it figured out, but the one area I can't get past is, if I want to remove the tableview controller and create a view controller populated with a tableview. I can get the tableview to appear fine, but no matter what I try I can never get it to populate.
In the viewdidload area I can setup the tableview, color the background, do whatever I want to do, but I seem to 'lose' control of it somehow.
In short, would someone please be able to give me the steps involved in correctly changing the tableviewcontroller to a viewcontroller with a tableview in the apple example?
Thank you.

Lian, you need to read the documentation on UITableViewController. http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/AboutTableViewsiPhone/AboutTableViewsiPhone.html
I'm not sure what you mean by "remove the tableview controller and create a view controller populated with a tableview" or why you would want this configuration. If you're having trouble with populating the tableViewController, you just pass in the data, usually from an NSArray or NSDictionary in the cellForRowAtIndexPath method. You either need to select the UITableViewController template when you create the class file or include the UITableViewDataSource and UITableViewDelegate if you're adding a tableView to a ViewController.
If you mean you want to change the view controller on screen, then you're looking to pop to another view using the navigation controller.

Related

Draw manual segue to myself

I have a view controller contains a table view that displays list of items. Each item could contains list of items (or could be a leaf).
To drilldow the list items, I would like to create a show/push segue, kinda in recursively way, but I seem not able to draw the manual segue to the view controller itself?
Is it supported?
I was playing around with it just after leaving that first comment - I don't think you can have a manual segue to the same view controller!
The best thing to do would be to give that view controller a storyboard identifier (e.g Selection and then create an instance of that view controller with (in Swift):
let subCategoryVC = storyboard.instantiateViewControllerWithIdentifier("Selection") as! SelectionViewController
or in Objective-C:
SelectionViewController *subCategoryVC = (SelectionViewController *) [self.storyboard instantiateViewControllerWithIdentifier:#"Selection"];
(Docs for UIStoryboard.instantiateViewControllerWithIdentifier:)
You could put that in your table view section method along with a manual segue to the leaf view controller.
(The code above assumes the view controller with the table view is called SelectionViewController!)
As Rich mentioned, this is probably not doable as for today. There are two workaround/solutions I can think of:
Instaniate the vc programatically from storyboard and programatically
use navigationController to push it. (I think this is what Rich was
talking about.)
Embed the View Controller in another Navigation Controller and draw
the manual segue to the Navigation Controller.
I choose the 2nd one just because it is very easy and more visual in storyboard. The first one should just work, too.

NSToolbar in Xcode 7 using Storyboards (NSWindowController -> NSSplitViewController)

Hi I've seen this question asked a few times already but with no definite answer yet so I created it for xcode 7 and swift2 (which may have changed things a bit anyway).
I created a project using Xcode 7 and Cocoa OSX Story boards + swift2, so my project started with a NSWindowController that Connects to a NSViewController (as expected!). I added a NSToolbar to my window controller and added a NSButton to the toolbar. I changed my NSViewController to be one of the new NSSplitViewController that links to three NSViewControllers and displays their views horizontally - with vertical dividers - (similar to the layout you see in the photo app or pages in Yosemite +). My final goal will be that the button in My toolbar shows and hides the first split.
It is my understanding is, and I would expect that to achieve this I should create an action in the NSSplitViewController that changes the auto layout constrains more or less in the way they are working it out here: How to do collapse and expand view in mac application?.
And then somehow link this action to the NSButton that is in the Toolbar... which happens to be in the NSWindowController (far up and isolated in the hierarchy)...
I have already gone through other questions about NSToolbar and storyboards and failed to accomplish my goal:
The YouTube video: Cocoa Programming L17 - NSToolbar which is the closest I found to solve the problem, but his method does not work for storyboards, only creating your own xib file.
In this question: How to use NSToolBar in Xcode 6 and Storyboard? One person proposes to make the link using the first reponder and expecting everything to hook up at run-time (which looks a bit dodgy and not the way apple would implement it I think...). A second person suggested to create a view controller variable in the NSWindowController and manipulate its properties from there... but again, a bit dodgy too.
One latest comment I saw in that question which seems the best way to tackle the problem (but still not as good as I guess it could be) is to add a NSObjectController to the dock of each scene and when the scene loads, set the values of the objects to the other secene's controller. Is this really the best way to go ahead? If so, how could I achieve this one?
Apple did mention (again) in WWDC15 that they created storyboards for osx and the split-view controller that owns view-controllers so that you can move your logic and work to the specific view-controller, so I would be expecting to do everything from inside my split-view controller as this is the target that needs to change.
Does anyone know how to achieve this from the view controller itself? I really haven't been able to find a way to connect my ToolBarItem to it.
OK, I've created this question quite a few days ago and no answer so far so I've answer with what I recently did to overcome the problem.
After I created my Xcode project I did this:
Created a subclass MySplitViewController for the NSSplitViewController
Added an IBOutlet for each NSSplitViewItem. For example:
#IBOutlet weak var mySplitViewItem: NSSplitViewItem!
Created a subclass WindowController for the NSWindowController
Added an IBAction in the WindowController class that links to the NSToolbarItem (my button)
Added a property that gets the Window Controller's content as MySplitViewController
var mySplitViewController: MySplitViewController {
return self.window?.contentViewController as! MySplitViewController
}
Now I can access the split view controller's property from the Window Controller in the action I created:
mySplitViewController. mySplitViewItem.collapsed = true
I created some sample code that does this (but using a view controller and changing the text for a label here, just in case someone wants to see a working project with this behaviour. And a blog post about it too :)
One person proposes to make the link using the first reponder and expecting everything to hook up at run-time (which looks a bit dodgy and not the way apple would implement it I think...).
I think this first responder method is actually the proper way.
As an example:
Add something similar to the following, in whichever view controller makes sense.
#IBAction func doSomething(_ sender: AnyObject?) {
print("Do something.")
}
This will magically show up in the first responder:
In your storyboard, right-click the orange "first responder" icon above your window controller, and you should see doSomething in the very long list. You just need to connect that up to your toolbar button.
In the following screen capture, you can see my "Toggle Sidebar" button is connected to the toggleSidebar action in my first responder.
I didn't even have to write this method — it's provided by NSSplitViewController:
#IBAction open func toggleSidebar(_ sender: Any?)
So, I was working this same issue and finding no solution as you experienced. I read your post and was trying to figure how I would implement your solution when it occurred to me to use a notification. In about 30 seconds, I had a perfectly fine working solution:
In your windowController add an IBAction to post a notification like so
-(IBAction)toggleMasterViewClicked:(id)sender
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"TestNotification" object:nil];
}
Hook up that action to your NSToolbarItem, then in the viewController add self as an observer for that notification like so
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(toggleMasterView:) name:#"TestNotification" object:nil];
In your case, selector would be updateMyLabelText
I don't really see any downside here. No reference to other objects needed, no dependancies. Works flawlessly for me
While connectiong IBActions works by using either the First Responder or by adding an "Object" to the scene, then changing its class to the window's view controller class, this doesn't help with IBOutlets and delegates that you'd like to point to the view controller.
Here's a work-around for that:
Add the Toolbar to the View Controller, not to its Window. That way, you can make all the IBOutlet connections in the View Controller Scene easily. I've done that for years and found no issues with it, even when using Tabs.
You'll have to assign the window's toolbar in code, then. E.g. like this:
#interface ViewController ()
#property (weak) IBOutlet NSToolbar *toolbar; // connect this in your storyboard to the Toolbar that you moved to the View Controller Scene
#end
- (void)viewWillAppear {
[super viewWillAppear];
self.view.window.toolbar = self.toolbar;
}

Keep leftBarButtonItems on new UIViewcontroller when pushed

I have a UIViewController embedded in a UINavigationController. The rootViewController now contains already some buttons as leftBarButtonItems.
Now when I push a new UIViewController on top of the UINavigationController I want the new UIViewController to keep the existing leftBarButtonItems extended with the Back-Button.
Right now the situations is as follows: When I push the new UIViewController then the existing leftBarButtonItems disappear and only the Back-Button is visible.
Each UIViewController has it's own "navigationItem" property, which acts as the navigation bar representation for that viewcontroller. When you add buttons to the navigationItem of a particular UIViewController they are limited in scope to the viewcontroller to which they were added, and they don't persist into other viewcontrollers.
Basically, you'll have to add the buttons to the navigationItem of each viewcontroller as it loads. You can make this simpler by writing adding a method to do this work to a class other than your UIViewControllers. What happens when you touch each button might be viewcontroller specific though, so you'll have to think through how touch actions will be fed back to the relevant viewcontroller. Perhaps introduce some kind of NavigationBarDelegate protocol or something?
I found what seems like a hacky way to get around this when pushing multiple instances of the same view controller on to a detail view controller which I assume would work similarly. Before pushing the new view controller I used this: (browser is my new view controller)
self.browser.navigationItem setLeftBarButtonItem:self.detailViewController.navigationItem.leftBarButtonItem animated:YES]; // Sets popover view controller button.
[self.detailViewController.navigationController pushViewController:self.browser animated:YES];
This probably isn't a good way to do it but it seems to work in my situation.

NSView added as subview doesn't show

I have a puzzling problem. Working on a cocoa app in mac os x 10.7.
My app main window contains a split view. In a certain use context in one of the subviews of the split view is loaded a custom view with some labels (nstextfield) and a split view (instantiating a view controller that loads a nib and getting view from that controller). Frame of the custom view is set to split view subview bounds and everything works fine.
Problem is that one of the subviews of the second split view should be loaded (same method: view controller-nib-view-frame/bounds) with a custom view containing a table view and a button, but in this case nothing shows. Everything is done the same way but last custom view is not visible. Any idea?
Thanks
(edit)
this is the code I use to instantiate controller for the view to be added, get the view, and add it as subview to a subview of the split view
- (void)loadSubview {
self.subviewToAddController = [[viewController alloc] initWithNibName:nil bundle:nil];
//nib name is coded in the controller class definition
[[self.subviewToAddController view] setFrame:[self.splitViewContainerSubView bounds]];
//container subView is an outlet
[self.splitViewContainerSubView addSubview:[self.subviewToAddController view]];
}
However I don't think the problem is in this code because if I ask the container subview for its own subviews I can see the new subview is present in the list. It just doesn't show. If I add it as a subview of the split view (a test a just made) or as subview of the subview of the most external split view it is correctly showed too (sorry for the confused explanation, I would need a diagram but in this moment I can't make it)
To elaborate more my doubt (I didn't want to misled so I didn't mention before) can't it be a problem of coordinates, so view is correctly loaded and added as subview but is not visible because hidden by something or showed out of visible area?
(update)
Sorry it took so long to post an update.
After more testing I found out the problem is related to autolayout. No idea what the exact problem is and how to solve it. I ended up turning it off for the nibs the were in troubles and use the old way to set interface objects position and size/resize. Not the best way but for now I can go on.
My best guess is that you didn't set the autoresizing masks of the view properly.

IPhone XCode programming: view called from a navigation view doesn't set its IBOutlet attributes

I created a view Called ProgrammaView that appears when a row of a table is clicked.
This view has a UILabel, a UIImageView and a UITextView.
Now.
ProgrammaView's Outlets have to be changed by the parameter passed to a method of the view called iniz.
in this
image there is first the ProgrammaView.h and then the method iniz.
The problem is that the label and other stuff doesn't change!
I checked 3 million times that everything between the xib file and the controller is linked.
The trick to call iniz in the other viewcontrollers works well in other part of the program so i think is not that the problem.
Thank you in advance!
You need to call setNeedsDisplay to indicate that the view should be redrawn.
My understanding is that you start up and show view after that you update the values and expect the view to display new values.
You need to call setNeedsDisplay to indicate that the view should be redrawn. Try to add it at the end of your iniz method.
See apple doc.

Resources