IBOutletCollections alternatives in OSX (2016 Redux) for custom radio buttons - macos

I'm trying to implement custom buttons as a radio button group. As I've found no way to customize radio button appearance (on/off/hover for each state), I've implemented them as custom image buttons (NSButton subclass). That part works fine. The issue is handling the states of each group of buttons and the corresponding variables determined by the groups (1 per group). IBCollections looks like a great fit for this problem. But I'm writing a Mac app.
The few questions I can find on here on IBOutletCollections in OS X* are a couple of years old. I can't even comment on them to ask since I lack the reputation points, thus the new question.
I did upvote the answers as they helped immensely as the blog posts on IBCollections I read didn't bother to specify them as iOS/UIKit only nor did XCode display any errors (SO HELPFUL! /sarcasm).
Has anyway come up with an alternative way to accomplish this? Separate outlets for each is madness for a group of buttons like these (or worse multiple groups). Can I implement them as an array for IB defined buttons with IBOutlets and IBActions?
*soon to revert to Mac OS (though it will capitalization challenged :)

I won't claim it's an elegant solution, but I managed to solve my problem by grouping the custom buttons with NSArray arrayWithObjects: for each button group.
I added two methods to emulate radio button behavior (in this case for custom color buttons):
-(void)setButtonSelected:(NSArray*) theButtons toColor:(NSString*)color {
[self clearAllButtons:theButtons];
for (ColorButton *button in theButtons) {
if ([button.color isEqualToString:color]) {
button.state = NSOnState;
}
}
}
-(void)clearAllButtons:(NSArray*) theButtons {
for (ColorButton *button in theButtons) {
button.state = NSOffState;
}
}
As my specific problem involved more than one group of buttons that required unique selections, I then added arrays for the each of the aligned options in the groups (columns basically).
- (void)clearColorConflicts:(NSArray*)theButtons forRow:(NSString*)row {
for (ColorButton *button in theButtons) {
if (![button.row isEqualToString:row]) {
if (button.state == NSOnState) {
button.state = NSOffState;
}
}
}
}
Again, it may not be an elegant solution but it solved my problem without IBOutletCollection.
I did look into NSMatrix but I wasn't able to use custom image button behavior (on, off, hover_on, hover_off) when I grouped the custom buttons as a matrix.
The column groups could be handled by the two original methods but I have additional steps for variable/defaults updating when rows/category selections are cleared by selection in another row. In hindsight I could have checked the state of each group after selection instead.
My problem may have been unique, but I'm posting this in case it helps someone else.
I'm not marking as solved as I hope someone has a better solution than mine.

Related

Why Is My Set Up Cutting Off My Constraints To Margins?

I'm working from a storyboard connected to a UIViewController as such:
UPDATE:
The Problem Seems to be that my constraints do not pin to margins. Here are my constraints pinning to the bottom.
Here is how that translates to different devices.
I have messed with the various size settings shown in the second to last picture. I will try a more systematic approach to changing these if someone isn’t able to very easily detect why this is occurring. It seems unrelated to the Page Control and more related to page sizing
Project Github HERE
Note again, this is the exact same problem I get even when creating the view controller in the method used at:
HERE
I chose the code used as opposed to the code at the link only because I had already coded this and they were identical in issue, I have become aware sense then that this is a more complicated way to accomplish this though.
The issue is recreated perfectly with a simple constraint to the bottom.
There are many issues with your code / storyboard, but I think the problem you're complaining about is here:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
for view in self.view.subviews {
if view is UIScrollView {
view.frame = UIScreen.main.bounds // *
} else if view is UIPageControl {
view.backgroundColor = UIColor.clear
}
}
}
Remove the line that I've commented.
(If you also change the color in the last line to .red, just as an experiment, you will be able to see the page control, and you'll see that the text view is behaving consistently on different sizes of device.)

What is the best way to develop applications using the auto layout in Xcode?

So I guess this is going to be closed for being too subjective and too opinion based but if anyone can help me I would appreciate it.
I got a question. If I have a few controllers that all have almost the same thing For example they have the same background, have a menu going around the edge but the actual content is different. I had a couple of ideas. 1) Just have one view controller and just kill the objects for that current view if the user chooses a different option on the menu and spawn the new objects for that menu. My issue with this way was that I could't find a way to use the auto layout with this.
Second way would to be have a function in a .swift file that I can call and it creates an image view and sets up the menu an everything like that. I have the opposite issue here though, now the auto layout won't work.
App devs must have a way of doing this, I'm just probably thinking of this completely the wrong way.
Is there a better way to be doing this - I am sure there is? I would appreciate it if someone could point me in the correct direction.
Thanks
EDIT:
I should make it clear that the language I am using is swift.
You can create custom container view controller and swap the view controllers for the part that change according to the user selection.
--Adding Example--
e.g iPad's Settings app. The left side is a table view and right side is detail view which changes on user selection. So Tableview can be wrapped in a view controller let's say ListViewController. This will not change. The right side will be DetailViewController which would be swapped according to user selection. Your ContainerViewController will have 2 view controllers at all times.
Here is how to add view controllers as child and set their views in objective-c.
- (void) setupContentViewControllerWith: (DetailViewController*) detailViewController andListViewController:(ListViewController*)listViewController {
[self addChildViewController:listViewController];
[self addChildViewController:detailViewController];
listViewController.view.frame = CGRectMake(kListView_X, kListView_Y, kListView_Width, kListView_Height);
detailViewController.view.frame = CGRectMake(kListView_Width, kDetailView_Y, self.view.bounds.size.width, self.view.bounds.size.height-kDetailView_Y);
[self.scrollContainer addSubview:listViewController.view];
[self.scrollContainer addSubview:detailViewController.view];
[self.scrollContainer setContentSize:CGSizeMake(kListView_Width+self.view.bounds.size.width, self.view.bounds.size.height)];
}
When user selects new item from the list, you can swap DetailViewControllers as below
- (void) replaceEpisodeControllerWith:(DetailViewController *)detailViewController {
detailViewController.view.frame = CGRectMake(kListView_Width, kDetailView_Y, self.view.bounds.size.width, self.view.bounds.size.height-kDetailView_Y);
[UIView transitionFromView:currentDetailViewController.view
toView:detailViewController.view
duration:0.0
options:UIViewAnimationOptionTransitionNone
completion:^(BOOL finished)
{
[currentDetailViewController.view removeFromSuperview];
[currentDetailViewController removeFromParentViewController];
[currentDetailViewController release];
currentDetailViewController = detailViewController;
}];
}
I don't have swift version of this.

Single cell selection NSTableView

There are a few google results for this question but they are ancient and didn't really help. So I'm asking again for modern uses, how can I set up selection for a single row and column. Like the Numbers app. So the row/column its self is not highlighted but the focus ring is drawn for the row, column that was selected.
I'm open to Cell based or View based implementation. I have tried doing things inside the
- (void)tableViewSelectionDidChange:(NSNotification *)notification
but haven't been able to get things working or looking nice.
Has anyone done this, is there a better view architecture for this?

How do I customize a UITableViewCell to display information differently (for dummies, drawing included)?

Alright, I might make this confusing, but hopefully not. So I have a UITableView that I want to section in 3: Details (A), Additional Details (B), and Assignment (C).
In the Details section, I want to just display information in the same way that the Contacts app does, but I don't know how to configure the UITableViewCell to display that way.
In the Additional Details section, I want to display a normal section, so I actually got that covered.
In the Assignment section, I want to have a combination where two cells are normal and will link to other controllers and one cell is just a plain button. Is there something special I need to do for the button cell?
Right now I have a mix of buttons, table cells, and labels, so it looks kinda bad, and thus I want to clean it up and make the interface consistent.
Here's a drawing of what I want to do:
And on a side note, after I click on a cell and it slides to the next controller and then I go back, the cell is still selected. How can I get it to un-select itself after the action it's linked to is performed?
Thanks in advance for help!
All you need is a UITableView with Grouped style, then in tableView:cellForRowAtIndexPath: method you should check the section of the cell you are returning (ie. [indexPath section]) and return a cell based on that since all the cells within the same section should be of basically the same type and style. Not sure about the button, though really you should just have custom behavior for those cells in the tableView:didSelectRowAtIndexPath: method. Its all really about properly implementing the right delegates.
In cellForRowAtIndexPath should be something like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
...
...
if(indexPath.section == kAssignmentSection){
if(indexPath.row == kAssignRow || indexPath.row == kTransferRow){
cell.accesoryType = UITableViewCellAccessoryDisclosureIndicator;//Or Button
}
}
}
Now in you should check for
-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
if(indexPath.section == kAssignmentSection){
if(indexPath.row == kAssignRow){
//Do your thing for AssingRow or any other index you know that needs to be processed
}
}
}
I actually figured this out a couple of hours after I posted the question by digging into the documentation, and I ended up continuing work on my app and kind of disregarded this question. Anyway, it's actually quite easy to change how the cells look. It's all in the cell style.
The cell style determines how the cell looks; Default looks like B in my drawing, Value2 looks like A in my drawing.
And the arrow on right side is the accessory type, or in this case it's the DisclosureIndicator.
I guess this is a perfect example of read the documentation first before asking. So here's the docs I was reading:
UITableViewCell
UITableViewCellStyle
UITableViewCellAccessoryType

How do I implement a customized list in Cocoa?

I want to build a Cocoa App with a list of entries very similar to the ToDo list of Things.app (see the screencast). The question is whether I should use
a TableView,
a CollectionView or
a WebView.
I think it could work with all of them, but which one suits the following requirements best?
have a list of entries -> 1 column & many rows
reordering with drag & drop
select single entries & use keys for actions like delete
open up an entry: the row should expand to show more input fields
customized look: rounded corners, shadow, background gradient
So far my research says that the TableView has most of the functionality, but is harder to customize in its appearance, the CollectionView doesn't have drag & drop (right?) but is easy to design and the WebView would take much effort to not hurt the user experience and I can't bind my model directly to input fields.
What pros and cons am I missing and what would you recommend to use?
A WebView doesn't make sense. You might as well create a web application if you use a WebView. An NSCollectionView is more for grid like data, like TV listings per hour.
NSTableView is the only one that makes sense in this case. I've implemented all 5 bullet points with with an NSTableView without issue. You need to extend NSTableView and do some custom drawing for the customized look. That's the hardest part.
open up an entry: the row should expand to show more input fields
You need an outline view. A table view is for flat lists.
Note that NSOutlineView is a subclass of NSTableView, so all the table-view features work on an outline view as well.
There are people who've done this already. One that I've used successfully is by Matteo Bertozzi and is available here: http://th30z.netsons.org/2009/03/cocoa-sidebar-with-badges-take-2/ It might take a bit of massaging to get it to work properly (especially if you need complex drag-and-drop behavior), but for basic functionality, such as getting the section titles and items in the list, it works excellently.
Edit: This has come up before and is a common question on the cocoa-dev email list. Here are some other options.
Just took a look at Things.app itself using "F-script anywhere".
They've used a subclass of NSTableView called "DetailTableView" which presents the condensed todo items. Collapsed todo items are implemented using a custom cell called "ToDoCell", but the expanded look you get when editing is interesting. In that case they've got a custom view called "ToDoEditView" which is inserted as a subview of the DetailTableView when required. I suspect this editing view is temporarily added as a subview in the correct location and the corresponding row of the tableview gets resized temporarily while it is present.
All pretty speculative .. I'd love to know the details of how this was done. It's an awesome UI.
I'm approaching the very same problem in my app (with one big list similar to the Things todo list) and I think a table view would make a lot of sense here.
The trick is having your cells ("rows") expand when double-clicked. That's about all the progress I've made so far.

Resources