I have a view controller which has a UITableView with some custom cells.
Within the custom cells I have a main UIImageView. I add a tap gesture recogniser to the image view, so that when the image is tapped the handleImageTap method is called.
Question
What I am trying to do is pass the image from the selected UIImageView (from the specific cell) into a new View Controller.
When the handleImageTap is called I run the following:
UIImageView *imageView = (UIImageView *)gestureRecognizer.view;
// send the image instead of self when firing the segue
[self performSegueWithIdentifier:#"remindMeTurnInfo" sender:imageView];
I then have the following in the prepareForSegue method:
if ([segue.identifier isEqualToString:#"remindMeTurnInfo"]) {
UIImageView *imgView = (UIImageView *)sender;
MESPlayedTurnReminderViewController *VC = segue.destinationViewController;
VC.mainImageView.image = imgView.image;
}
The above does not work the image is not passed across. How can I get the image from the selected cells image view to the new controller?
Also
Sometimes when the image view of the cell is selected the didSelectRowAtIndexPath method is called. This is not correct and should not be called when the image view is tapped. This doesn't appear to be all the time, is there anyway to ensure this is not called?
I also need a reference to the cell that the imageview is within for the prepareForSegue method. How do I get the reference for the cell that the imageview is within, when the cell is (should not be) actually selected here.
Your question has 2 problems.
First, you should not use table view cells to store data. Table view cells are view objects. They display data. When the user triggers an action on a cell, you should figure out the indexPath of the cell, use that info to look up the data in your model (the image for the selected row or section/row, in your case) and use that.
Second, you should never try to manipulate another view controller's views. Treat the other VC's views as private. This is a biggie. Reaching into another VC and touching its views violates the encapsulation of the two VCs and means that the VC doing the touching becomes dependent on the appearance of the "touched" VC. Bad. Then you can't change the appearance of the touched VC without breaking other code. It also doesn't work right after creating the new VC, because it's views don't exist yet.
Instead, you should add an "imageToUse" property to the other view controller, and set THAT in the prepareForSegue method. Then the second view controller can take the image and install it in it's image view in it's viewWillAppear method.
I changed the approach.
Putting a UIImage on the destination Controller instead. Then in the viewDidLoad of this controller I pass the image into the UIImageView. I imagine this is because the image view is not created yet.
Related
I've been trying to create table view cells each with a UIImageView serving as a background for them. However, when I tap on each cell the table view will not register the click and will not transition to the view controller I have hooked up, even while I'm using the didSelectRowAtIndexPath function.
I realize it's probably an issue with the ImageView obstructing the table views ability to register the cell tap. The cells will transition however when I drag my finger/mouse on it from left to right, just not on taps. I tried to use a Tap Gesture Recognizer on the Image View however it only worked for the cell at the very top and not all of them. How do I tackle this issue?
Here is an image of the table view cells so you have an idea of what I'm working with: http://imgur.com/a/Ku4uD. Thank you!
If you uncheck User Interaction Enabled on your Image View, the problem should be solved. When running into a problem always check the user interaction of the most child view and work your way up.
One trick I have also learned is to create a subclass of a child and override touchesShouldCancel like so:
override func touchesShouldCancel(in view: UIView) -> Bool {
print("touchesShouldCancel")
//Run extra code that you want when the user selects this view
//then still retrieve the tap by its parent.
return false
}
I am unsure of exactly what your problem is, but I would delete whatever segue that you have, add a new one by dragging from the yellow circle on the left side of the center portion of the top of your tableView ViewController inside the storyboard, to the viewController that you desire it to segue to. Give the segue an appropriate identifier, and then inside your tableView class under tableView didSelectRow add performSegue(withIdentifier: "ChosenIdentifier", sender: indexPath)
Then in prepare forSegue add in:
if let vc = sender.destination as? TheViewControllerYouAreSegueingTo {
if let indexPath = sender as? IndexPath {
vc.variableIdentifyingWhatCellWasClicked = indexPath.row
}
}
with whatever adjustment is needed to meet your specific needs.
I'm trying for this solution from many days, I have a scenario where I want to pass touch even (Swiping for page view controller) of my first custom cell to the parent view which is a page view controller.
Here my first cell in the table view is a transparent cell. It is not visible instead of we can see the background view which is a super class of table view controller and it is a page view controller. So here I want to pass the touch event which should be swiping for page view controller. And all the remaining cells are not transparent. Here I'm sending the image so that you can understand. easily. So help me out in passing the swipe/touch to my page view controller Basic Look with transparent cell on top So in that transparent cell area we can see the super view of table view controller which is a page view controller.
As you can see left side is the basic look, and in that you can see the page view controller, and then the right side image is when we scroll the cells it will look like this.
So now you can understand clearly the height of table view and my requirement too.
So how to pass touch/ swipe event to the page view controller when we select transparent cell(indexpath.row ==0 first cell)
I tried the solution that given but no use..
You can add one more view on top of it (pageview -> cellview -> new view on top with opacity = 0). Next add swipe gesture to new view and finally make a newView.delegate = pageviewController to capture swipe event.
#protocol NewViewControllerDelegate<NSObject>
-(void)gestureDidFire;
#end
#interface NewViewController : UIViewController
// you gesture outlet look like IBAction *swipeGestureReconizer;
#property (nonatomic, assign)id <NewViewControllerDelegate>delegate;
#end
//newViewContrlloer.m
- IBAction swipeGestureReconizer
{
if(self.delegate && [self.delegate responseToSelector:#seletor(gestureDidFire)])
{
[self.delegate gestureDidFire];
}
}
//in your page view interface
#interface yourPageView()<NewViewControllerDelegate>
{
//need instance of newView
newViewController.delegate = self;
}
-(void)gestureDidFire
{
//implement what you want
}
I'm trying to add this custom control below my tableview in a TableViewController:
https://github.com/zogieosagie/RMEIdeasPullToSortControl
In the example the creator gives, the control is implemented using a ViewController and an added tableview, but I want to use it in a TableViewController. I have created and initialized it as shown in the example but I cannot get it to show up behind the table. Any ideas?
Here is a screenshot of the control above my tableview: https://www.dropbox.com/s/ojfpacxelcy9cqm/Photo%20May%2028%2C%208%2057%2035%20PM.png
Here is my code in the viewDidLoad method:
[self.tableView setBackgroundColor:[UIColor clearColor]];
self.rmeideasPullDownControl = [[RMEIdeasPullDownControl alloc] initWithDataSource:self delegate:self clientScrollView:self.tableView];
self.sortTitlesArray = [[NSArray alloc] initWithObjects:#"Listed from A - Z", #"Listed from Z - A", #"Brand value: HIGHEST - LOWEST", #"Brand value: LOWEST - HIGHEST", #"Founded: OLDEST - NEWEST", #"Founded: NEWEST - OLDEST", nil];
CGRect originalFrame = self.rmeideasPullDownControl.frame;
self.rmeideasPullDownControl.frame = CGRectMake(0.0, 45.0, originalFrame.size.width, originalFrame.size.height);
//It is recommended that the control is placed behind the client scrollView. Remember to make its background transparent.
//[self.view insertSubview:self.rmeideasPullDownControl belowSubview:self.tableView];
[self.tableView addSubview:self.rmeideasPullDownControl];
[self.tableView sendSubviewToBack:self.rmeideasPullDownControl];
Table view controllers do not lend themselves to managing anything other than a table view. In a table view controller the content view of the view controller is the table view.
You should not try to add other views as subviews of a table view.
Those 2 things combined mean that you can't do what you are trying to do.
Instead, you should create a regular UIViewController. In your storyboard, add a container view to the view controller's content view. Create a UITableViewController as a separate scene, and then control-drag from the container view onto the table view controller. That will set up an embed segue, so your table view controller becomes a child view of the regular view controller. Now you can do whatever you want to the main view controller's content view, including adding other views behind the table view.
Do you mean that you are using a Table View Controller on the storyboard? Or do you mean that your backing code is a subclass of UITableViewController?
I haven't used this project before but I'm guessing you are using a Table View Controller on the storyboard, in which case there is no backing view for the RMEIdeasPulldownControl to attach to (the top-level view is a UITableViewController). If you look in the example it needs to be attached to a scrollview (like a table view) but it needs to be inserted into a view (like a UIView)
If you meant the second one then I'm not sure, UITableViewControllers are subclassed from UIViewControllers and are really very similar, so I can't imagine any trouble arising from that.
It isn't possible directly, but you can create UIViewControllerClass with relevant storyboard UIViewController
add a MyUIView in hierarchy then UITableView next to MyUIView
attach datasource and delegates for UITableView and use MyUIView as per your requirement.
I'm trying to add a tableview as subview to my tableViewController, but I want to setup the cells in storyboard. It will be a static tableview.
This is the code for calling the tableview on button click.
- (IBAction)botaoAdicionar:(id)sender {
AtividadesPraticadasTableView *tableview = [[AtividadesPraticadasTableView alloc] initWithFrame:CGRectMake(0, 170, 320, 320) style:UITableViewStylePlain];
[self.view addSubview:tableview];
}
In the tableview class I have this:
#implementation AtividadesPraticadasTableView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
Now, I have a viewcontrollerin storyboard with a tableview, which the class of the tableviewI changed to this file AtividadesPraticadasTableView. It has three static custom cells in storyboard, therefore it opens a blank default tableview.
What am I missing?
Static table views are entirely contained within the storyboard, and require information from the storyboard to display their content.
You've defined a static table view controller in the storyboard, populated it and set the tableView's custom class to your custom class, but when you want to add the table view you are just instantiating a table view of that class. That isn't going to get any of the information you've added to the storyboard.
In addition, the static cells information is read and understood by the UITableViewController, not the UITableView, so you are at the wrong level there too.
You need to do the following:
Get a reference to the storyboard, either from your original view controller's storyboard property (if it is on the same storyboard as your static table) or using storyboardWithName:bundle:.
instantiate the table view controller from that storyboard, using instantiateViewControllerWithIdentifier:. This will create a table view controller object containing all your static cells
Add this as a child view controller to your original view controller, using addChildViewController:
Add the table view controller's tableView as a subview
It may be simpler to add a container view in the storyboard to hold this view, and reveal it when the button is pressed, as Mike Slutsky suggested - this will do all of the instantiating and adding and child view controller-ing work for you, but the principle is still the same.
Also, adding a table view as a subview to a table view controller sounds very dodgy - a table view controller already has a table view as its view, and you can't really add subviews to that.
The thing your missing is the association between the programatically instantiated tableview and the UITableView that you put in your storyboard. You cannot just draw UITableViews in your storyboard and start instantiating new UITableViews in the controller's code and expect xcode to know which UITableView you wanted to use from the storyboard. Use an IBOutlet to connect a global variable for the controller to the UITableView in the storyboard, then the controller will know what you're trying to refer to. If you want that UITableView to appear on a button click, simply set the UITableView to hidden by default in the storyboard and then unhide it when the button is pressed.
The thing You are missing called manual. Check this protocol for TableView dataSource https://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewDataSource_Protocol/Reference/Reference.html#//apple_ref/occ/intf/UITableViewDataSource
P.S. Here good tutorial for storyboards http://maniacdev.com/ios-5-sdk-tutorial-and-guide/xcode-4-storyboard
I have an app with two view controllers. ViewControllerA is a blank view with a tap gesture assigned which allows the user to tab on the view and create a UITextView at the point of the tap. The user can create as many UITextViews as they wish and they are added then programmatically to the view (ViewControllerA) as sub views.
There is also a button which allows the user to change the text font and styling. This triggers a Segue to the second view controller ViewControllerB which then allows the user to set Font, Text Size, Color etc. Once completed the user clicks the DONE button on ViewControllerB and another Segue switches back to the initial view (ViewControllerA).
This all works fine. Except when the user switches back to the initial view (ViewControllerA) from ViewControllerB the view is reloaded from the storyboard and the sub views I have added programmatically are gone.
In view (ViewControllerA) ViewDidLoad and ViewWillAppear are firing just fine so the problem seems to be the initial view is released when the first Segue fires and then recreated from the storyboard on the transition back but the subviews are of course not included as they are not in the storyboard since I added them programmatically.
Any suggestions for a best practice on how to solve this so that the subviews are recreated also when the main view (ViewControllerA) reloads?
Many thanks for any suggestions!
From the question it sounds like you had a segue to the text styles view, then another segue "back to the original" - it doesn't work like that, segues always make new instances of the destination VC. You should have had a modal segue to the text styles view, then dismissed the modal view controller - this would return to your original instance.
Just for the record, I solved this as follows in case anyone else needs a solution.
I created a subview in ViewControllerA which is the size of the main view excluding the Toolbar. I call this canvasView. Then I add all of my ImageViews and TextViews to this canvas view.
Then in ViewControllerA viewWillDisappear I archive the canvasView and all of its subviews to a file like this.
NSString *archivePath = [NSTemporaryDirectory() stringByAppendingPathComponent:#"Canvas.archive"];
BOOL result = [NSKeyedArchiver archiveRootObject:_canvasView
toFile:archivePath];
if (!result) {
NSLog(#"Archive failed to archivePath %#",archivePath);
}
Then in ViewControllerA viewWillAppear I check if there is an existing archive and if so reload it which loads the sub views in the correct order. Otherwise I create an empty canvasView like this.
// If the collageView already exists then restore it from the achive, otherwise initialize a new one.
NSString *archivePath = [NSTemporaryDirectory() stringByAppendingPathComponent:#"Canvas.archive"];
_canvasView = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];
if (_canvasView) {
// Restore existing canvasView
[_backgroundView addSubview:_canvasView];
} else {
// Initialize a new canvasView
_canvasView = [[UIScrollView alloc] initWithFrame:CGRectMake(_backgroundView.frame.origin.x,
_backgroundView.frame.origin.y,
_backgroundView.frame.size.width,
_backgroundView.frame.size.height)];
[_backgroundView addSubview:_canvasView];
}