2015-12-27 16 views
6

में सरणी के संदर्भ को संग्रहीत करना मैं किसी ऑब्जेक्ट को एक सरणी पास करना चाहता हूं और इस सरणी का संदर्भ संग्रहीत करना चाहता हूं। मैं इस वस्तु के भीतर इस सरणी को संशोधित करने में सक्षम होना चाहता हूं और यह सुनिश्चित कर सकता हूं कि यह हर जगह संशोधित हो।स्विफ्ट

यहाँ है कि मैं क्या पूरा करने के लिए (कैसे कोड काम नहीं करता है)

class Foo { 
    var foo : Array<Int> 

    init(foo: Array<Int>) { 
     self.foo = foo 
    } 

    func modify() { 
     foo.append(5) 
    } 
} 

var a = [1,2,3,4] 
let bar = Foo(a) 
bar.modify() 
print(a) // My goal is that it will print 1,2,3,4,5 

मेरे निष्कर्ष अब तक

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

बी नहीं देखा जाएगा में यह से कुछ भी हटाना) मैं एक समारोह पैरामीटर पर inout उपयोग कर सकते हैं। यह मुझे इस फ़ंक्शन के भीतर संशोधित करने की अनुमति देगा। हालांकि, जैसे ही मैं इसे किसी ऑब्जेक्ट सदस्य को असाइन करने का प्रयास करूंगा, मुझे फिर से ए)

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

क्या कुछ और है? क्या मुझे कुछ स्विफ्ट निर्माण याद आ रहा है जो मुझे ऐसा करने की अनुमति देता है?

+0

आप इसे "ए" को निरंतर घोषित करने की अपेक्षा कैसे करेंगे? इसके अलावा आपको इनआउट पैरामीटर का उपयोग करके इसे पास करना होगा और इसे "&" उपसर्ग –

+0

के साथ अपनी विधि में पास करना होगा, मैं एक var होने के लिए "ए" को बदल सकता हूं। पैरामीटर का उपयोग करना और इनआउट पैरामीटर केवल तभी काम करेगा जब मैं सरणी को उस विधि में संशोधित करता हूं जिस पर इसे पारित किया गया था। जैसे ही मैं "self.foo = foo" करता हूं, यह काम करना बंद कर देगा। Self.foo का अर्थ संशोधन "ए" –

+0

को प्रभावित नहीं करेगा, इसे var के रूप में घोषित करें, var foo परिभाषित करें: [int] = [] {willSet (newArray) {a = newArray}} –

उत्तर

0

the Swift Programming Language से,

Structures are always copied when they are passed around in your code, and do not use reference counting.

आप सरणी चर की सामग्री की जांच करते हैं, तो आपको लगता है कि वास्तव में संलग्न देखेंगे काम करता है:

 
class Foo { 
    var foo : Array 

    init(_ foo: Array) { 
    self.foo = foo 
    } 

    func modify() { 
    foo.append(5) 
    } 

    func printFoo() { 
    print("self.foo: \(foo)") 
    } 
} 

let a = [1,2,3,4] 
let bar = Foo(a) 
bar.modify() 
bar.printFoo() 
print("a: \(a)") 

 
self.foo: [1, 2, 3, 4, 5] 
a: [1, 2, 3, 4] 

का उत्पादन आपने सी लिया है का विकल्प, के संदर्भ में नहीं।

+0

हां। मुझे पता है कि यह वस्तु के अंदर एक सरणी में संलग्न होगा। मेरा लक्ष्य यह सुनिश्चित करना है कि एक सरणी (इस मामले में "ए") जिसे ऑब्जेक्ट में पास किया गया था, भी संशोधित किया गया है। तो, मैं इसे प्रिंट करने के लिए एक तरीका ढूंढ रहा हूं [1,2,3,4,5] –

+0

मुझे यहां क्या करने की कोशिश कर रहे हैं, इसके बारे में बहुत सावधान रहना होगा। प्रत्येक बार जब आप किसी आंतरिक सरणी चर में परिवर्तन करते हैं, तो बाहरी सरणी की सामग्री को डुप्लिकेट करना चाहते हैं, तो आप 'encapsulation' की अवधारणा को कम कर रहे हैं। क्या आंतरिक सरणी चर में हेरफेर करना बेहतर नहीं होगा और फिर आवश्यक होने पर इसका पर्दाफाश करना होगा? मुझे लगता है कि लियो का जवाब संपत्ति पर्यवेक्षकों की शक्ति का उपयोग करके चालाक है लेकिन जब भी सरणी तत्व बदल जाता है तो यह पूरे सरणी की प्रतिलिपि बनाता है। – timbo

+0

मैं encapsulation के बारे में असहमत हूं। मान लें कि हम गुजर रहे थे और फू और फू पर ऑब्जेक्ट कुछ विधि बुला रहे थे जो इस ऑब्जेक्ट सामग्री को संशोधित करेंगे। यह encapsulation तोड़ नहीं होगा। आमतौर पर ऐरे ऑब्जेक्ट बोल रहा है। हम इस पर एक विधि (संलग्न) बुला रहे हैं। तो, इसका इलाज किसी भी अलग नहीं किया जाना चाहिए। –

4

आप इस के लिए एक NSArray या NSMutableArray का उपयोग करें ताकि कोई भी काम एक प्रतिलिपि बनाने जाएगा, क्योंकि स्विफ्ट सरणी मूल्य प्रकार के होते हैं होगा।

0

एक इसलिए एक निरंतर घोषित किया जाता है बदला नहीं जा सकता। यदि आप किसी की सामग्री को संशोधित करने की योजना बना रहे हैं, तो इसे एक चर के रूप में घोषित करें। i.e.,

var a = [1,2,3,4] 
+0

आप सही हैं। एक "var" के रूप में घोषित किया जाना चाहिए। हालांकि, समस्या उस से अधिक गहरी है। –

1

आप स्विफ्ट्स (बहुत गैर-स्विफ्ट) UnsafeMutablePointer का उपयोग कर सकते हैं।

के बाद से (अपने पद से) व्यवहार सरणियों के लिए संदर्भ वास्तव में लग भरोसा नहीं किया जा सकता है, बजाय वर्ग भीतरी सरणी foo के लिए एक UnsafeMutablePointer साथी के साथ-साथ किसी भी "बाहरी" सरणियों कि आप foo से आबद्ध किया जाना चाहते हैं रखने के , इस अर्थ में कि वे दोनों सिर्फ स्मृति में एक ही पते पर संकेत दिए गए हैं में।

class Foo { 
    var foo : [Int] 
    var pInner: UnsafeMutablePointer<Int> 

    init(foo: [Int]) { 
     pInner = UnsafeMutablePointer(foo) 
     self.foo = Array(UnsafeBufferPointer(start: pInner, count: foo.count)) 
    } 

    func modify(inout pOuter: UnsafeMutablePointer<Int>) { 
     foo.append(5) // <-- foo gets new memory adress 
     pInner = UnsafeMutablePointer(foo) 
     pOuter = pInner 
    } 
} 

var a = [1,2,3,4] // first alloc in memory 
var pOuter: UnsafeMutablePointer<Int> = UnsafeMutablePointer(a) 
var bar = Foo(foo: a) // 'bar.foo' now at same address as 'a' 
print(bar.foo) // [1,2,3,4] 
bar.modify(&pOuter) // -> [1,2,3,4,5] 
a = Array(UnsafeBufferPointer(start: pOuter, count: bar.foo.count)) 

/* Same pointer adress, OK! */ 
print(bar.pInner) 
print(pOuter) 

/* Naturally same value (same address in memory) */ 
print(bar.foo) 
print(a) 

पॉइंटर्स हालांकि खतरनाक हो सकते हैं (इसलिए फिटिंग प्रकार का नाम), और फिर, बहुत ही तेज़। वैसे भी ...

/* When you're done: clear pointers. Usually when using 
    pointers like these you should take care to .destroy 
    and .dealloc, but here your pointers are just companions 
    to an Array property (which has a pointer an reference 
    counter itself), and the latter will take care of the 
    objects in memory when it goes out of scope.   */ 
bar.pInner = nil 
pOuter = nil 

अब, क्या होता है जब या तो a या foo क्षेत्र से बाहर चला जाता है, यह चर कि क्षेत्र से बाहर नहीं हैं टूट जाएगा, या स्विफ्ट कुछ चालाक संदर्भ गिनती है कि एक स्मृति पते का एहसास में क्या है भी उपयोग में है ? मैंने इसकी जांच नहीं की है, लेकिन उसमें खुद को शामिल करने के लिए स्वतंत्र महसूस करें।

+0

दिलचस्प। आपको प्रत्येक विधि में पॉटर पास करना होगा जो आंतरिक सरणी को संशोधित करता है। –

+0

हाँ यह सबसे तेज़ या सुंदरतम समाधान नहीं है, लेकिन आपको यह सुनिश्चित करने के लिए पता चलेगा कि आपके सरणी न केवल "हर जगह संशोधित" हैं, बल्कि वास्तव में, स्मृति में समान सरणी हैं। साथ ही, ध्यान दें कि बिंदु ए के लिए) आपके उत्तर में: त्वरित रूप से मूल्यों के साथ सरणी प्रारंभ करते समय आपको आवश्यक स्थान आवंटित करता है। यदि आप कोई मान जोड़ते हैं, तो उसे पूर्ण सरणी + नए तत्व के लिए जगह आवंटित करने की आवश्यकता है, फिर "पुरानी" सरणी + नई प्रविष्टि को नई जगह पर कॉपी करें, और अंततः पुरानी जगह को छोड़ दें। यही कारण है कि ऐसा लगता है कि यह यादृच्छिक रूप से संदर्भ/मूल्य प्रति का उपयोग कर रहा है। – dfri