从 UIScrollview UIView SubView 推送到另一个 ViewController

Posted

技术标签:

【中文标题】从 UIScrollview UIView SubView 推送到另一个 ViewController【英文标题】:Pushing to another ViewController from UIScrollview UIView SubView 【发布时间】:2014-05-20 18:48:42 【问题描述】:

我有一个以轮播方式显示信息的滚动视图,我现在要做的是在轮播中的每个视图上添加点击事件,我可以通过添加 UITapGestureRecongnizer* 每次推送时,都会记录一个错误*嵌套推送动画会导致导航栏损坏,并且会显示错误信息 下面是我加载 Carousel View 和添加 Click 事件的代码,Carousel 上的数据也是从 jSON 获取并与 NSObject 一起存储在 **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);



处理查看点击事件的代码如下,我知道我做错了但我不知道该怎么做。

-(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];
     



请,任何帮助将不胜感激...谢谢

【问题讨论】:

【参考方案1】:

代码中最不寻常的部分是moreViewMove 中的循环。看起来它将分配并推送到 N 个视图控制器,其中 N 是 carouselArray 中的元素数。

这类事情的一般模式是有一个基于模型创建视图的循环,一个获取点击的手势识别器,以及将点击映射回模型的方法。然后点击处理程序只查找单个模型项并执行导航。

updateUI: 中的循环创建子视图和手势识别器。将视图映射回模型的常用方法是使用视图的tag 属性。在你的 updateUI 中,你会做这样的事情:

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:)];

现在在 moreViewMove: 中,您可以找出点击了哪个索引,因为手势识别器将作为参数发送...

- (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

尽可能少地配置新的 vc。任何与选择模型的哪个部分无关的 init 内容都应该移到其他地方,希望能移到新视图控制器的初始化中。

【讨论】:

拜托,你让我很开心,Hommie,loooooolllllll 今天我在工作的一个朋友实际上告诉了我同样的事情,但不能很好地理解他。谢谢一堆人,非常感谢,但现在的问题是它只选择滚动中的第一个视图,如果我点击下一个视图,它会给我第一个视图的信息 很高兴您取得了进展。在moreViewMove: 方法中,能否将我在编辑中建议的日志记录添加到上面的moreViewMove 方法中。 总是选择 Tag 0 接下来,当你在updateUI中设置标签时,NSLog标签。您还可以记录手势识别器(使用 %@ 或 %p)并将其与 moveViewMove 中发送的手势识别器进行比较: 是的,它很好地标记了它。它非常准确地标记它,现在数组中只有四个字典,它给每个字典一个标签号

以上是关于从 UIScrollview UIView SubView 推送到另一个 ViewController的主要内容,如果未能解决你的问题,请参考以下文章

在 iPhone SDK 中将 UIButton 从 UIScrollView 移动到 UIView

将 UIView 从 xib 添加到 UIScrollView

将捏合手势从自定义 UIView 传递到父 UIScrollView

iOS:在故事板中将子类从 UIView 更改为 UIScrollView

将触摸事件从 UIVew 传输到 UIScrollView

将 UIView 从 UIPopOverController 中的 UIScrollView 拖放到主 UIViewController?