2012-12-12 40 views
29

जब उपयोगकर्ता गतिशील TableView में किसी सेल को छूता है तो मुझे पॉपओवर सेगू करने की आवश्यकता होती है। लेकिन जब मैं इस कोड के साथ यह करने के लिए प्रयास करें:क्या मैन्युअल रूप से पॉपओवर सेगू करना (गतिशील UITableView सेल से) करना संभव है?

- (void)tableView:(UITableView *)tableview didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
     [self performSegueWithIdentifier:@"toThePopover" sender:[tableView cellForRowAtIndexPath]]; 
    //... 
} 

की तुलना में मैं कोई त्रुटि मिलती है:

अवैध विन्यास

Popover segue with no anchor

वहाँ यह करने के लिए कोई तरीका है (एक पॉपओवर segue प्रदर्शन करने के लिए मैन्युअल रूप से गतिशील tableView से)?

उत्तर

61

मुझे आज रात इसी मुद्दे का सामना करना पड़ा, वहां कुछ कामकाज (पॉपओवर पुराने तरीके से पेश करने सहित)।

इस उदाहरण के लिए, मेरे पास एक ऑब्जेक्ट है जो मेरी कस्टम सेल क्लास में संग्रहीत है। जब सेल का चयन किया जाता है, तो मैं इस तरह के फ़ंक्शन को ऑब्जेक्ट के बारे में popOverViewController में विवरण खोलने के लिए कॉल करता हूं, और तालिका में इसके संबंधित सेल पर बिंदु (एंकर)।

- (void)openCustomPopOverForIndexPath:(NSIndexPath *)indexPath{ 
     CustomViewController* customView = [[self storyboard] instantiateViewControllerWithIdentifier:@"CustomViewController"]; 

     self.myPopOver = [[UIPopoverController alloc] 
            initWithContentViewController:customView]; 
     self.myPopOver.delegate = self; 
     //Get the cell from your table that presents the popover 
     MyCell *myCell = (MyCell*)[self.tableView cellForRowAtIndexPath:indexPath]; 
     CGRect displayFrom = CGRectMake(myCell.frame.origin.x + myCell.frame.size.width, myCell.center.y + self.tableView.frame.origin.y - self.tableView.contentOffset.y, 1, 1); 
     [self.myPopOver presentPopoverFromRect:displayFrom 
              inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES]; 
    } 

इस विधि के साथ समस्या यह है कि हमें अक्सर कस्टम प्रारंभकर्ता के लिए पॉपओवर दृश्य की आवश्यकता होती है। यह समस्याग्रस्त है यदि आप चाहते हैं कि आपका दृश्य xib के बजाय स्टोरीबोर्ड में डिज़ाइन किया जाए और एक कस्टम इनिट विधि है जो आपके सेल से संबंधित ऑब्जेक्ट को इसके प्रदर्शन के लिए उपयोग करने के लिए पैरामीटर के रूप में ले जाती है। आप केवल एक पॉपओवर सेगू (पहली नज़र में) का उपयोग नहीं कर सकते हैं क्योंकि आपको गतिशील एंकर पॉइंट की आवश्यकता होती है (और आप सेल प्रोटोटाइप को एंकर नहीं कर सकते हैं)। तो यहां मैंने यह किया है:

  1. सबसे पहले, अपने दृश्य नियंत्रकों के दृश्य में एक छुपा 1px एक्स 1px UIButton बनाएं। (बटन बाधाओं को देने के लिए महत्वपूर्ण है जो इसे दृश्य में कहीं भी स्थानांतरित करने की अनुमति देगा)
  2. फिर अपने व्यू कंट्रोलर में बटन के लिए आउटलेट बनाएं (मैंने अपना पॉपओवर एंकर बटन कहा है) और छुपा बटन से एक सेगू खींचें उस नियंत्रक को देखें जिसे आप सीगू करना चाहते हैं। इसे एक पॉपओवर segue बनाओ।

अब आपके पास 'कानूनी' एंकर के साथ एक पॉपओवर सेग्यू है। बटन छुपा हुआ है, इसलिए कोई भी इसे गलती से स्पर्श नहीं कर सकता है। आप केवल एंकर पॉइंट के लिए इसका उपयोग कर रहे हैं।

अब इस तरह अपने फ़ंक्शन में मैन्युअल रूप से अपने सेग्यू को कॉल करें।

- (void)openCustomPopOverForIndexPath:(NSIndexPath *)indexPath{ 
     //Get the cell from your table that presents the popover 
     MyCell *myCell = (MyCell*)[self.tableView cellForRowAtIndexPath:indexPath]; 

     //Make the rect you want the popover to point at. 
     CGRect displayFrom = CGRectMake(myCell.frame.origin.x + myCell.frame.size.width, myCell.center.y + self.tableView.frame.origin.y - self.tableView.contentOffset.y, 1, 1); 

     //Now move your anchor button to this location (again, make sure you made your constraints allow this) 
     self.popOverAnchorButton.frame = displayFrom; 
     [self performSegueWithIdentifier:@"CustomPopoverSegue" sender:myCell]; 
    } 

और ...... वोला। अब आप अपने सभी महानता के साथ segues के जादू का उपयोग कर रहे हैं और आपके पास एक गतिशील एंकर बिंदु है जो आपके सेल को इंगित करता है। अब -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender में आप प्रेषक को अपने सेल की कक्षा में डाल सकते हैं (यह देखते हुए कि आप प्रेषक प्रकार पर उचित चेक करते हैं और कौन सी सेग्यू कहा जा रहा है) और सेल के ऑब्जेक्ट को सेग्यू का गंतव्य देखें।

अगर यह मदद करता है तो मुझे बताएं, या किसी के पास कोई प्रतिक्रिया या सुधार है।

+7

इसके अलावा, अगर यह आपकी मदद करता है। यदि आप इसे वोट दे सकते हैं। मैं एक नया उपयोगकर्ता हूं और कुछ भी करने के लिए बेवकूफ क्रेडिट कमाने की जरूरत है। – johnrechd

+0

क्या आपको पता है कि एक्सकोड 5/आईओएस 7 ने इस क्षेत्र में कुछ भी सुधार किया है? वैसे भी महान कामकाज। – neural5torm

+0

मुझे अभी तक यकीन नहीं है, हालांकि मुझे ऐसा नहीं लगता है। मैं एक ऐप अपडेट कर रहा हूं जो आईओएस 7 के लिए इस अगले सप्ताह का उपयोग करता है और यदि आवश्यक हो तो अपडेट हो जाएगा। – johnrechd

3

बस इस उत्तर को एक स्पर्श सेल से पॉपओवर पेश करने के वैकल्पिक तरीके के रूप में जोड़ना, हालांकि यह एक सेगू के बजाय कोड का उपयोग करता है। popoverEdit की एक स्टोरीबोर्ड आईडी के साथ नया दृश्य नियंत्रक की स्थापना की, स्टोरीबोर्ड का उपयोग करना: हालांकि यह बहुत आसान है और iOS 7 के माध्यम से आईओएस 4 से मेरे लिए काम किया है:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    [tableView deselectRowAtIndexPath:indexPath animated:NO]; 

    //get the data of the row they clicked from the array 
    Url* clickedRec = [self.resultsArray objectAtIndex:indexPath.row]; 

    //hide the popover in case it was already opened from a previous touch.  
    if (self.addNewPopover.popoverVisible) { 
      [self.addNewPopover dismissPopoverAnimated:YES]; 
      return; 
     } 

    //instantiate a view controller from the storyboard 
    AddUrlViewController *viewControllerForPopover = 
    [self.storyboard instantiateViewControllerWithIdentifier:@"addUrlPopup"]; 

    //set myself as the delegate so I can respond to the cancel and save touches. 
    viewControllerForPopover.delegate=self; 
    //Tell the view controller that this is a record edit, not an add   
    viewControllerForPopover.addOrEdit = @"Edit"; 
    //Pass the record data to the view controller so it can fill in the controls    
    viewControllerForPopover.existingUrlRecord = clickedRec; 

    UIPopoverController *popController = [[UIPopoverController alloc] 
              initWithContentViewController:viewControllerForPopover]; 

    //keep a reference to the popover since I'm its delegate   
    self.addNewPopover = popController; 

    //Get the cell that was clicked in the table. The popover's arrow will point to this cell since it was the one that was touched. 
    UITableViewCell *clickedCell = [self.tableView cellForRowAtIndexPath:indexPath]; 

    //present the popover from this cell's frame. 
    [self.addNewPopover presentPopoverFromRect:clickedCell.frame inView:self.myTableView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; 
} 
2

स्विफ्ट जवाब popoverPresentationController का उपयोग कर।

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 

    let fromRect:CGRect = self.tableView.rectForRowAtIndexPath(indexPath) 

    let popoverVC = storyboard?.instantiateViewControllerWithIdentifier("popoverEdit") as! UIViewController 
    popoverVC.modalPresentationStyle = .Popover 
    presentViewController(popoverVC, animated: true, completion: nil) 
    let popoverController = popoverVC.popoverPresentationController 
    popoverController!.sourceView = self.view 
    popoverController!.sourceRect = fromRect 
    popoverController!.permittedArrowDirections = .Any 

} 
+0

यह मेरे लिए एक पॉपओवर सेग्यू के लिए एक तैयारफॉरसेग्यू के अंदर भी काम करता है। मुझे 1x1 pt व्यू के साथ रेक्ट को परिवर्तित करने या किसी अन्य पुराने वर्कअराउंड करने की ज़रूरत नहीं है। मैंने स्टोरीबोर्ड में tableView में SourceView भी सेट किया है। इससे विभाजित दृश्य पर अनुकूलन में मदद मिलती है क्योंकि मेरा पॉपओवर अधिकतर स्क्रीन से बाहर फिसल रहा था जब प्राथमिक दृश्य मल्टीटास्किंग समायोजन में छिपा हुआ था। – James