2013-02-13 13 views
27

मैं __bridge आईओएस में आईएनजी पर कुछ सलाह की जरूरत है।कहाँ और कैसे __bridge को

उम्मीद है कि SSCCE नीचे समस्या बेहतर समझा जाएगा की तुलना में मैं शब्दों में कर सकते हैं, लेकिन मुझे पता है कि कैसे मैं एक NSMutableArray* करने के लिए एक void* परिवर्तित कर सकते हैं की जरूरत है; जो __bridge विविधता का उपयोग किया जाना चाहिए (कोड में टिप्पणी देखें)।

विभिन्न पुलों के बारे में पढ़ना, मैं निष्कर्ष निकाला कि मैं __bridge_transfer की आवश्यकता होगी, लेकिन मैं CGPathApplyCGPath बाद में CGPoints की एक सरणी करना चाहते हैं तो मैं अंत में addObject:

पर एक EXC_BAD_ACCESS प्राप्त बुलाया गया है ।

#import <Foundation/Foundation.h> 

void _processPathElement(void* info, const CGPathElement* element) 
{ 
    NSMutableArray *array = (/* WHAT BRIDGE HERE */ NSMutableArray*) info; 
    switch (element->type) 
    { 
     case kCGPathElementMoveToPoint: 
     case kCGPathElementAddLineToPoint: 
     { 
      CGPoint point = element->points[0]; 
      [array addObject:[NSValue valueWithCGPoint:point]]; 
      break; 
     } 
     default: 
      break; 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    @autoreleasepool 
    { 
     //Create path 
     CGMutablePathRef path = CGPathCreateMutable(); 
     CGPathMoveToPoint( path, NULL, 0, 0); 
     CGPathAddLineToPoint(path, NULL, 1, 0); 
     CGPathAddLineToPoint(path, NULL, 1, 1); 
     CGPathAddLineToPoint(path, NULL, 0, 1); 
     CGPathCloseSubpath(path); 

     NSMutableArray *pathPoints = [NSMutableArray array]; 
     CGPathApply(path, &pathPoints, _processPathElement); 

     NSLog(@"Points:%@", pathPoints); 
    } 
} 

1: SSCCE

+0

मुझे समझ नहीं आता। एक्सकोड द्वारा सुझाए गए अनुसार मैंने बस '__bridge' का उपयोग किया। और आपका प्रोग्राम संकलित करता है। – esh

+3

या आप इसे ढूंढ रहे हैं, '__bridge' स्वामित्व के हस्तांतरण के बिना उद्देश्य-सी और कोर फाउंडेशन के बीच एक सूचक स्थानांतरित करता है। '__bridge_retained' या 'CFBridgingRetain' कोर फाउंडेशन पॉइंटर को ऑब्जेक्टिव-सी पॉइंटर बनाता है और आपको स्वामित्व स्थानांतरित करता है। आप ऑब्जेक्ट के स्वामित्व को छोड़ने के लिए CFRelease या संबंधित फ़ंक्शन को कॉल करने के लिए ज़िम्मेदार हैं। '__bridge_transfer' या 'CFBridgingRelease' उद्देश्य-सी के लिए एक गैर-उद्देश्य-सी सूचक को स्थानांतरित करता है और एआरसी को स्वामित्व स्थानांतरित करता है। एआरसी वस्तु के स्वामित्व को छोड़ने के लिए जिम्मेदार है। – esh

+0

@ ब्लैकफैम 3 (पहली टिप्पणी) यह संकलन करने के लिए कोड प्राप्त करने का एक मामला नहीं है। मुझे स्मृति को सही ढंग से बनाए रखने की आवश्यकता है ताकि मेरे पास 'NSLog' –

उत्तर

47

टी वह पुल कीवर्ड can be found here के उपयोग पर दस्तावेज़ीकरण। विशेष रूप से, मैं §3.2.4 कहना चाहता हूँ:

(__bridge T) op गंतव्य प्रकार टी संकार्य डाले टी एक retainable वस्तु सूचक प्रकार है, तो सेशन एक गैर retainable सूचक प्रकार होना चाहिए। यदि टी एक गैर-रखरखाव सूचक प्रकार है, तो ऑप में एक टिकाऊ ऑब्जेक्ट पॉइंटर प्रकार होना चाहिए। अन्यथा कास्ट खराब गठित है। स्वामित्व का कोई हस्तांतरण नहीं है, और एआरसी सम्मिलित संचालन को बरकरार रखता है।

(__bridge_retained T) op ऑपरेंड को रोकता है, जिसमें गंतव्य प्रकार के लिए बनाए रखने योग्य ऑब्जेक्ट पॉइंटर प्रकार होना चाहिए, जो एक गैर-रखरखाव सूचक प्रकार होना चाहिए। एआरसी मूल्य को बरकरार रखता है, स्थानीय मूल्यों पर सामान्य अनुकूलन के अधीन, और प्राप्तकर्ता उस +1 को संतुलित करने के लिए ज़िम्मेदार है।

(__bridge_transfer T) op संकार्य, जो, गैर retainable सूचक प्रकार होना आवश्यक है गंतव्य प्रकार है, जो एक retainable वस्तु सूचक प्रकार होना चाहिए करने के लिए डाले। एआरसी स्थानीय मूल्यों पर सामान्य अनुकूलन के अधीन, संलग्न पूर्ण अभिव्यक्ति के अंत में मूल्य जारी करेगा। जबकि अपने NSMutableArray एक retainable सूचक प्रकार है

सूचक आप (void*) में पारित किया जा रहा हो, एक गैर retainable सूचक प्रकार है। यह __bridge_retained सीधे बाहर नियम। तो सवाल है, __bridge या __bridge_transfer पर?

__bridge_transfer आम तौर पर प्रयोग किया जाता है जब आप एक विधि है कि एक CF वस्तु है कि बनाए रखा गया है रिटर्न से ऑब्जेक्टिव-सी सूचक चाहते हैं। उदाहरण के लिए, CFStringCreateWithFormat एक बनाए गए CFString को वापस कर देगा, लेकिन यदि आप इससे एनएसएसटींग चाहते हैं, तो आपको उनके बीच __bridge_transfer की आवश्यकता होगी। इससे एआरसी उस ऑब्जेक्ट को रिलीज कर देगा जो सीएफ को उपयुक्त होने पर बनाए रखा जाएगा। उदाहरण के लिए, NSString* str = (__bridge_transfer NSString*) CFStringCreateWithFormat(...);

आपका कोड ऐसा नहीं कर रहा है, आपको स्वामित्व के साथ दखल देने की आवश्यकता नहीं है।आपकी मुख्य विधि इसके मेमोरी प्रबंधन के नियंत्रण में है, और यह केवल उस विधि के संदर्भ में गुज़र रही है जो इसे कॉल करती है (यद्यपि अप्रत्यक्ष रूप से, लेकिन यह सब मुख्य के दायरे में है)। इस प्रकार, आप __bridge का उपयोग करेंगे।

लेकिन प्रतीक्षा करें, जब मैं __bridge का उपयोग करता हूं, तो मेरे कोड को स्मृति पहुंच त्रुटियां मिलती हैं !?

आह, यह आपके द्वारा पोस्ट किए गए कोड के साथ एक मुद्दा है, और पूरे ब्रिजिंग चर्चा के संबंध में नहीं है। आपके प्रसंस्करण फ़ंक्शन _processPathElement के लिए आपको void* CGApplyPath पर पास करने की आवश्यकता है। आप जो पास कर रहे हैं वह NSMutableArray** है।

जब आप NSMutableArray* पर पुन: प्रयास करते हैं, तो आप वास्तव में NSMutableArray** कास्टिंग कर रहे हैं। यह कुख्यात EXC_BAD_ACCESS का कारण बन जाएगा। आपको पॉइंटर को पास करने की ज़रूरत है, पॉइंटर को पॉइंटर नहीं। लेकिन, CGPathApply(path, pathPoints, _processPathElement) काम नहीं करेगा, आप NSMutableArray* को void* के रूप में पास नहीं कर सकते हैं। आपको क्या चाहिए (विडंबनात्मक रूप से), एक पुल है। पहले के समान कारणों से, आपको केवल __bridge की आवश्यकता है। कोड नीचे देखें, जगह में सही पुलों के साथ, और उम्मीद के रूप में काम:

#import <UIKit/UIKit.h> 
#import <Foundation/Foundation.h> 

void _processPathElement(void* info, const CGPathElement* element) 
{ 
    NSMutableArray *array = (__bridge NSMutableArray*) info; 
    switch (element->type) 
    { 
     case kCGPathElementMoveToPoint: 
     case kCGPathElementAddLineToPoint: 
     { 
      CGPoint point = element->points[0]; 
      [array addObject:[NSValue valueWithCGPoint:point]]; 
      break; 
     } 
     default: 
      break; 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    @autoreleasepool 
    { 
     //Create path 
     CGMutablePathRef path = CGPathCreateMutable(); 
     CGPathMoveToPoint( path, NULL, 0, 0); 
     CGPathAddLineToPoint(path, NULL, 1, 0); 
     CGPathAddLineToPoint(path, NULL, 1, 1); 
     CGPathAddLineToPoint(path, NULL, 0, 1); 
     CGPathCloseSubpath(path); 

     NSMutableArray *pathPoints = [[NSMutableArray alloc] init]; 
     CGPathApply(path, (__bridge void*)pathPoints, _processPathElement); 

     NSLog(@"Points:%@", pathPoints); 
    } 
} 

यह प्रिंट आउट देगा:

Points:(
    "NSPoint: {0, 0}", 
    "NSPoint: {1, 0}", 
    "NSPoint: {1, 1}", 
    "NSPoint: {0, 1}" 
) 
+0

धन्यवाद। =] मुझे लगता है कि आप इसे लिख रहे थे जैसा कि मैंने पाया और पोस्ट किया (उसी) निष्कर्ष। आपका उत्तर हालांकि बहुत अधिक जानकारी प्रदान करता है और पुष्टि करता है कि मैंने सही समाधान में ठोकर खाई। –

+0

ध्यान दें कि 'CFBridg *' प्रकारों का उपयोग अक्सर स्पष्ट होता है (हम में से कुछ के लिए, वैसे भी)। – bbum

1

मैं क्यों इस काम करता है नहीं वास्तव में यकीन है, लेकिन मैं समाधान मिल गया है होना करने के लिए:

NSMutableArray *array = (__bridge NSMutableArray*) info; 

//AND 

CGPathApply(path, (__bridge void*)pathPoints, _processPathElement); 

किसी को भी क्यों की व्याख्या कर सकते हैं इस काम करता है और इस बात की पुष्टि नहीं हैं (/ कर रहे हैं) है कि किसी भी मेमोरी लीक मैं आभारी होगी

+1

मेरा उत्तर टाइप करते समय मुझे यह याद आया (इसलिए मुझे नए उत्तरों के बारे में सूचित नहीं किया गया)। इसके लिए तर्क के लिए ऊपर देखें। – WDUK

संबंधित मुद्दे