How can I give a particular behavior to a UITableViewRowAction? - ios

I have a standard UITableView of items. Tapping a row will bring a DetailsViewController with details about the selected item and the possibility to use it through a UIButton.
I have implemented the (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath method made available from iOS 8 and I defined two actions:
The standard deletion of the item (pretty simple stuff).
The possibility to use the item like above. I basically want this action behavior to be the same of the IBAction related to the button in the DetailsViewController.
I thought about presenting this view controller automatically and making an automatic tapping of the button without using interaction, but this could be a bit confusing for the user according to me. So I would prefer to call the IBAction method directly from the table view controller. Is it possible and how can I achieve this result?
I can provide the source code if this could help you to help me.

What you need to do is take the "use this thing" action out of your ViewController, and put it in the Model object for "thing."
Then, when you want to use your "thing" from the tableView or the DetailsViewController, you can call this function directly on the associated model object, and allow your two (possibly more) different user interfaces to perform the "use that thing" functionality appropriately based on their own UI needs.

Related

Storyboards: How do I use the same view controller in several places?

For years, I've hand-coded my view code for iPhone apps, but now I'm giving storyboards another look.
One common pattern in my code is to use the same view controller in two places, but with slight UI variations. For example, when browsing a list of brands (BrandListController), I'd like to show a table view of all brands in the system; tapping a brand shows you its products. But when filtering items by brand, I'd like to show a table view of brands (with the same content and same cell appearance), but I'd like tapping a row to take you back to the filter screen instead of showing you that brand's items. I'd also like a "Search" bar button item in the top right.
It's easy to make these things happen in code, by just adding a boolean member variable so the controller can be configured before it's presented.
But how would I do this with storyboards? I could have multiple controllers segue to the same instance of BrandListController, but again, I would want the controller to have different behavior and include/exclude UI elements based on how it's used. It seems like a bad idea to create two separate instances of BrandListController in the storyboard, because then I would have to duplicate all the outlet connections and I would have to keep changes in sync. But what are my other options?
The thing to realise with Storyboards is that you don't necessarily have to only use a single storyboard.
You can use multiple storyboards or use them in conjunction with nibs etc...
However, in this case what you could do is still use you boolean property on the controller.
Then in the prepareForSegue method of the other controllers you can set this boolean property to change the behaviour. You might even have a couple of nibs that defines a small section of UI to place into the view depending on the property.
I've done stuff like this to pass blocks into view controller too.
For example...
I had a "User Search" controller that had a default behaviour of if you tap a user it will push to that user's profile page.
But I could pass in a code block that would, for instance, dismiss the search controller and I use the selected user to create a new message to them (or whatever). Or something else entirely depending on the code block I passed in.
EDIT
LOL, just re-read your question. What I did with the blocks would work for you too. I created a block property called userTappedBlock or something. If that exists then I run it when the cell is tapped. If not I do the default behaviour.

Can I use multiple lines of text in a UIAlertView's button?

At one point in my app, the user has to choose from a list of reasons (it's a medical app that lets one user check if another user gives a patient the right medicine and dose via one or more photos). If the photo is rejected, the user has to choose a reason.
One of our customers provided a list of possible reasons, and they can't be changed. The problem is that one of these reasons is a very long sentence and when I add it to the alertview, the text gets really small instead of just wrapping to a new line. I tried putting a \n in my string, but then the second line isn't shown (so it does work, but I only see the first line in the view).
Can I add multiline functionality to the alertview's buttons? I know a UIButton does not support multiline. I also know UIAlertView's addSubView: does not work anymore since iOS7. I'd rather not use any third party libraries, but if I really have to I'm open to suggestions. Increasing the size of the alertview would be an option as well.
For your requirement it will be better if you use UIActionSheet or Customized PopUp View where you can use multiline.
UIAlertView and UIActionSheet are really meant to provide concise feedback and make concise decisions respectively. It sounds like you need a richer interface for the user to make a selection. I would suggest that you create a custom UITableViewController class with a dynamic cell that presents a set of reasons and allows selection of a reason. You could dynamically create a non-editable UITextView to display a multi-line reason and perhaps a button next to the reason to select it. Each row of the UITableView would contain a UIButton to select and a UITextView to show the reason. In your UIableViewController class you would assemble all the reasons relative to the context and then present them in the table view for selection - one row for each possible response. Alternatively, you can forgo the button and just present the reasons via a UITextView. If the user clicks on the row (table cell) you can indicate the response with a check mark
cell.accessoryType = UITableViewCellAccessoryCheckmark;
and capture the selection for processing in
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Reason *selectedReason = self.myReasonsArray[indexPath.row];
}
enter link description here
Also, UIAlertViews do not support subclassing and have very limited configuration capabilities. I'm suggesting you accomplish your objective by creating a "custom" modal view via a UITableViewController that can be used to essentially popup a rich interface that allows you to do all sorts of things like have multi-line text, images, whatever. You can reuse this view everywhere via delegation.

Segmented control to toggle through multiple tableviews

What I’m basically trying to is to implement the control segment/tableview as in Mailbox (see it around 2:00: http://www.youtube.com/watch?v=FG-h8pDXfoE&feature=youtu.be&t=2m)
I am using Core Data in one UITableViewController hooked up to a UITableView.
When user toggles the UISegmentedControl, the TableView is reloaded with a different set of NSPredicate, and UITableViewRowAnimationRight/Left, kind of makes it appear that that a different table view slides in and replaces the old one.
As the number of cells increase, the performance of this design decrease dramatically, and it could also look much better.
I can see a few different ways of going about it, but I figured I'd ask you guys for some pointers to head me in the right direction:
What is the best way to have a segmented control to toggle through multiple tableviews? Should these tableviews be connected to the same data source/delegate?
Take a look at this pod: https://github.com/xmartlabs/XLMailBoxContainer. It makes the UI animation among the view controllers. These view controller can extend UITableViewController or any other view controller.
UITableViewCell swipe animation can be accomplished using https://github.com/alikaragoz/MCSwipeTableViewCell.
I hope this could help you!
It really depends how different each of these table views is. If they are quite similar, it's probably easiest to just share the delegate and data source and have some conditional code.
In fact you can just have a single table view, but have different cells / configuration depending on your current context.
Could be as simple as having adding some conditions to
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
Another approach would be to use view controller containment. You would create a UITableViewController for each and then have parent view controller with segmented control which swaps child view controller accordingly.
As for the animation and performance, I can't really see any problem. You can get the animations without much effort if you use NSFetchedResultsController, see an example here: https://developer.apple.com/library/ios/documentation/CoreData/Reference/NSFetchedResultsControllerDelegate_Protocol/Reference/Reference.html.
See SBSegmentedViewController. I wrote it for exactly what you're trying to do.

Embedding UIViewController view inside another UIViewController

In my app, I have a login-register-forgotpasword wireframe. Each step of the process is implemented in a separate UIViewController, all of them inside the same Storyboard, and transitions between each controller are animated. So far so good.
Now we've changed the design, so all views have the same background elements and a header (not exactly a UINavigationBar), and I don't like the feel of the animation to a view that always looks to be actually the same, but just showing a different form. So I'm considering different approaches to, instead of pushing whole controllers, just showing/hiding its views, but staying in the same controller.-
1) My first try was instantiating the controller which view I want to show, and add it to the current view. Something like.-
- (IBAction)btnRegisterPressed:(id)sender {
_viewHome.hidden = YES;
RegisterController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"registerNewUser"];
[self.view addSubview:controller.view];
}
This one would be perfect, as I'm using static UITableViews for my forms, so as far as I know I'd need a UITableViewController for each one. But it seems IBOutlets and IBActions got broken. Is this approach possible in some way? If so, it's considered a bad practice?
2) My second option is just creating all the views inside one controller, and properly showing/hiding them. This would one be hard to maintain, and chances are I'd have to forget about static UITableViews.
Could anyone give me some advice of which option would be better, or point me to any other possible approach I'm missing?
Your option #1 is not appropriate as written but close to an approach you should probably consider. You can add nest the views of different UIViewControllers however when you do so you should use the methods described in Managing Child View Controllers in a Custom Container so that the parent controller correctly manages its child controllers.
You can use as many tableviews as you want for the same controller. The delegate methods contains the object that fired the method itself.
Following this approach (which i wouldn't recommend) you can probably tag your tableviews and then do:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
if (tableView.tag == 1) {
doStuff;
} else if (tableView.tag == 2) {
doOtherStuff;
}
}
Well, personally, I feel we should keep things simple and straight forward for end user to quickly gel up with your app. Animations plays an important role in this. Tapping on cell of a tableview pushes another table view and there are different UI widgets like chevron that indicates the transition and user is not surprised.
Showing everything on single screen and hiding/unhiding them based on user's action is fine as long as you have proper animation. For instance, you might have seen TableView sections collapsing/expanding on tap.
You need to make a trade off and see what best suits based on your application. Whatever you decide my suggestion would be to add nice animations instead of simple hide/unhide.

ios/iphone sdk form management best practices

I'm working on an iPhone app that will have involve a lot of forms. Currently I have a ViewController class for each settings page which has an UITableView loaded with possible settings. When someone clicks on a setting they are taken taken to a new view to enter the form value, or allowed to enter things in place.
What's the best way to keep things DRY? What pieces of this implementation could be implemented once and re-used?
When someone clicks on a settings option which goes to a new view how can I create this view and add a text field according to the data type (uitextfield or picker or something else) in code?
You can programmatically:
create view hierarchy
UIButton
UILabel
You get the idea.
However, I would recommend getting your logic working for a few of the cases, and then it should become obvious what parts are redundant as you find yourself typing in the same thing over and over. At that point, refactor to get the redundant code into a re-usable form.
HTH.
If you have a tableView, the flow is to create the viewController of the selected settings in the didSelectCell method of your tableView delegate and to push it through the current viewController's navigation controller.
here's a sample:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.navigationController pushViewController:[self settingsViewControllerAtIndexPath:indexPath] animated:YES];
}
so you'll have to implement the method:
- (UIViewController*)settingsViewControllerAtIndexPath:(NSIndexPath *)indexPath;
wich will return the viewController managing the settings associated with the selected row of your root tableView.
If your forms are pretty statics, you should consider using a xib in order to minimize the amount of code needed. it isn't a perfect answer to your "how to keep DRY" but it's neat enough ;)
Good luck.

Resources