2014-10-22 13 views
6

पर GPUImage फ़िल्टर उप-वर्गों को पोर्ट करना मैं उद्देश्य-सी से स्विफ्ट तक एक ऐप पोर्ट करने का प्रयास कर रहा हूं, लेकिन मुझे GPUImageFilter के उप-वर्ग के साथ समस्याएं आ रही हैं।स्विफ्ट

Obj सी में, GPUImageFilter उपवर्गीकरण और एक अलग टुकड़ा शेडर का उपयोग कर के रूप में आसान के रूप में

- (id)init; 
{ 
    NSString *fragmentShaderPathname = [[NSBundle mainBundle] pathForResource:@"TestShader" ofType:@"fsh"]; 
    NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragmentShaderPathname encoding:NSUTF8StringEncoding error:nil]; 

    if (!(self = [super initWithFragmentShaderFromString:fragmentShaderString])) 
    { 
     return nil; 
    } 

    return self; 
} 

मैं कैसे स्विफ्ट में ऐसा करने को समझ नहीं सकता। यह मेरा नया प्रारंभकर्ता है:

override init() { 
    let fragmentShaderPathname = NSBundle.mainBundle().pathForResource("TestShader", ofType: "fsh")! 
    let fragmentShaderString = NSString(contentsOfFile: fragmentShaderPathname, encoding: NSUTF8StringEncoding, error: nil) 

    super.init(fragmentShaderFromString: fragmentShaderString) 
} 

जैसे ही यह कहा जाता हो जाता है इस त्रुटि संदेश के साथ ऐप्लिकेशन क्रैश: /Users/peterwunder/Documents/XCode/welp/welp/GPUImageTestFilter.swift: 12: 7: fatal error: use of unimplemented initializer 'init(vertexShaderFromString:fragmentShaderFromString:)' for class 'welp.GPUImageTestFilter'

क्या मैं गलत कर रहा हूँ?

उत्तर

7

दिलचस्प समस्या! स्विफ्ट और ऑब्जेक्टिव-सी के बीच प्रारंभ में अंतर के कारण आप ट्रिप हो रहे हैं। यदि GPUImageFilter कक्षा स्विफ्ट में लिखी गई थी, तो संकलक आपको यह सेटअप नहीं करने देगा, लेकिन चूंकि आप & मिलान कर रहे हैं, यह रनटाइम तक शिकायत नहीं करता है।

  1. आप let myFilter = CustomGPUImageFilter()
  2. आपका init() भार फोन शेडर स्ट्रिंग और कॉल super.init(fragmentShaderString: "foo")
  3. GPUImageFilter.init(fragmentShaderString:) कॉल [self initWithVertexShaderFromString:@"bar" fragmentShaderFromString:@"foo"]: यहाँ क्या हो रहा है, जब आप अपने उपवर्ग का दृष्टांत करने की कोशिश है।

उस अंतिम पंक्ति में self किस प्रकार का है? यदि आप अपने उप-वर्ग के प्रारंभकर्ता से कॉल कर रहे हैं, तो self का प्रकार वास्तव में आपके उप-वर्ग का है: CustomGPUImageFilter। तो प्रारंभकर्ता जिसे बुलाया जाता है वास्तव में आपके उप-वर्ग पर है। यह समस्या क्यों है?

दुर्भाग्य से, स्विफ्ट वर्गों स्वचालित रूप से अगर वे अपने स्वयं के नामित initializers, जो कि आपके init() है परिभाषित उनके सुपर क्लास से initializers वारिस नहीं है। तो रनटाइम CustomGPUImageFilter.init(vertexShaderFromString:fragmentShaderFromString:) पर कॉल करने का प्रयास करता है, इसे नहीं मिला, और उस त्रुटि संदेश के साथ दुर्घटनाग्रस्त हो जाता है।

खुशी से, फिक्स काफी सरल है। यदि आप अपने प्रारंभकर्ता को convenience init के रूप में चिह्नित करते हैं, तो आप अब नामित प्रारंभकर्ता को परिभाषित नहीं करेंगे, जिसका अर्थ है कि आपका सबक्लास GPUImageFilter से प्रारंभकर्ताओं का उत्तराधिकारी होगा। फिर ऊपर चरण 3 में, रनटाइम आपके उप-वर्ग पर विरासत प्रारंभकर्ता को मिलेगा और किसी समस्या के बिना निष्पादित करेगा। ध्यान दें कि आप super.init... के बजाय self.init... कॉल करने के लिए की आवश्यकता होगी:

convenience override init() { 
    let fragmentShaderPathname = NSBundle.mainBundle().pathForResource("TestShader", ofType: "fsh")! 
    let fragmentShaderString = NSString(contentsOfFile: fragmentShaderPathname, encoding: NSUTF8StringEncoding, error: nil) 

    self.init(fragmentShaderFromString: fragmentShaderString) 
} 

इस प्रक्रिया के बारे में अधिक के लिए, स्विफ्ट दस्तावेज में class inheritance and initialization पर अनुभाग पढ़ें। प्रक्रिया महत्वपूर्ण उद्देश्य-सी से अलग है।

+1

डांग। मुझे उम्मीद थी कि चीजें मौलिक रूप से अलग होंगी, लेकिन मुझे _this_ की उम्मीद नहीं थी। : डी धन्यवाद! –