AddTarget के लिए पैरामीटर पास करना: कार्रवाई: forControlEvents


125

मैं addTarget का उपयोग कर रहा हूं: कार्रवाई: forControlEvents इस तरह:

[newsButton addTarget:self
action:@selector(switchToNewsDetails)
forControlEvents:UIControlEventTouchUpInside];

और मैं अपने चयनकर्ता "switchToNewsDetails" के लिए मापदंडों को पारित करना चाहूंगा। केवल एक चीज जो मैं करने में सफल हूं, वह (आईडी) प्रेषक को लिखित रूप से पारित करना है:

action:@selector(switchToNewsDetails:)

लेकिन मैं पूर्णांक मानों जैसे चर को पास करने की कोशिश कर रहा हूं। इसे इस तरह से लिखना काम नहीं करता है:

int i = 0;
[newsButton addTarget:self
action:@selector(switchToNewsDetails:i)
forControlEvents:UIControlEventTouchUpInside];

इसे इस तरह से लिखना भी काम नहीं करता है:

int i = 0;
[newsButton addTarget:self
action:@selector(switchToNewsDetails:i:)
forControlEvents:UIControlEventTouchUpInside];

किसी भी सहायता की सराहना की जाएगी :)


switchToNewsDetails के लिए विधि हस्ताक्षर क्या है?
हारून सॉन्डर्स

- (शून्य) switchToNewsDetails: (आईडी) प्रेषक; - (शून्य) switchToNewsDetails: (int) i: (आईडी) प्रेषक;
पियरे एस्पेनन

लेकिन क्या मैं पर निर्भर करता है? क्या यह प्रत्येक बटन के लिए विशिष्ट है? मेरा उत्तर देखें - क्या आपको संपत्ति की ज़रूरत नहीं है?
व्लादिमीर


@PierreEspenan आपका वर्तमान स्वीकृत उत्तर केवल पूर्णांक टैग के माध्यम से पारित करने की अनुमति देता है जो बहुत सीमित है। मेरा आग्रह है कि आप इसे मेरे उत्तर में बदल दें, जो किसी भी वस्तु को पारित करने की अनुमति देता है । stackoverflow.com/a/40051706/2057171
अल्बर्ट रेनशॉ

जवाबों:


173
action:@selector(switchToNewsDetails:)

आप switchToNewsDetails:यहां पद्धति के लिए पैरामीटर पास नहीं करते हैं। आप बस कुछ चयन होने पर बटन को कॉल करने में सक्षम बनाने के लिए एक चयनकर्ता बनाते हैं (आपके मामले में स्पर्श करें)। नियंत्रण क्रियाओं का जवाब देने के लिए 3 प्रकार के चयनकर्ताओं का उपयोग कर सकते हैं, उनमें से सभी ने अपने मापदंडों का पूर्वनिर्धारित अर्थ दिया है:

  1. कोई मापदंडों के साथ

    action:@selector(switchToNewsDetails)
  2. 1 पैरामीटर के साथ जो संदेश भेजता है उस नियंत्रण को इंगित करता है

    action:@selector(switchToNewsDetails:)
  3. 2 पैरामीटर जो संदेश को भेजने वाले नियंत्रण और संदेश को ट्रिगर करने वाली घटना को दर्शाता है:

    action:@selector(switchToNewsDetails:event:)

यह स्पष्ट नहीं है कि आप वास्तव में क्या करने की कोशिश करते हैं, लेकिन आप प्रत्येक बटन पर एक विशिष्ट विवरण सूचकांक निर्दिष्ट करना चाहते हैं, जिसे आप निम्न कर सकते हैं:

  1. आवश्यक अनुक्रमणिका के बराबर प्रत्येक बटन पर एक टैग गुण सेट करें
  2. में switchToNewsDetails:विधि आपको लगता है कि सूचकांक और खुले उचित Deatails प्राप्त कर सकते हैं:

    - (void)switchToNewsDetails:(UIButton*)sender{
        [self openDetails:sender.tag];
        // Or place opening logic right here
    }

4
क्या होगा अगर हम पूर्णांक के अलावा कुछ और पास करने की कोशिश कर रहे हैं? क्या होगा अगर मुझे एक स्ट्रिंग की तरह ऑब्जेक्ट पास करने की आवश्यकता है?
user102008

@user आपका संदर्भ क्या है? लगता है कि आपको इसे अलग से पारित करने की आवश्यकता होगी
व्लादिमीर

बहुत बहुत धन्यवाद। आपको यह डेटा कहां मिला? मैं हमेशा संदर्भ की सराहना करता हूं ताकि शायद मैं अगली बार खुद इसे पा सकूं।
भालूमाँ

1
@bearMountain आप इस लिंक को देख सकते हैं: developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… उदाहरण के लिए
व्लादिमीर

3
आपको इसे अलग से पारित करने की आवश्यकता नहीं है। यदि आप किसी भी NSObject को पास कर रहे हैं, तो आप बस कह सकते हैं [button.layer setValue:yourObject forKey:@"anyKey"];और फिर विधि में (objectClass *)[button.layer valueForKey:@"anyKey"];यह जाँच सकते हैं कि यह एक और अधिक मुफ्त संस्करण की तरह है.tag
अल्बर्ट रेनशॉ

64

बटन के साथ कस्टम पैरामेट्स को पास करने के लिए आपको सिर्फ सब्बल UIButton की जरूरत है ।

(ASR चालू है, इसलिए कोड में कोई रिलीज़ नहीं है।)

यह myButton.h है

#import <UIKit/UIKit.h>

@interface myButton : UIButton {
    id userData;
}

@property (nonatomic, readwrite, retain) id userData;

@end

यह myButton.m है

#import "myButton.h"
@implementation myButton
@synthesize userData;
@end

उपयोग:

myButton *bt = [myButton buttonWithType:UIButtonTypeCustom];
[bt setFrame:CGRectMake(0,0, 100, 100)];
[bt setExclusiveTouch:NO];
[bt setUserData:**(insert user data here)**];

[bt addTarget:self action:@selector(touchUpHandler:) forControlEvents:UIControlEventTouchUpInside];

[view addSubview:bt];

समारोह में विश्वास:

- (void) touchUpHandler:(myButton *)sender {
    id userData = sender.userData;
}

यदि आपको उपरोक्त कोड के किसी भी भाग पर मुझे अधिक विशिष्ट होने की आवश्यकता है - टिप्पणी में इसके बारे में पूछने के लिए स्वतंत्र महसूस करें।


मुझे लगता है कि यह सबसे अच्छा तरीका है
thisağatay Gürtürk

सबसे सुरुचिपूर्ण समाधान।
विक्टर सी।

2
शानदार जवाब ... बहुत अनुकूलन। ठीक वही जो मेरे द्वारा खोजा जा रहा था। Molodets! :)
डेनिकोव

प्रतिक्रिया के लिए धन्यवाद :) खुशी है, कि यह किसी के लिए उपयोगी है :)
यूरी Polezhayev

1
सरल और उपयोगी समाधान। बस मुझे यह जोड़ने दें कि यह tagएंड्रॉइड विचारों में संपत्ति के समान है । वे किसी भी वस्तु को स्टोर कर सकते हैं। और आप कुंजी को किसी शब्दकोश / मानचित्र में भी स्टोर कर सकते हैं ।
फेरन मायलिनच

19

लक्ष्य-कार्रवाई से कार्रवाई चयनकर्ता के तीन अलग-अलग रूपों की अनुमति मिलती है:

- (void)action
- (void)action:(id)sender
- (void)action:(id)sender forEvent:(UIEvent *)event

16

.Tag के माध्यम से सिर्फ एक (int) से अधिक की आवश्यकता है? KVC का उपयोग करें!

आप बटन ऑब्जेक्ट के माध्यम से अपने द्वारा वांछित किसी भी डेटा को पास कर सकते हैं (CALayers keyValue तानाशाह तक पहुंचकर)।


अपना लक्ष्य इस तरह सेट करें (":")

[myButton addTarget:self action:@selector(buttonTap:) forControlEvents:UIControlEventTouchUpInside];

अपना डेटा (बटन) स्वयं जोड़ें ( .layerबटन का अच्छा है) इस तरह:

NSString *dataIWantToPass = @"this is my data";//can be anything, doesn't have to be NSString
[myButton.layer setValue:dataIWantToPass forKey:@"anyKey"];//you can set as many of these as you'd like too!

फिर जब बटन टैप किया जाता है तो आप इसे इस तरह से देख सकते हैं:

-(void)buttonTap:(UIButton*)sender{

    NSString *dataThatWasPassed = (NSString *)[sender.layer valueForKey:@"anyKey"];
    NSLog(@"My passed-thru data was: %@", dataThatWasPassed);

}

ऑब्जेक्ट सेट करने या जोड़ने के लिए UIButton.layer में कोई विधि नहीं है। आपको वह समाधान कहां से मिलेगा?
mAc

1
एक UIButton UIView का एक प्रकार है, सभी UIView में CALayer .layer प्रॉपर्टी है। काइलर्स में NS सहकर्मी व्यवहार होता है। ध्यान दें कि यह उद्देश्य-सी स्विफ्ट नहीं है, यह मुद्दा हो सकता है? यहाँ ऐप्पल डॉक्स ऑन कैलेयर की-वैल्यू कोडिंग: developer.apple.com/library/content/documentation/Cocoa/…
अल्बर्ट रेनशॉ

1
यह शीर्ष पर उत्तर होना चाहिए। यह करने के लिए सबसे आसान तरीका है! धन्यवाद!
danielrosero

1
इसे उत्तर स्वीकार किया जाना चाहिए। यह बहुत आसान और स्मार्ट तरीका है।
इमॉन

1
बहुत बढ़िया जवाब! काश मुझे यह बहुत पहले पता होता।
जॉन

7

मैंने उपरोक्त जानकारी के आधार पर एक हल बनाया। मैं सिर्फ titlabel.text को उस स्ट्रिंग पर सेट करता हूं जिसे मैं पास करना चाहता हूं, और titlabel.hidden = YES सेट करें

ऐशे ही :

UIButton *imageclick = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
imageclick.frame = photoframe;
imageclick.titleLabel.text = [NSString stringWithFormat:@"%@.%@", ti.mediaImage, ti.mediaExtension];
imageclick.titleLabel.hidden = YES;

इस तरह, विरासत या श्रेणी की कोई आवश्यकता नहीं है और स्मृति रिसाव नहीं है


5

मैं एक सरणी में प्रत्येक फोन नंबर के लिए कई बटन बना रहा था, इसलिए प्रत्येक बटन को कॉल करने के लिए एक अलग फोन नंबर की आवश्यकता थी। मैंने सेटटैग फ़ंक्शन का उपयोग किया क्योंकि मैं लूप के लिए कई बटन बना रहा था:

for (NSInteger i = 0; i < _phoneNumbers.count; i++) {

    UIButton *phoneButton = [[UIButton alloc] initWithFrame:someFrame];
    [phoneButton setTitle:_phoneNumbers[i] forState:UIControlStateNormal];

    [phoneButton setTag:i];

    [phoneButton addTarget:self
                    action:@selector(call:)
          forControlEvents:UIControlEventTouchUpInside];
}

फिर मेरे कॉल में: विधि मैंने लूप के लिए एक ही उपयोग किया और सही फोन नंबर लेने के लिए एक स्टेटमेंट:

- (void)call:(UIButton *)sender
{
    for (NSInteger i = 0; i < _phoneNumbers.count; i++) {
        if (sender.tag == i) {
            NSString *callString = [NSString stringWithFormat:@"telprompt://%@", _phoneNumbers[i]];
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callString]];
        }
    }
}

आप इस कोड में सुधार कर सकते हैं:- (void)call:(UIButton *)sender { NSString *phoneNumber = _phoneNumbers[i]; NSString *callString = [NSString stringWithFormat:@"telprompt://%@", phoneNumber]; [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callString]]; }
लैडेसा

2

जैसा कि समाधान के लिए यहां कई तरीके बताए गए हैं, सिवाय श्रेणी की सुविधा के।

परिभाषित (अंतर्निहित) तत्व को अपने अनुकूलन योग्य तत्व में विस्तारित करने के लिए श्रेणी सुविधा का उपयोग करें।

उदाहरण के लिए (पूर्व):

@interface UIButton (myData)

@property (strong, nonatomic) id btnData;

@end

आपके विचार में नियंत्रक। एम.एम.

 #import "UIButton+myAppLists.h"

UIButton *myButton = // btn intialisation....
 [myButton set btnData:@"my own Data"];
[myButton addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];

आयोजन प्रबंधकर्ता:

-(void)buttonClicked : (UIButton*)sender{
    NSLog(@"my Data %@", sender. btnData);
}

आप वास्तव में श्रेणियों में गुण नहीं जोड़ सकते।
HotFudgeSunday

2

आप सहायक-क्रिया को बंद कर सकते हैं (ऑब्जेक्टिव-सी में ब्लॉक) एक सहायक क्लोजर आवरण (क्लोजरस्लीव) को जोड़कर और इसे नियंत्रण से संबंधित वस्तु के रूप में जोड़ सकते हैं ताकि यह बरकरार रहे। इस तरह आप किसी भी पैरामीटर को पास कर सकते हैं।

स्विफ्ट 3

class ClosureSleeve {
    let closure: () -> ()

    init(attachTo: AnyObject, closure: @escaping () -> ()) {
        self.closure = closure
        objc_setAssociatedObject(attachTo, "[\(arc4random())]", self, .OBJC_ASSOCIATION_RETAIN)
    }

    @objc func invoke() {
        closure()
    }
}

extension UIControl {
    func addAction(for controlEvents: UIControlEvents, action: @escaping () -> ()) {
        let sleeve = ClosureSleeve(attachTo: self, closure: action)
        addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
    }
}

उपयोग:

button.addAction(for: .touchUpInside) {
    self.switchToNewsDetails(parameter: i)
}

उपरोक्त विधि ( self.switchToNewsDetails(parameter: i)) 2 बार फायरिंग, मुझे मदद करने के लिए क्यों
नागेन्द्र

कोड मेरे लिए काम करता है। एक नए सिंगल व्यू ऐप प्रोजेक्ट pastebin.com/tPaqetMb में परीक्षण किया गया । तो समस्या शायद आपके कोड में है, जैसे button.addAction()दो बार कॉल करना । button.addActionक्लोजर के अंदर और पहली लाइन पर भी एक ब्रेकपॉइंट जोड़ें और इसे स्वयं डीबग करने का प्रयास करें।
मारीआन Marierný

2

एक और तरीका है, जिसमें आप उस सेल का इंडेक्सपाप प्राप्त कर सकते हैं, जहां आपका बटन दबाया गया था:

सामान्य क्रिया चयनकर्ता का उपयोग करना:

 UIButton *btn = ....;
    [btn addTarget:self action:@selector(yourFunction:) forControlEvents:UIControlEventTouchUpInside];

और फिर अपने नियंत्रण में:

   - (void) yourFunction:(id)sender {

    UIButton *button = sender;
    CGPoint center = button.center;
    CGPoint rootViewPoint = [button.superview convertPoint:center toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:rootViewPoint];
    //the rest of your code goes here
    ..
}

जब से आप एक indexPath मिलता है यह बहुत सरल हो जाता है।


1

ऊपर मेरी टिप्पणी देखें, और मेरा मानना ​​है कि एक से अधिक पैरामीटर होने पर आपको NSInvocation का उपयोग करना होगा

NSInvocation के बारे में अधिक जानकारी यहाँ

http://cocoawithlove.com/2008/03/construct-nsinvocation-for-any-message.html


असल में, मैं कई पारमों को पास नहीं करना चाहता, मैं सिर्फ एक पूर्णांक चाहता हूं।
पियरे एस्पेनन

वास्तव में वहाँ प्रदर्शनकर्ता है: withObject: withObject: विधि जो 2 मापदंडों के साथ चयनकर्ताओं को कॉल करने की अनुमति देती है। लेकिन अधिक के लिए आपको NSInvocation
व्लादिमीर की

1

इससे मेरी समस्या ठीक हो गई लेकिन जब तक मैं बदल नहीं गया, तब तक यह दुर्घटनाग्रस्त हो गया

action:@selector(switchToNewsDetails:event:)                 

सेवा

action:@selector(switchToNewsDetails: forEvent:)              

0

मैंने कस्टमबूटन में यूआईब्यूटन को उपविभाजित किया और मैं एक संपत्ति जोड़ता हूं जहां मैं अपना डेटा संग्रहीत करता हूं। इसलिए मैं विधि कहता हूं: (CustomButton *) प्रेषक और उस विधि में मैं केवल अपना डेटा प्रेषक। अपरिपक्वता पढ़ता हूं।

उदाहरण कस्टमबटन:

@interface CustomButton : UIButton
@property(nonatomic, retain) NSString *textShare;
@end

विधि कार्रवाई:

+ (void) share: (CustomButton*) sender
{
    NSString *text = sender.textShare;
    //your work…
}

कार्रवाई सौंपें

    CustomButton *btn = [[CustomButton alloc] initWithFrame: CGRectMake(margin, margin, 60, 60)];
    // other setup…

    btnWa.textShare = @"my text";
    [btn addTarget: self action: @selector(shareWhatsapp:)  forControlEvents: UIControlEventTouchUpInside];

0

यदि आप केवल नेविगेशन कंट्रोलर द्वारा दिखाए गए बायरबारूटन इटेम के लिए पाठ को नए दृश्य के साथ बदलना चाहते हैं, तो आप वर्तमान दृश्य का शीर्षक बदल सकते हैं इससे पहले कि आप चाहने वाले पाठ को pushViewController कॉल कर सकते हैं और इसे दृश्य में पुनर्स्थापित कर सकते हैं। वर्तमान दृश्य।

यह दृष्टिकोण कार्यक्षमता (popViewController) और दिखाए गए तीर की उपस्थिति को बरकरार रखता है।

यह हमारे लिए कम से कम iOS 12 के साथ काम करता है, जिसे Xcode 10.1 के साथ बनाया गया है ...


मुझे नहीं लगता कि यह उत्तर प्रश्न से संबंधित है।
पियरे एस्पेनन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.