3D Touch peek and pop trouble - ios

I'm trying to implement peek and pop feature in my application.but since I can't test it yet, I wanted to know if I was doing it correctly, I feel something is wrong?
- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
{
NSLog(#"TEST");
NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:location];
if (indexPath) {
UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];
NSDictionary *dict = [self.array objectAtIndex:indexPath.row];
cell.textLabel.text = [dict objectForKey:#"name"];
DetailViewController *previewController = [[DetailViewController alloc] init];
// previewController.content = content;
previewingContext.sourceRect = cell.frame;
return previewController;
}
return nil;
}

I'm currently implementing this in our app and that looks mostly right. A problem I encountered is that the coordinates given to you in location are for the UIViewController's view, not the UITableView. Depending on your setup, they may be the same, but in my case, I needed to convert the location to the UITableView's coordinates.
CGPoint convertedLocation = [self.view convertPoint:location toView:self.tableView];
Of course, your mileage may vary.

You should not need to correct the location if you registered the previewDelegate with the correct sourceView. So instead of
[self registerForPreviewingWithDelegate:self sourceView:self.view];
you should register it this way:
[self registerForPreviewingWithDelegate:self sourceView:self.tableView];
Then location you get from the delegate call takes scrolling / contentOffset into account.

The only problem with your code is the way to get convertedLocation is not right.
Below code will get correct location even after you scroll the table view.
CGPoint convertedLocation = [self.tableView convertPoint:location fromView:self.view];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:convertedLocation];

Related

How delete row form UICollectionView?

I have UICollectionView that has two UICollectionResuabeView(Custom View) and one UICollectionViewCell. The form a single entity in UICollectionView. I put Delete button on one of UICollectionResuabeView and by pressing it want to delete the row (if i call it right).
This is the screenshot form Storyboard:
I tried getting section of it my many means, but non works. Guess I just dont have enough knowledge of how UICollectionView works. Here is some code I tried:
I know its I mess, but at least I was trying ))
I ve tried this toget indexPath, but none works.
-(IBAction)deletePressed:(UIButton* )sender{
RecipeCollectionHeaderView *contentView = (RecipeCollectionHeaderView *)[sender superview];
RecipeViewCell *cell = (RecipeViewCell *)[contentView superview];
cell = (RecipeViewCell *)[contentView superview];
// determine indexpath for a specific cell in a uicollectionview
NSIndexPath *editPath = [self.collectionView indexPathForCell:cell];
NSInteger rowIndex = editPath.row;
NSInteger secIndex = editPath.section;
// NSIndexPath *indexPath = nil;
// indexPath = [self.collectionView indexPathForItemAtPoint:[self.collectionView convertPoint:sender.center fromView:sender.superview]];
// NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
// NSSet *touches = [event allTouches];
//
// UITouch *touch = [touches anyObject];
//
// CGPoint currentTouchPosition = [touch locationInView:self.collectionView];
//
// NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint: currentTouchPosition];
NSLog(#"IndexPath CollectionView %ld", (long)rowIndex);
}
I also tried make it work like in this post, but it does not give a result:how to access from UICollectionViewCell the indexPath of the Cell in UICollectionView
Thank you all!
EDIT!
I found this works well:
-(IBAction)deletePressed:(UIButton* )sender{
[self.ordersArray removeObjectAtIndex:0];
[self.collectionView reloadData];
}
The only thing I need now is to get section of UICollectionView by UIBotton that been pressed, to delete section I want. How to do it?)
You also need to remove item from the array and UICollectionView as well.
Try to use this code.
-(void) deleteRow:(NSInteger)index {
[self.contentView performBatchUpdates:^{
[arrayForRows removeObjectAtIndex:i];
NSIndexPath *indexPath =[NSIndexPath indexPathForRow:i inSection:0];
[self.contentView deleteItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
} completion:^(BOOL finished) {
}];
}
For cell selection use this code snippet:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
//Item position that you would like to delete.
indexPath.row;
}

How can I make a method act as a tap on a MKAnnotation?

I have two views. One is a map view and another is a table view of all of the titles of the MKAnnotations. Right now I am able to call a method on the table view from the tap of the MKAnnotation. But what I want to also do is call a method from the tap of an object on the table view that acts as a tap on the MKAnnotation. Help please?
Here is the table view code that the MKAnnotation tap uses to select an object on the table view.
- (void)highlightCellForPost:(PAWPost *)post {
// Find the cell matching this object.
NSUInteger index = 0;
for (PFObject *object in [self objects]) {
PAWPost *postFromObject = [[PAWPost alloc] initWithPFObject:object];
if ([post isEqual:postFromObject]) {
// We found the object, scroll to the cell position where this object is.
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:PAWWallPostsTableViewMainSection];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
return;
}
index++;
}
Here's is the code for the MKAnnotation that calls the above method.
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
id<MKAnnotation> annotation = [view annotation];
if ([annotation isKindOfClass:[PAWPost class]]) {
PAWPost *post = [view annotation];
[self.wallPostsTableViewController highlightCellForPost:post];
} else if ([annotation isKindOfClass:[MKUserLocation class]]) {
// Center the map on the user's current location:
CLLocationAccuracy filterDistance = [[NSUserDefaults standardUserDefaults] doubleForKey:PAWUserDefaultsFilterDistanceKey];
MKCoordinateRegion newRegion = MKCoordinateRegionMakeWithDistance(self.currentLocation.coordinate,
filterDistance * 2.0f,
filterDistance * 2.0f);
[self.mapView setRegion:newRegion animated:YES];
self.mapPannedSinceLocationUpdate = NO;
}
}
So I essentially want to do what I've done above but in reverse order.
You can simply call selectAnnotation on your map view in didSelectRowAtIndexPath.
Firstly, I would create a new NSArray property postObjects which contains all of the PFObjects in self.objects already converted to PAWPost objects rather than having to continually iterate the objects array and create new PAWPost objects. Once you do this, your first method becomes the much simpler -
- (void)highlightCellForPost:(PAWPost *)post {
// Find the cell matching this object.
NSUInteger index = [self.posts indexOfObject:post];
if (index != NSNotFound) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:PAWWallPostsTableViewMainSection];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}
Then, your tableview method is
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == PAWWallPostsTableViewMainSection) {
PAWPost *post=self.posts[indexPath.row];
[self.mapView setCenterCoordinate:post.coordinate animated:YES];
[self.mapView selectAnnotation:post animated:YES];
}
}

UITableViewCell & getting bounds/frame

I have UITableView cell, in a UITableView. When i am trying to add new value from search bar list selected that time that value i am adding into table and same time displying the popover on that newly added cell but some time its working perfect but no of times it display anywhere i am using cell.frame my code is bellow for the same i am attach the expected result screen short also please any one know then help me
- (void)loadPopOver:(id)idDataObj {
NSDictionary *dictDataObj = (NSDictionary*)idDataObj;
//add the popOverControl
OrdersDetailPopViewController *orderDetailPopVC = [[OrdersDetailPopViewController alloc] init];
orderDetailPopVC.idParentDelegate = self;
CGSize sizeObj = [orderDetailPopVC initView:5 totalTextArea:0 dataForTableViews:[dictDataObj valueForKey:TAG_DATASOURCE] titles:[dictDataObj valueForKey:TAG_TITLES]];
if (sizeObj.height == 0 && sizeObj.width == 0) {
NSLog(#"API Error : Incomplete data sent.");
return;
}
//Point from where to show the popOverControl
CGRect cgRect;
if (indexPathLastSelected.section == -1 ) {
if([_isFromSearchBar isEqualToString:#"FROM_SEARCH_BAR"])
{
UITableViewCell *cell = [tableViewLeft cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];
cgRect = cell.frame;
//cgRect.origin.y = 190;
cgRect.origin.y = 25;
//cgRect.origin.x =270;
}
else if([_isFromRightTable isEqualToString:#"FROM_RIGHT_TABLE"])
{
UITableViewCell *cell = [tableViewLeft cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];
cgRect = cell.frame;
}
}
else {
UITableViewCell *cell = [tableViewLeft cellForRowAtIndexPath:indexPathLastSelected];
cgRect = cell.frame;
}
popOverFormInput = [[UIPopoverController alloc] initWithContentViewController:orderDetailPopVC];
popOverFormInput.contentViewController = orderDetailPopVC;
[popOverFormInput setPopoverContentSize:sizeObj];
popOverFormInput.delegate = self;
if (self.view.window != nil)
[popOverFormInput presentPopoverFromRect:cgRect inView:tableViewLeft permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
You have a lot of funky code in your project which I highly suggest you revise. For now though, I suggest going for simplicity and using a method like this
//Get the cell's frame that you're interested in
UITableViewCell *cell = [tableViewLeft cellForRowAtIndexPath:selectedindexPath]
//and then use that cell's frame to position your popover over it.
[popOverFormInput presentPopoverFromRect:[cell frame] inView:cell.contentView
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
As you are trying to popup using the CGRect, It might not the superView's frame Or else you are somewhere misusing of the frame Value.
Better get(Note) the NSIndePath of the tableView. Later can use it to popup from it >
For Ex:
- (void)loadPopOver:(id)idDataObj {
NSIndexPath *selectedindexPath;
.
.
.
if([_isFromSearchBar isEqualToString:#"FROM_SEARCH_BAR"])
selectedindexPath = // [tableViewLeft cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];
.
.
.
// Try this to pop your View
[self.popOver presentPopoverFromRect:[tableViewLeft rectForRowAtIndexPath:selectedindexPath] inView:[self view] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
At the time of calling method i just put the delay
and i fixed the issue
[self performSelector:#selector(showPopOver) withObject:nil afterDelay:0.20];

How to find cell indexPath that was selected when calling [tableView setEditing:NO]?

On a tableView that allows selection in edit mode, how do i find which was the selected cell when i call [tableView setEditing:NO animated:YES] and exit edit mode ?
There is no call to didDeselectRowAtIndexPath:, are there any other methods i overlooked ?
Edit for solution:
The cell never gets deselected, therefore indexPathForSelectedRow still returns the correct value. Fair enough.
you can use GestureRecognizer for this .
try this :
UISwipeGestureRecognizer *gestureObj = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(Method:)];
[gestureObj setDirection:UISwipeGestureRecognizerDirectionRight];
[self.tableview addGestureRecognizer:gestureObj];
-(void)Method:(UISwipeGestureRecognizer *)gestureRecognizer {
CGPoint p = [gestureRecognizer locationInView:self.tableview];
NSIndexPath *indexPath = [self.tableview indexPathForRowAtPoint:p];
if (indexPath == nil)
{
[self setEditing:YES animated:YES];
NSLog(#"slide on table view but not on a row");
}
else
{
[self setEditing:YES animated:YES];
NSLog(#"slide on table view at row %d", indexPath.row);
}
UITableViewCell *cell = [self.MYArray objectAtIndex:indexPath.row];
}
The answer is that the row never gets deselected.
indexPathForSelectedRow is still valid before actually exiting the edit mode.

iOS - Loop through Cells and retrieve data

Sorry I'm pretty new to iOS dev.
I have a UITableView setup from cells being pulled from a single XiB nib. I've created a on/off switch in the nib, and I am trying to save the state of the switch upon viewWillDisappear for the number of cells that I have. (6 cells to be exact).
How can I loop through all the cells and save this information?
I tried this in my UIViewController to get the info for one cell:
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
UITableView *tv = (UITableView *)self.view;
UITableViewCell *tvc = [tv cellForRowAtIndexPath:0];
}
it gives me the error "Program received signal: "EXC_BAD_INSTRUCTION".
How can I accomplish this?
You have to pass a valid NSIndexPath to cellForRowAtIndexPath:. You used 0, which means no indexPath.
You should use something like this:
UITableViewCell *tvc = [tv cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
BUT. Don't do this. Don't save state in the UITableViewCell.
Update your dataSource when a switch changed its state.
If you have implemented the UITableViewDataSource methods the right why your tableView reuses cells. That means the state of your cells will vanish when the cells are reused.
Your approach might work for 6 cells. But it will fail for 9 cells.
It will probably even fail if you scroll the first cell off screen.
I wrote a quick demo (if you don't use ARC add release where they are necessary) to show you how you should do it instead:
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataSource = [NSMutableArray arrayWithCapacity:6];
for (NSInteger i = 0; i < 6; i++) {
[self.dataSource addObject:[NSNumber numberWithBool:YES]];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
UISwitch *aSwitch = [[UISwitch alloc] init];
[aSwitch addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = aSwitch;
}
UISwitch *aSwitch = (UISwitch *)cell.accessoryView;
aSwitch.on = [[self.dataSource objectAtIndex:indexPath.row] boolValue];
/* configure cell */
return cell;
}
- (IBAction)switchChanged:(UISwitch *)sender
{
// UITableViewCell *cell = (UITableViewCell *)[sender superview];
// NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
CGPoint senderOriginInTableView = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:senderOriginInTableView];
[self.dataSource replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:sender.on]];
}
as you see it's not very complicated to not store state in the cells :-)
Moving [super viewDidDisappear:animated]; to the end of your method may be the most expedient way to address the problem. If that does not work, move the logic into viewWillDisappear:animated:.
A better way to deal with this would be to avoid reading the current state from the view at all. Rather, the view should pass the state to the model on each update. This way you would be able to harvest the current state from your model, entirely independently from the state of your view.

Resources