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


84

যখন একটি UIScrollView(বা এর উত্পন্ন শ্রেণি) স্ক্রল করছে, মনে হচ্ছে NSTimersস্ক্রোলটি শেষ না হওয়া পর্যন্ত যা চলছে সমস্তগুলি বিরতি হয়ে যায়।

এই কাছাকাছি পেতে একটি উপায় আছে? থ্রেডস? একটি অগ্রাধিকার সেটিং? কিছু?



সাত বছর পরে ... স্ট্যাকওভারফ্লো
a/

উত্তর:


202

সমাধান কার্যকর করার সহজ ও সহজ কাজটি হ'ল:

NSTimer *timer = [NSTimer timerWithTimeInterval:... 
                                         target:...
                                       selector:....
                                       userInfo:...
                                        repeats:...];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

4
UITrackingRunLoopMode হল মোড - এবং এর সর্বজনীন - আপনি বিভিন্ন টাইমার আচরণ তৈরি করতে ব্যবহার করতে পারেন।
টম অ্যান্ডারসেন

এটি পছন্দ করে, জিএলকেভিউ কনট্রোলারের সাথে মনোযোগের মতো কাজ করে। যখন ইউআইএসক্রোলভিউ প্রদর্শিত হবে তখনই নিয়ন্ত্রণের পংক্তিটি হ্যাঁ হ্যাঁ সেট করুন এবং বর্ণিত হিসাবে আপনার নিজস্ব টাইমার শুরু করুন। যখন স্ক্রোলভিউটি বরখাস্ত হয়ে যায় তখন এটি বিপরীত হয়! আমার আপডেট / রেন্ডার লুপ খুব ব্যয়বহুল নয়, যাতে এটি সাহায্য করতে পারে।
জেরোইন বোমা

4
অসাধারণ! আমি টাইমারটি নিষ্ক্রিয় করার সময় কি অপসারণ করতে হবে বা না? ধন্যবাদ
জ্যাকোপো পেঞ্জো

এটি স্ক্রোলিংয়ের জন্য কাজ করে তবে অ্যাপ্লিকেশন ব্যাকগ্রাউন্ডে গেলে টাইমার থামায়। উভয় অর্জনের জন্য কোন সমাধান?
পুলকিত শর্মা

23

যে কেউ সুইফট 3 ব্যবহার করেন

timer = Timer.scheduledTimer(timeInterval: 0.1,
                            target: self,
                            selector: aSelector,
                            userInfo: nil,
                            repeats: true)


RunLoop.main.add(timer, forMode: RunLoopMode.commonModes)

7
এর timer = Timer(timeInterval: 0.1, target: self, selector: aSelector, userInfo: nil, repeats: true)পরিবর্তে প্রথম কমান্ড হিসাবে কল করা ভাল Timer.scheduleTimer(), কারণ scheduleTimer()রানলুপে টাইমার যুক্ত করে এবং পরবর্তী কলটি একই রানলুপে যোগ করা হলেও ভিন্ন মোডের সাথে যুক্ত হয়। দু'বার একই কাজ করবেন না।
অ্যাসিড উজ্জ্বল

8

হ্যাঁ, পল ঠিক বলেছেন, এটি একটি রান লুপ ইস্যু। বিশেষত, আপনার এনএসআরনলুপ পদ্ধতিটি ব্যবহার করা দরকার:

- (void)addTimer:(NSTimer *)aTimer forMode:(NSString *)mode

7

এটি সুইফ্ট সংস্করণ।

timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: aSelector, userInfo: nil, repeats: true)
            NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)

6

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


11
এর জন্য অন্য থ্রেডের দরকার নেই, কাশিফের সাম্প্রতিক উত্তর দেখুন । আমি এটি চেষ্টা করেছি এবং এটি কোনও অতিরিক্ত থ্রেডের প্রয়োজন ছাড়াই কাজ করে।
অগ্রগামী

4
চড়ুইতে কামান গুলি চালানো। কোনও থ্রেডের পরিবর্তে, ডান রান লুপ মোডে টাইমারটি ঠিক করুন।
uliw साक्षी

4
আমি মনে করি নীচে কাশফের উত্তরটি সর্বোত্তম উত্তর হিসাবে এটি কেবল আপনার এই সমস্যাটি সমাধানের জন্য কোডের 1 লাইন যুক্ত করা দরকার।
দামেন মারফি

3

যে কেউ সুইফট 4 ব্যবহার করার জন্য:

    timer = Timer(timeInterval: 1, target: self, selector: #selector(timerUpdated), userInfo: nil, repeats: true)
    RunLoop.main.add(timer, forMode: .common)

2

tl; ডাঃ রানলুপটি স্ক্রোলিং করছে যাতে এটি আর কোনও ইভেন্ট হ্যান্ডেল করতে পারে না - আপনি নিজে নিজে টাইমার সেট না করে রাখুন যাতে রানওলাপ টাচ ইভেন্টগুলি পরিচালনা করে থাকে তখনও এটি ঘটতে পারে। অথবা বিকল্প সমাধান চেষ্টা করে জিসিডি ব্যবহার করুন


কোনও আইওএস বিকাশকারীকে অবশ্যই পড়তে হবে। প্রচুর জিনিস চূড়ান্তভাবে রানলুপের মাধ্যমে কার্যকর করা হয়।

অ্যাপলের ডক্স থেকে প্রাপ্ত ।

রান লুপ কী?

একটি রান লুপটি এর নামের মতো শোনা যায়। এটি আপনার থ্রেডটি প্রবেশ করে এবং আগত ইভেন্টগুলির প্রতিক্রিয়ায় ইভেন্ট হ্যান্ডলারগুলি চালাতে ব্যবহার করে

কীভাবে অনুষ্ঠানের বিতরণ ব্যাহত হয়?

কারণ আপনি যখন রান লুপটি চালান তখন টাইমার এবং অন্যান্য পর্যায়ক্রমিক ইভেন্টগুলি সরবরাহ করা হয় circum আপনি যখন লুপটি প্রবেশ করে এবং বারবার অ্যাপ্লিকেশন থেকে ইভেন্টগুলির অনুরোধ করে মাউস-ট্র্যাকিং রুটিন প্রয়োগ করেন তখনই এই আচরণের সাধারণ উদাহরণটি ঘটে। আপনার কোডটি সরাসরি ইভেন্টগুলি দখল করার কারণে অ্যাপ্লিকেশনটিকে সেই ঘটনাগুলিকে সাধারণত প্রেরণ করার পরিবর্তে সক্রিয় টাইমারগুলি আপনার মাউস-ট্র্যাকিং রুটিনটি প্রস্থান না করে এবং অ্যাপ্লিকেশনটিতে নিয়ন্ত্রণ ফিরে না পাওয়া পর্যন্ত অচল করে দিতে সক্ষম হবে।

রান লুপ কার্যকর হওয়ার মাঝখানে থাকলে টাইমারকে গুলি করা হলে কী হবে?

এটি আমাদের অনেক সময় লক্ষ্য না করেই প্রচুর সময় হয়। আমি বোঝাতে চাইছি আমরা টাইমারটি 10: 10: 10: 00 তে আগুন জ্বালিয়ে দিয়েছি, তবে রানলুপ একটি ইভেন্ট চালাচ্ছে যা 10: 10: 10: 05 অবধি গ্রহণ করে, তাই টাইমারটি বহিস্কার করা হয় 10: 10: 10: 06

একইভাবে, যদি রানার লুপটি কোনও হ্যান্ডলার রুটিন সম্পাদন করার মাঝামাঝি সময়ে থাকে তবে টাইমার তার হ্যান্ডলার রুটিনটি চালানোর জন্য রান লুপের মাধ্যমে পরবর্তী সময় পর্যন্ত অপেক্ষা করে। রান লুপটি যদি চলমান না থাকে তবে টাইমার কখনই গুলি চালায় না।

স্ক্রোলিং বা এমন কোনও কিছু যা রান টাইমটি ব্যস্ত রাখে যা আমার টাইমার সমস্ত সময় জ্বলতে থাকে?

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

আমি কীভাবে রানলুপসের মোড পরিবর্তন করতে পারি?

আপনি পারবেন না। ওএস আপনার জন্য কেবল নিজেকে পরিবর্তন করে। যেমন যখন ব্যবহারকারী ট্যাপ করেন, তারপরে মোডটি স্যুইচ করে eventTracking। ব্যবহারকারীর ট্যাপগুলি সমাপ্ত হলে মোডটি আবার ফিরে যায় default। আপনি যদি কোনও নির্দিষ্ট মোডে চালিত করতে চান তবে তা ঘটবে তা নিশ্চিত করা আপনার পক্ষে।


সমাধান:

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

ডিফল্টরূপে টাইমারগুলি trackingমোডে নির্ধারিত হয় না । সেগুলি নির্ধারিত:

একটি টাইমার তৈরি করে এবং এটি ডিফল্ট মোডে বর্তমান রান লুপের সময়সূচী করে ।

scheduledTimerনীচে এই আছে:

RunLoop.main.add(timer, forMode: .default)

আপনি যদি স্ক্রল করার সময় আপনার টাইমারটি কাজ করতে চান তবে আপনাকে অবশ্যই এটি করতে হবে:

let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self,
 selector: #selector(fireTimer), userInfo: nil, repeats: true) // sets it on `.default` mode

RunLoop.main.add(timer, forMode: .tracking) // AND Do this

বা কেবল করুন:

RunLoop.main.add(timer, forMode: .common)

চূড়ান্তভাবে উপরের একটিটির অর্থ হ'ল স্পর্শ ইভেন্টগুলি দ্বারা আপনার থ্রেড অবরুদ্ধ নয় । যা এর সমান:

RunLoop.main.add(timer, forMode: .default)
RunLoop.main.add(timer, forMode: .eventTracking)
RunLoop.main.add(timer, forMode: .modal) // This is more of a macOS thing for when you have a modal panel showing.

বিকল্প সমাধান:

আপনি আপনার টাইমারটির জন্য জিসিডি ব্যবহারের বিষয়ে বিবেচনা করতে পারেন যা আপনাকে রান কোড লুপ পরিচালনার সমস্যা থেকে আপনার কোড "রক্ষা" করতে সহায়তা করবে।

পুনরাবৃত্তি না করার জন্য কেবল ব্যবহার করুন:

DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
    // your code here
}

পুনরাবৃত্তি টাইমার ব্যবহারের জন্য:

কীভাবে ডিসপ্যাচসোর্সটাইমার ব্যবহার করবেন তা দেখুন


ড্যানিয়েল জলকুতের সাথে আমার যে আলোচনা হয়েছিল তার থেকে আরও গভীর খনন:

প্রশ্ন: জিসিডি (ব্যাকগ্রাউন্ড থ্রেড) যেমন একটি ব্যাকগ্রাউন্ড থ্রেডের asyncAfter কীভাবে রানলুপের বাইরে কার্যকর হবে? এগুলি থেকে আমার বুঝতে পারা যায় যে সমস্ত কিছুই রানলুপের মধ্যে কার্যকর করা উচিত

অগত্যা নয় - প্রতিটি থ্রেডের সর্বাধিক এক রান লুপ থাকে তবে থ্রেডের "মালিকানা" কার্যকর করার সমন্বয় করার কোনও কারণ না থাকলে শূন্য থাকতে পারে।

থ্রেডগুলি একটি ওএস স্তরের সাশ্রয়ী মূল্যের মূল্য যা আপনার প্রক্রিয়াটিকে একাধিক সমান্তরাল সম্পাদন প্রসঙ্গের মধ্যে এর কার্যকারিতা বিভক্ত করার ক্ষমতা দেয়। রান লুপগুলি একটি ফ্রেমওয়ার্ক-স্তরীয় সাশ্রয়ী মূল্যের সাশ্রয় যা আপনাকে একক থ্রেডে আরও বিভক্ত করতে দেয় যাতে এটি একাধিক কোড পাথের মাধ্যমে দক্ষতার সাথে ভাগ করা যায়।

সাধারণত আপনি যদি এমন কিছু প্রেরণ করেন যা থ্রেডে চালিত হয় তবে সম্ভবত এটির রানলুপ থাকবে না যদি না এমন কিছু কল আসে [NSRunLoop currentRunLoop]যা স্পষ্টতই একটি তৈরি করে।

সংক্ষেপে, মোডগুলি মূলত ইনপুট এবং টাইমারগুলির জন্য একটি ফিল্টার প্রক্রিয়া

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