ইন-লুপটিতে ingালাই টাইপ করুন


116

আমার এই ইন-ইন লুপটি রয়েছে:

for button in view.subviews {
}

এখন আমি চাই বোতামটি একটি কাস্টম শ্রেণিতে কাস্ট করা যাতে আমি এর বৈশিষ্ট্যগুলি ব্যবহার করতে পারি।

আমি এটি চেষ্টা করেছি: for button in view.subviews as AClass

তবে এটি কাজ করে না এবং আমাকে একটি ত্রুটি দেয়:'AClass' does not conform to protocol 'SequenceType'

এবং আমি এটি চেষ্টা করেছি: for button:AClass in view.subviews

কিন্তু উভয়ই কাজ করে না।


কীভাবেfor button in view.subviews as [AClass]
ওয়াকওমা

2
হাহা আমি এটা ভেবে দেখিনি, অবশ্যই এটি ভালভাবে এস্লাসের অ্যারেতে ফেলে দেওয়া ভাল, ধন্যবাদ মানুষ। আপনি এটি সম্পর্কে একটি উত্তর দিতে পারেন যাতে আমি আপনাকে কিছু প্রতিনিধি দিতে পারি :)
আরবিটর

উত্তর:


173

সুইফট 2 এবং তারপরের জন্য :

সুইফট 2 লুপের জন্য কেস প্যাটার্ন যুক্ত করে , এটি লুপের জন্য কাস্ট টাইপ করা আরও সহজ এবং নিরাপদ করে :

for case let button as AClass in view.subviews {
    // do something with button
}

আপনি সুইফট ১.২ এবং এর আগে যা করতে পারেন তার থেকে এটি কেন ভাল ? কারণ কেস প্যাটার্নগুলি আপনাকে সংগ্রহের বাইরে আপনার নির্দিষ্ট ধরণের বাছাই করতে দেয়। এটি কেবলমাত্র আপনি যে ধরণের সন্ধান করছেন সেটির সাথেই এটি মেলে, সুতরাং আপনার অ্যারেতে যদি মিশ্রণ থাকে তবে আপনি কেবল একটি নির্দিষ্ট ধরণের ক্ষেত্রেই পরিচালনা করতে পারেন।

উদাহরণ স্বরূপ:

let array: [Any] = [1, 1.2, "Hello", true, [1, 2, 3], "World!"]
for case let str as String in array {
    print(str)
}

আউটপুট:

Hello
World!

জন্য সুইফট 1.2 :

এই ক্ষেত্রে, আপনি ingালাই view.subviewsকরছেন এবং করছেন না button, সুতরাং আপনার পছন্দসই অ্যারেটিতে এটি খালি করা দরকার:

for button in view.subviews as! [AClass] {
    // do something with button
}

দ্রষ্টব্য: অন্তর্নিহিত অ্যারে প্রকারটি যদি না হয় তবে এটি [AClass]ক্রাশ হবে। এটিই আপনাকে জানিয়ে !দিচ্ছে as!। আপনি যদি এই ধরণের সম্পর্কে নিশ্চিত না হন তবে আপনি as?alচ্ছিক বাঁধার পাশাপাশি শর্তসাপেক্ষ কাস্ট ব্যবহার করতে পারেন if let:

if let subviews = view.subviews as? [AClass] {
    // If we get here, then subviews is of type [AClass]
    for button in subviews {
        // do something with button
    }
}

জন্য সুইফট 1.1 এবং তার আগে:

for button in view.subviews as [AClass] {
    // do something with button
}

দ্রষ্টব্য: সাবভিউগুলি সমস্ত ধরণের না হলে এটি ক্রাশ হবে AClass। উপরে তালিকাভুক্ত নিরাপদ পদ্ধতিটি সুইফটের পূর্ববর্তী সংস্করণগুলির সাথেও কাজ করে।


আমার মতো অন্যদের জন্য কেবল একটি নোট যারা প্রথমে এটি পায় নি - শ্রেণীর নামটি [ ]বন্ধনীগুলির মধ্যে এই উদাহরণটির মতো ঠিক যেতে হবে । হতে পারে এটি কেবলমাত্র আমি কিন্তু আমি ভেবেছিলাম এটি প্রথমে কোড নমুনায় কেবল একটি ফর্ম্যাটিং পছন্দ ছিল :) আমি মনে করি এটি এটি কারণ আমরা একটি অ্যারেতে কাস্টিং করছি।

@kmcgrady এটি এর [Class]চেয়ে অনেক ভাল দেখাচ্ছে Array<Class>
আরবিটর

কৌতূহলের বাইরে, লুপের ভিতরে একাধিক কেস স্টেটমেন্ট করার কোনও উপায় আছে কি? EG যদি আমি বোতামগুলিতে একটি জিনিস করতে চাই, অন্যটি পাঠ্য ক্ষেত্রে?
রনলগ

125

এই বিকল্পটি আরও সুরক্ষিত:

for case let button as AClass in view.subviews {
}

বা দ্রুত উপায়:

view.subviews
  .compactMap { $0 as AClass }
  .forEach { .... }

1
বাহ্যিক castালাই না থাকায় এটি উত্তরের উত্তরের মতো মনে হচ্ছে।
প্যাট্রিক

1
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। সেরা এক এবং সঠিক এক!
থমস কলমন

সঠিক উত্তর. সংক্ষিপ্ত এবং সহজ।
পাশান

4

আপনি একটি whereধারাও ব্যবহার করতে পারেন

for button in view.subviews where button is UIButton {
    ...
}

12
যেখানে ক্লজটি বুলিয়ান গার্ড, তবে buttonলুপের দেহের অভ্যন্তরের প্রকারটি দেয় না যা অন্যান্য সমাধানগুলির লক্ষ্য। সুতরাং এটি কেবল লুপের বডি চালিত করবে view.subviewsযার উপাদানগুলি সেগুলি UIButton, তবে যেমন AClass- স্পেসিফিক পদ্ধতিগুলিতে কল করার ক্ষেত্রে সহায়তা করে না button
জন হুইটলি

1
@ জন হুইটলি আপনি ঠিক আছেন যে whereকেবল প্রহরী এবং নিক্ষেপ করেন না।
edelaney05

whereআপনার ক্ষেত্রে কেবল বুলিয়ান গার্ডের প্রয়োজন হয় এমন ক্ষেত্রে (অনিচ্ছাকৃত) ক্ষেত্রে আরও মার্জিত এবং পাঠযোগ্য হতে পারে।
এসটিও

3

প্রদত্ত উত্তরগুলি সঠিক, আমি কেবল এটি একটি সংযোজন হিসাবে যুক্ত করতে চেয়েছিলাম।

ফোর্স কাস্টিং সহ লুপের জন্য ব্যবহার করার সময়, কোডটি ক্র্যাশ হয়ে যাবে (যেমন ইতিমধ্যে অন্যরা উল্লেখ করেছেন)।

for button in view.subviews as! [AClass] {
    // do something with button
}

তবে একটি আইফ-ক্লজ ব্যবহার না করে,

if let subviews = view.subviews as? [AClass] {
    // If we get here, then subviews is of type [AClass]
    ...
}

আরেকটি উপায় হ'ল কিছুক্ষণের লুপটি ব্যবহার করা:

/* If you need the index: */
var iterator = view.subviews.enumerated().makeIterator()
while let (index, subview) = iterator.next() as? (Int, AClass) {
    // Use the subview
    // ...
}

/* If you don't need the index: */
var iterator = view.subviews.enumerated().makeIterator()
while let subview = iterator.next().element as? AClass {
    // Use the subview
    // ...
}

যা আরও সুবিধাজনক বলে মনে হচ্ছে অ্যারের কিছু উপাদান (তবে সমস্ত নয়) টাইপ হতে পারে AClass

যদিও আপাতত (সুইফ্ট 5 হিসাবে), আমি ক্ষেত্রে-লুপের জন্য যেতে চাই:

for case let (index, subview as AClass) in view.subviews.enumerated() {
    // ...
}

for case let subview as AClass in view.subviews {
    // ...
}

এখানে কেবল একটি সন্দেহ ... সুইফ্ট গণিত ফাংশনটি এখানে পুনরাবৃত্তিগুলি / লুপ সম্পাদন করে .. পারফরম্যান্স হারাতে কেবল রিফ্যাক্টরিং ভাবা দুর্দান্ত হবে না ... ধন্যবাদ
আম্বর কে

2

ভ্যাকোয়ামার দেওয়া উত্তরটি সুইফ্ট ১.০ এ সঠিক ছিল। এবং আর সুইফট ২.০ নিয়ে কাজ করে না।

যদি আপনি চেষ্টা করেন তবে আপনি এর মতো একটি ত্রুটি পাবেন:

'[যেকোনওজেক্ট]' '[এসক্লাস]' তে রূপান্তরযোগ্য নয়;

সুইফট ২.০ এ আপনার লিখতে হবে:

for button in view.subviews as! [AClass]
{
}

0

আপনি ingালাই সঞ্চালন করতে পারেন এবং এটি দিয়ে একই সময়ে নিরাপদ থাকতে পারেন:

for button in view.subviews.compactMap({ $0 as? AClass }) {

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