简体   繁体   中英

Pushing to another ViewController from UIScrollview UIView SubView

I've a scrollview that display information in a Carousel manner, what I want to do now is add click event on each and every View in the carousel, I was able to do that by adding UITapGestureRecongnizer* whenever it pushes, it Logs an error *nested push animation can result in corrupted navigation bar out and also it displays the wrong information Below is my code for loading the Carousel View and adding Click event, and also the data on the Carousel are gotten from a jSON and stored with NSObject in a **NSMutableArray*...

 -(void)updateUI:(NSMutableArray *)array {

CGFloat contentOffset = 0.0f;

for (NSString *dis in carouselArray) {
    CGRect frame = CGRectMake(contentOffset, 0.0f, responseScroll.frame.size.width, responseScroll.frame.size.height);

    UIView *views = [[UIView alloc] initWithFrame:frame];
    views.backgroundColor = [UIColor clearColor];
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 130)];
    imageView.contentMode = UIViewContentModeScaleToFill;

    //imageView.image = [UIImage imageNamed:@"banner.png"];
    UITapGestureRecognizer *imageMove = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(moreViewMove)];
    imageMove.cancelsTouchesInView = NO;

    NSString *urls = [dis valueForKey:@"imageURL"];
    if ([urls  isEqual: @""]) {
        imageView.image = [UIImage imageNamed:@"banner.png"];
    } else {
        [imageView setImageWithURL:[NSURL URLWithString:urls]];
    }

    UILabel *name = [[UILabel alloc] initWithFrame:CGRectMake(10, 132, 152, 21)];
    name.font = [UIFont fontWithName:@"Helvetica Bold" size:13];
    name.textColor = [UIColor blackColor];
    name.text = [dis valueForKey:@"name"];
    UILabel *address = [[UILabel alloc] initWithFrame:CGRectMake(10, 149, 194, 21)];
    address.font = [UIFont fontWithName:@"Helvetica Light" size:12];
    address.textColor = [UIColor blackColor];
    address.text = [dis valueForKey:@"address"];
    UILabel *km = [[UILabel alloc] initWithFrame:CGRectMake(278, 133, 42, 21)];
    km.font = [UIFont fontWithName:@"Helvetica" size:11];
    CLLocation *current = [[CLLocation alloc] initWithLatitude:locationManager.location.coordinate.latitude longitude:locationManager.location.coordinate.longitude];
    CLLocation *itemLoc = [[CLLocation alloc] initWithLatitude:[[dis valueForKey:@"lat"] doubleValue] longitude:[[dis valueForKey:@"lon"] doubleValue]];
    CLLocationDistance itemDist = [itemLoc distanceFromLocation:current]/1000;
    //NSLog(@"Distance: %f", itemDist);
    km.text = [[NSString alloc] initWithFormat:@"%.2fkm", itemDist];
    views.userInteractionEnabled = YES;
    [views addGestureRecognizer:imageMove];
    _starRating = [[EDStarRating alloc] initWithFrame:CGRectMake(234, 149, 78, 16)];
    _starRating.starImage = [UIImage imageNamed:@"star.png"] ;
    _starRating.starHighlightedImage = [UIImage imageNamed:@"starhighlighted.png"];
    _starRating.maxRating = 5.0;
    _starRating.delegate = self;
    _starRating.horizontalMargin = 0;
    _starRating.editable=NO;
    _starRating.rating= [[dis valueForKey:@"rating"] floatValue];
    _starRating.displayMode=EDStarRatingDisplayHalf;
    [views addSubview:imageView];
    [views addSubview:name];
    [views addSubview:address];
    [views addSubview:km];
    [views addSubview:_starRating];
    [responseScroll setUserInteractionEnabled:YES];
    [responseScroll addSubview:views];

    [responseScroll addGestureRecognizer:imageMove];

    contentOffset += views.frame.size.width;
    responseScroll.contentSize = CGSizeMake(contentOffset, views.frame.size.height);
}

}

And the code for handling View Click Events is below, I know I'm doing it wrong but I can't figure out what to do here.

-(void)moreViewMove {


for (NSString *dat in carouselArray) {
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    path = [path stringByAppendingPathComponent:@"u_id.plist"];
    NSMutableDictionary *dico = [[NSMutableDictionary alloc] initWithContentsOfFile:path];

    NSString *place_id = [dat valueForKey:@"place_id"];
    NSString *place_reference = [dat valueForKey:@"place_reference"];

    CLLocation *current = [[CLLocation alloc] initWithLatitude:startLocation.coordinate.latitude longitude:startLocation.coordinate.longitude];
    CLLocation *itemLoc = [[CLLocation alloc] initWithLatitude:[[dat valueForKey:@"lat"] floatValue] longitude:[[dat valueForKey:@"lon"] floatValue]];
    CLLocationDistance itemDist = [itemLoc distanceFromLocation:current]/1000;

    UIDevice *device = [UIDevice currentDevice];
    NSString *u_id = [[device identifierForVendor] UUIDString];
    if ([dico objectForKey:@"u_id"]) {
        moreView *more = [self.storyboard instantiateViewControllerWithIdentifier:@"MoreView"];
        more.names = [dat valueForKey:@"name"];
        more.currentLat = [[NSString alloc] initWithFormat:@"%f", locationManager.location.coordinate.latitude];
        more.currentLon = [[NSString alloc] initWithFormat:@"%f", locationManager.location.coordinate.longitude];
        more.destinationLon = [dat valueForKey:@"lon"];
        more.destinationLat = [dat valueForKey:@"lat"];
        more.addressL = [dat valueForKey:@"address"];
        more.kilo = [[NSString alloc] initWithFormat:@"%.2fkm", itemDist];
        more.dataURL = @{@"type": @"details",@"u_id":[dico objectForKey:@"u_id"], @"place_id": place_id, @"place_reference": place_reference, @"device":@"server"};
        [self.navigationController pushViewController:more animated:YES];
    } 
}

}

Please, any help would be Appreciated... Thanks

The most unusual part of the code is the loop in moreViewMove . It looks like it will allocate and push up to N view controllers, where N is the number of elements in carouselArray .

The general pattern for this sort of thing is to have a loop that creates the views based on the model, a gesture recognizer to get the taps, and means to map the tap back to the model. Then the tap handler just looks up a single model item and performs navigation.

The loop in updateUI: creates the subviews and gesture recognizers. A common means of mapping the views back to the model is with the view's tag property. In your updateUI, you would do something like this:

UIView *views = [[UIView alloc] initWithFrame:frame];
views.tag = [carouselArray indexOfObject:dis];

// ...
// change the gesture recognizer selector to take a parameter
// notice the colon on the selector moreViewMove:
UITapGestureRecognizer *imageMove = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(moreViewMove:)];

Now in moreViewMove:, you can find out which index was tapped because the gesture recognizer will be sent as a param...

- (void)moreViewMove:(UITapGestureRecognizer *)gr {

    // don't put a loop in here.
    // probably don't build a dictionary in here that doesn't depend on which item was tapped

    UIView *theViewThatWasTapped = gr.view;
    NSInteger tag = theViewThatWasTapped.tag;

    // now, we can know what part of our model was tapped
    NSString *dis = carouselArray[tag];

    // check how you're doing with an NSLog
    NSLog(@"user tapped view with tag %ld model is %@", tag, dis);

    // your job now is to allocate a single view controller,
    // configure it with your model (dis) and push it

Do as little work as you can to configure the new vc. Any init stuff that's invariant with respect to what part of the model was selected should be moved elsewhere, hopefully into that new view controller's initialization.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM