সুইফট: রেফারেন্স দিয়ে অ্যারে পাস করবেন?


125

আমি আমার সুইফট প্রেরণ করতে ইচ্ছুক Array account.chatsথেকে chatsViewController.chatsরেফারেন্স দ্বারা (তাই যখন আমি একটি চ্যাট যোগ করুন যে account.chats, chatsViewController.chatsএখনও পয়েন্ট account.chats)। অর্থাত্, account.chatsপরিবর্তনগুলির দৈর্ঘ্য যখন আমি সুইফট দুটি অ্যারে পৃথক করতে চাই না ।


1
আমি শেষ পর্যন্ত মাত্র উপার্জন accountএকটি বিশ্বব্যাপী পরিবর্তনশীল এবং সংজ্ঞা chatsসম্পত্তির ChatsViewControllerহিসাবে: var chats: [Chat] { return account.chats }
ma11 শেই 28

উত্তর:


72

সুইফটে স্ট্রাক্টগুলি মান দ্বারা পাস হয় তবে আপনি inoutআপনার অ্যারে সংশোধন করতে সংশোধকটি ব্যবহার করতে পারেন (নীচের উত্তরগুলি দেখুন)। ক্লাসগুলি রেফারেন্স দিয়ে পাস হয়। Arrayএবং Dictionaryসুইফটে স্ট্রাক্ট হিসাবে প্রয়োগ করা হয়।


2
অ্যারেটি সুইফটে মান দ্বারা অনুলিপি করা / পাস করা হয় না - এটি নিয়মিত কাঠামোর তুলনায় সুইফটে খুব আলাদা আচরণ করে। দেখুন stackoverflow.com/questions/24450284/...
বুন

14
@ বুন অ্যারে এখনও শব্দার্থবিজ্ঞানের সাথে অনুলিপি / পাস-বাই-মান দিয়ে গেছে তবে কেবল COW ব্যবহারের জন্য অনুকূলিত হয়েছে ।
eonil

4
এবং আমি ব্যবহারের প্রস্তাব দিচ্ছি না NSArrayকারণ NSArrayএবং সুইফ্ট অ্যারেতে সূক্ষ্ম শব্দার্থক পার্থক্য রয়েছে (যেমন রেফারেন্স-টাইপ), এবং এটি আপনাকে সম্ভবত আরও বাগগুলিতে নিয়ে যায়।
eonil

1
এটি আমাকে মারাত্মকভাবে হত্যা করছিল। জিনিসগুলি যেভাবে কাজ করে না সে সম্পর্কে আমি মাথা ঘুরছিলাম।
খুনশান

2
inoutস্ট্রাক্টসের সাথে ব্যবহার করলে কী হবে ?
অ্যালস্টন

137

ফাংশন প্যারামিটার অপারেটরের জন্য আমরা ব্যবহার করি: একটি প্যারামিটার ধ্রুবক তৈরি করতে

যাক (এটি ডিফল্ট অপারেটর, সুতরাং আমরা লেট বাদ দিতে পারি ) (এর অর্থ আমরা এমনকি স্থানীয় অনুলিপিও সংশোধন করতে পারি না);

Var এটা পরিবর্তনশীল (আমরা এটিতে স্থানীয়ভাবে পরিবর্তন করতে পারেন, কিন্তু এটা অভ্যস্ত বহিরাগত পরিবর্তনশীল যে ফাংশন প্রেরণ করা হয়েছে প্রভাবিত) প্রণয়ন; এবং

এটিকে আউট-আউট প্যারামিটার হিসাবে তৈরি করতে। ইন-আউট মানে প্রকৃতপক্ষে রেফারেন্সের মাধ্যমে ভেরিয়েবল পাস করা, মান দ্বারা নয়। এবং কেবলমাত্র রেফারেন্সের মাধ্যমে মান গ্রহণ করা নয়, রেফারেন্সের মাধ্যমে এটি পাস করার জন্যও এটি যথাযথ পরিবর্তে & - দিয়ে পাস করা প্রয়োজনfoo(&myVar)foo(myVar)

সুতরাং এটি এর মতো করুন:

var arr = [1, 2, 3]

func addItem(inout localArr: [Int]) {
    localArr.append(4)
}

addItem(&arr)    
println(arr) // it will print [1, 2, 3, 4]

সঠিকভাবে বলতে গেলে এটি কেবল একটি রেফারেন্সই নয়, তবে বাহ্যিক ভেরিয়েবলের জন্য একটি সত্যিকারের উপাধি, সুতরাং আপনি কোনও চলক প্রকারের সাথে যেমন একটি কৌশল করতে পারেন, উদাহরণস্বরূপ পূর্ণসংখ্যার সাথে (আপনি এটিতে নতুন মান নির্ধারণ করতে পারেন), যদিও এটি একটি নাও হতে পারে ভাল অনুশীলন এবং এটি এর মতো আদিম ডেটা সংশোধন করতে বিভ্রান্তিকর হতে পারে।


11
এটি অনুলিপি করা হয়নি এমন উদাহরণস্বরূপ ভেরিয়েবল হিসাবে অ্যারে কীভাবে ব্যবহার করবেন তা সত্যই ব্যাখ্যা করে না।
মাতেজ উক্মার

2
আমি ভেবেছিলাম ইনট আউট কোনও অস্থায়ীতে অ্যারের অনুলিপি করতে এবং তারপরে এটি ফাংশন থেকে বেরিয়ে আসার পথে পুনরায় সেট করার জন্য একটি গিটার এবং একটি সেটটার ব্যবহার করেছিল - যেমন এটি অনুলিপিগুলি
ডাম্বলডেড

2
আসলে ইন-আউট কপিরাইট অনুলিপি ব্যবহার করে বা মান ফলাফলের মাধ্যমে কল করে। যাইহোক, একটি অপ্টিমাইজেশন হিসাবে এটি রেফারেন্স দ্বারা ব্যবহার করতে পারে। "একটি অপ্টিমাইজেশন হিসাবে, যখন আর্গুমেন্টটি মেমরির কোনও দৈহিক ঠিকানায় সংরক্ষণ করা একটি মান হয়, তখন একই মেমরির অবস্থানটি ফাংশন বডির ভিতরে এবং বাইরে উভয় ক্ষেত্রেই ব্যবহৃত হয় The অনুকূলিত আচরণটি রেফারেন্স দ্বারা কল হিসাবে পরিচিত; এটি সমস্ত প্রয়োজনীয়তা পূরণ করে ies অনুলিপি করার ওভারহেড অপসারণ করার সময় অনুলিপি অনুলিপি মডেল। "
টড কানিংহাম

11
সুইফ্ট 3-এ, inoutঅবস্থান পরিবর্তন হয়েছে, অর্থাৎfunc addItem(localArr: inout [Int])
এলকুইমিস্ট

3
এছাড়াও, varফাংশন প্যারামিটার বৈশিষ্ট্যের জন্য আর উপলব্ধ নেই।
elquimista

23

নিজেকে এমন একটি সংজ্ঞা দিন BoxedArray<T>যা Arrayইন্টারফেস প্রয়োগ করে তবে সমস্ত ফাংশন একটি সঞ্চিত সম্পত্তিতে অর্পণ করে। যেমন

class BoxedArray<T> : MutableCollection, Reflectable, ... {
  var array : Array<T>

  // ...

  subscript (index: Int) -> T { 
    get { return array[index] }
    set(newValue) { array[index] = newValue }
  }
}

BoxedArrayআপনি যে কোনও জায়গাতেই ব্যবহার করুন Array। একটি উইলকে BoxedArrayরেফারেন্স দ্বারা নির্ধারণ করা, এটি একটি শ্রেণি, এবং এইভাবে Arrayইন্টারফেসের মাধ্যমে সঞ্চিত সম্পত্তিতে পরিবর্তনগুলি সমস্ত রেফারেন্সের জন্য দৃশ্যমান হবে।


কিছুটা ভীতিজনক সমাধান :) - ঠিক মার্জিত নয় - তবে মনে হয় এটি কার্যকর হবে।
মতেজ উম্মার

ঠিক আছে, 'রেফারেন্স শব্দার্থ দ্বারা পাস' পেতে 'NSArray ব্যবহার করুন' এ ফিরে যাওয়ার চেয়ে এটি অবশ্যই ভাল!
GoZoner

13
ক্লাসের পরিবর্তে অ্যারেটিকে স্ট্রাক্ট হিসাবে সংজ্ঞায়িত করার অনুভূতি হ'ল ভাষা নকশা ভুল।
মতেজ উম্মার

আমি রাজী. এমন Stringঘৃণাও রয়েছে যেখানে বিটিউটের একটি সাব Anyটাইপ থাকে যদি আপনি import Foundationতারপরে Stringএকটি সাব টাইপ হয়ে যান AnyObject
GoZoner

19

সুইফ্ট সংস্করণগুলির 3-4- এর জন্য (এক্সকোড 8-9), ব্যবহার করুন

var arr = [1, 2, 3]

func addItem(_ localArr: inout [Int]) {
    localArr.append(4)
}

addItem(&arr)
print(arr)

3

কিছুটা এইরকম

var a : Int[] = []
func test(inout b : Int[]) {
    b += [1,2,3,4,5]
}
test(&a)
println(a)

???


3
আমি মনে করি যে প্রশ্নটি দুটি ভিন্ন বস্তুর বৈশিষ্ট্য একই অ্যারে নির্দেশ করার জন্য একটি উপায় চাইছে। যদি এটি হয় তবে কান এর উত্তর সঠিক: একজনকে অবশ্যই একটি শ্রেণিতে অ্যারেটি আবৃত করতে হবে, বা এনএসআরাই ব্যবহার করা উচিত।
ওয়েস ক্যাম্পেইগনে

1
ঠিক আছে, আউটআউট কেবল ফাংশন বডি (কোনও ক্লোজার আচরণ নয়) এর আজীবন কাজ করে
খ্রিস্টান ডায়েটরিচ

গৌণ নিট: এটি func test(b: inout [Int])... সম্ভবত এটি একটি পুরানো বাক্য গঠন; আমি কেবল ২০১ 2016 সালে সুইফটে উঠলাম এবং এই উত্তরটি ২০১৪ থেকে তাই সম্ভবত জিনিসগুলি আলাদা হত?
রায় তোয়াল

2

আর একটি বিকল্প হ'ল অ্যারের গ্রাহককে প্রয়োজনমতো মালিকের কাছে এটি জিজ্ঞাসা করা। উদাহরণস্বরূপ, এর লাইন বরাবর কিছু:

class Account {
    var chats : [String]!
    var chatsViewController : ChatsViewController!

    func InitViewController() {
        chatsViewController.getChats = { return self.chats }
    }

}

class ChatsViewController {
    var getChats: (() -> ([String]))!

    func doSomethingWithChats() {
        let chats = getChats()
        // use it as needed
    }
}

তারপরে আপনি অ্যাকাউন্ট শ্রেণীর অভ্যন্তরে অ্যারেটিকে যতটা পছন্দ পরিবর্তন করতে পারেন। মনে রাখবেন যে আপনি যদি ভিউ কন্ট্রোলার ক্লাস থেকে অ্যারেটি সংশোধন করতে চান তবে এটি আপনাকে সাহায্য করবে না।


0

ব্যবহার inoutকরা একটি সমাধান তবে এটি আমার কাছে খুব দ্রুত বোধ করে না কারণ অ্যারেগুলি মান ধরণের। স্টাইলিস্টিকভাবে আমি ব্যক্তিগতভাবে পরিবর্তিত অনুলিপিটি পছন্দ করতে পছন্দ করি:

func doSomething(to arr: [Int]) -> [Int] {
    var arr = arr
    arr.append(3) // or likely some more complex operation
    return arr
}

var ids = [1, 2]
ids = doSomething(to: ids)
print(ids) // [1,2,3]

1
এই ধরণের জিনিসটির একটি কার্যকারিতা রয়েছে। এটি কেবলমাত্র মূল অ্যারেটি সংশোধন করতে একটি ট্যাড বিট কম ফোনের ব্যাটারি ব্যবহার করে :)
ডেভিড রেক্টর

আমি শ্রদ্ধার সাথে একমত। এই ক্ষেত্রে কল সাইটে পাঠযোগ্যতা সাধারণত পারফরম্যান্স হিটকে হ্রাস করে। অপরিবর্তনীয় কোড দিয়ে শুরু করুন এবং তারপরে এটিকে পরবর্তীতে পরিবর্তনীয় করে অনুকূলিত করুন। এমন বৃহত অ্যারে রয়েছে যেখানে আপনি সঠিক আছেন তবে বেশিরভাগ অ্যাপে এটি 0.01% প্রান্তের ক্ষেত্রে case
টডএইচ

1
আমি জানি না আপনি কার সাথে একমত নন। অ্যারের অনুলিপি করার জন্য একটি পারফরম্যান্স পেনাল্টি রয়েছে এবং কম পারফরম্যান্স অপারেশনগুলিতে বেশি সিপিইউ ব্যবহার করা হয় এবং এর ফলে আরও ব্যাটারি রয়েছে। আমি মনে করি আপনি ধরে নিয়েছেন যে আমি বলছিলাম এটি একটি ভাল সমাধান, যা আমি ছিল না। আমি নিশ্চিত করছিলাম যে কোনও তথ্য পছন্দ করে নেওয়ার জন্য লোকদের কাছে সমস্ত তথ্য উপস্থিত রয়েছে।
ডেভিড রেক্টর

1
হ্যাঁ, আপনি সঠিক, আউট আউট এর চেয়ে বেশি দক্ষ কোনও প্রশ্ন নেই। আমি ভেবেছিলাম আপনি পরামর্শ দিচ্ছেন যে inoutএটি সর্বজনীনভাবে ভাল কারণ এটি ব্যাটারি সঞ্চয় করে। যার জন্য আমি বলব যে এই সমাধানের পাঠযোগ্যতা, অপরিবর্তনযোগ্যতা এবং থ্রেড সুরক্ষা সর্বজনীনভাবে আরও ভাল এবং ইন-আউট কেবলমাত্র সেই বিরল ক্ষেত্রেই অপ্টিমাইজেশন হিসাবে ব্যবহার করা উচিত যেখানে ব্যবহারের ক্ষেত্রে এটি পরোয়ানা দেয়।
টোডএইচ

0

একটি NSMutableArrayবা একটি ব্যবহার করুনNSArray , যা ক্লাস হয়

এইভাবে আপনার কোনও মোড়ক লাগানোর দরকার নেই এবং সেতুটি বিল্ডটি ব্যবহার করতে পারেন

open class NSArray : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.