একটি ব্যক্তিগত এপিআই ব্যবহার না করে বর্তমান প্রথম প্রতিক্রিয়াশীল পান


340

আমি এক সপ্তাহ আগে আমার অ্যাপ্লিকেশনটি জমা দিয়েছি এবং আজ ভয়ঙ্কর প্রত্যাখ্যান ইমেল পেয়েছি। এটি আমাকে বলে যে আমার অ্যাপ্লিকেশনটি গ্রহণ করা যাবে না কারণ আমি একটি সর্বজনীন এপিআই ব্যবহার করছি; বিশেষত, এটি বলে,

আপনার অ্যাপ্লিকেশনটিতে অন্তর্ভুক্ত থাকা অ-সর্বজনীন এপিআই হ'ল ফার্স্ট রিসপন্ডার।

এখন, আপত্তিজনক এপিআই কলটি এমন একটি সমাধান যা আমি এখানে এসওতে পেয়েছি:

UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
UIView   *firstResponder = [keyWindow performSelector:@selector(firstResponder)];

আমি পর্দায় বর্তমান প্রথম প্রতিক্রিয়াশীল কীভাবে পেতে পারি? আমি এমন একটি উপায় খুঁজছি যা আমার অ্যাপ্লিকেশনটিকে প্রত্যাখ্যান করবে না।


5
দর্শনগুলির দ্বারা পুনরাবৃত্তি করার পরিবর্তে, আপনি যাদুটির এই সত্যই উজ্জ্বল বিটটি ব্যবহার করতে পারেন : stackoverflow.com/a/14135456/746890
ক্রিস নোলেট

উত্তর:


338

আমার অ্যাপ্লিকেশনগুলির একটিতে আমি ব্যবহারকারীদের পটভূমিতে আলতো চাপলে প্রায়শই প্রথম প্রতিক্রিয়াকারীকে পদত্যাগ করতে চাই। এই উদ্দেশ্যে আমি ইউআইভিউতে একটি বিভাগ লিখেছিলাম, যা আমি ইউআইওয়াইন্ডোতে কল করি।

নিম্নলিখিতটি এর উপর ভিত্তি করে এবং প্রথম প্রতিক্রিয়াশীলকে ফিরে আসা উচিত।

@implementation UIView (FindFirstResponder)
- (id)findFirstResponder
{
    if (self.isFirstResponder) {
        return self;        
    }
    for (UIView *subView in self.subviews) {
        id responder = [subView findFirstResponder];
        if (responder) return responder;
    }
    return nil;
}
@end

আইওএস 7+

- (id)findFirstResponder
{
    if (self.isFirstResponder) {
        return self;
    }
    for (UIView *subView in self.view.subviews) {
        if ([subView isFirstResponder]) {
            return subView;
        }
    }
    return nil;
}

সুইফট:

extension UIView {
    var firstResponder: UIView? {
        guard !isFirstResponder else { return self }

        for subview in subviews {
            if let firstResponder = subview.firstResponder {
                return firstResponder
            }
        }

        return nil
    }
}

সুইফটে ব্যবহারের উদাহরণ:

if let firstResponder = view.window?.firstResponder {
    // do something with `firstResponder`
}

278
কেন কেবল কল করার চেয়ে এটি আরও ভাল সমাধান [self.view endEditing:YES]?
টিম সুলিভান

69
@ টিম আমি আপনাকে এটি করতে পারিনি। প্রথম প্রতিক্রিয়াকারীকে পদত্যাগ করা স্পষ্টতই এটি অনেক সহজ উপায়। এটি মূল প্রশ্নগুলির সাথে সহায়তা করে না, যদিও এটি ছিল প্রথম প্রতিক্রিয়াকারীকে সনাক্ত করা।
টমাস মুলার

17
এছাড়াও, এটি আরও ভাল উত্তর কারণ আপনি ইতিমধ্যে পদত্যাগ করার চেয়ে প্রথম উত্তরদাতার সাথে অন্য কিছু করতে চাইতে পারেন ...
এরিক বি

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

10
আইওএস for এর জন্য পার্থক্য কেন? আপনিও কি সেই ক্ষেত্রে পুনরাবৃত্তি করতে চান না?
পিটার ডিউইউজ

531

যদি আপনার চূড়ান্ত লক্ষ্যটি কেবল প্রথম প্রতিক্রিয়াকারীকে পদত্যাগ করা হয় তবে এটি কাজ করা উচিত: [self.view endEditing:YES]


122
আপনারা সবাই বলছেন যে এটিই "প্রশ্নের" জবাব, আপনি কি আসল প্রশ্নটি একবার দেখে নিতে পারেন? প্রশ্নটি জিজ্ঞাসা করে যে কীভাবে বর্তমান প্রথম উত্তরদাতা পাবেন। প্রথম প্রতিক্রিয়াশীলকে কীভাবে পদত্যাগ করবেন তা নয়।
জাস্টিন ক্রেডিবল

2
এবং এই সেলফ ভিউকে আমাদের কোথায় বলা উচিত এডিটিং?
user4951

8
সত্য যে এটি সঠিকভাবে প্রশ্নের উত্তর দিচ্ছে না, তবে স্পষ্টতই এটি একটি খুব দরকারী উত্তর। ধন্যবাদ!
নোভাজো

6
এটি প্রশ্নের উত্তর না হলেও এমনকি +1 করুন। কেন? কারণ অনেকে এখানে একটি প্রশ্ন রেখে আসেন যে এই উত্তরগুলি উত্তর দেয় :) তাদের মধ্যে কমপক্ষে 267 (এই মুহুর্তে) ...
রোক জার্ক

1
এটি প্রশ্নের উত্তর দিচ্ছে না।
সাশো

186

প্রথম প্রতিক্রিয়াকারীকে হেরফের করার একটি সাধারণ উপায় হ'ল শূন্য লক্ষ্যমাত্রা ব্যবহার করা। এটি প্রতিক্রিয়াশীল চেইনে একটি স্বেচ্ছাচারিত বার্তা প্রেরণের একটি উপায় (প্রথম প্রতিক্রিয়াকারী দিয়ে শুরু করে) এবং কেউ বার্তাটির প্রতিক্রিয়া না দেওয়া পর্যন্ত শৃঙ্খলা অব্যাহত রাখার (নির্বাচকের সাথে মেলে একটি পদ্ধতি প্রয়োগ করেছে)।

কীবোর্ড খারিজ করার ক্ষেত্রে, এটি সবচেয়ে কার্যকর উপায় যা কোনও উইন্ডো বা দৃষ্টিভঙ্গি প্রথম প্রতিক্রিয়াশীল তা বিবেচনা করেই কাজ করবে:

[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

এটি সেক্ষেত্রে আরও কার্যকর হতে হবে [self.view.window endEditing:YES]

( ধারণাটি আমাকে মনে করিয়ে দেওয়ার জন্য বিগজ্যাফডকে ধন্যবাদ )


4
এই এত শান্ত. সম্ভবত আমি এখনও দেখতে পেলাম নেস্টেস্ট কোকো টাচ ট্রিক। আমার কোন শেষ নেই!
mluisbrown

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

2
এই সমাধানটি সেরা-অনুশীলন সমাধান। সিস্টেমটি ইতিমধ্যে জানে যে প্রথম প্রতিক্রিয়াকারী কে, এটি খুঁজে পাওয়ার দরকার নেই।
লেফটপিন

2
আমি এই উত্তর একাধিক upvote দিতে চান। এটি প্রতিভা বিস্মৃত হয়।
রিড মেইন

1
ডিভিওএস 1: জ্যাকবের উত্তর হ'ল প্রশ্নটি যা জিজ্ঞাসা করে ঠিক তেমনই, তবে এটি প্রতিক্রিয়াশীল সিস্টেমটিকে যেমন নকশা করা হয়েছিল সেভাবে ব্যবহার করার চেয়ে প্রতিক্রিয়াশীল সিস্টেমের শীর্ষে একটি হ্যাক। এটি পরিষ্কার এবং বেশিরভাগ লোকেরা এই প্রশ্নের জন্য কী আসে সেগুলি সম্পাদন করে এবং এক-লাইনের মধ্যেও। (আপনি অবশ্যই কোনও টার্গেট-অ্যাকশন শৈলীর বার্তা পাঠাতে পারেন, এবং কেবল পদত্যাগকারী ফার্স্ট রেসপন্ডারকে নয়)।
nevyn

98

এখানে এমন একটি বিভাগ যা আপনাকে কল করে দ্রুত প্রথম প্রতিক্রিয়াশীলকে সন্ধান করতে দেয় [UIResponder currentFirstResponder]। আপনার প্রকল্পে কেবল নিম্নলিখিত দুটি ফাইল যুক্ত করুন:

UIResponder + + FirstResponder.h

#import <Cocoa/Cocoa.h>
@interface UIResponder (FirstResponder)
    +(id)currentFirstResponder;
@end

UIResponder + + FirstResponder.m

#import "UIResponder+FirstResponder.h"
static __weak id currentFirstResponder;
@implementation UIResponder (FirstResponder)
    +(id)currentFirstResponder {
         currentFirstResponder = nil;
         [[UIApplication sharedApplication] sendAction:@selector(findFirstResponder:) to:nil from:nil forEvent:nil];
         return currentFirstResponder;
    }
    -(void)findFirstResponder:(id)sender {
        currentFirstResponder = self;
    }
@end

এখানে কৌশলটি হ'ল শূন্যের জন্য একটি ক্রিয়া প্রেরণ এটি প্রথম প্রতিক্রিয়াকারীকে প্রেরণ করে।

(আমি মূলত এই উত্তরটি এখানে প্রকাশ করেছি: https://stackoverflow.com/a/14135456/322427 )


1
+1 এটি আমি এখনও দেখেছি সমস্যার সর্বাধিক মার্জিত সমাধান (এবং প্রকৃত প্রশ্ন জিজ্ঞাসা করা হয়েছে) seen পুনরায় ব্যবহারযোগ্য এবং দক্ষ! এই উত্তর upvote!
ডিভাইস 1

3
সাবাস। এটি কেবলমাত্র সবচেয়ে সুন্দর এবং পরিষ্কার হ্যাক হতে পারে যা আমি ওবজকের জন্য দেখেছি ...
গ্রস

খুব সুন্দর. তারপরে প্রথম উত্তরদাতাকে জিজ্ঞাসা করতে সক্ষম হওয়ার জন্য কে সত্যিই ভাল কাজ করা উচিত (যদি কেউ) শৃঙ্খলে থাকা কোনও নির্দিষ্ট ক্রিয়া পদ্ধতি হ্যান্ডেল করবে তবে এটি প্রেরণ করা হয়েছিল। নিয়ন্ত্রণগুলি সক্ষম করা বা সক্ষম করা যায় কিনা তার ভিত্তিতে আপনি এটি সক্ষম বা অক্ষম করতে এটি ব্যবহার করতে পারেন। আমি এটিতে আমার নিজের প্রশ্নের উত্তর দেব এবং আপনার উত্তরটি উল্লেখ করব।
বেঞ্জোহন


সতর্কতা: আপনি একাধিক উইন্ডো যুক্ত করা শুরু করলে এটি কাজ করে না। দুর্ভাগ্যক্রমে আমি এখনও এর বাইরে কোনও কারণ দেখিয়ে বলতে পারি না can't
সীমানা

41

জাকব ডিম্বারের সবচেয়ে দুর্দান্ত উত্তরের ভিত্তিতে সুইফটে একটি এক্সটেনশন কার্যকর করা হয়েছে:

import UIKit

extension UIResponder {
    // Swift 1.2 finally supports static vars!. If you use 1.1 see: 
    // http://stackoverflow.com/a/24924535/385979
    private weak static var _currentFirstResponder: UIResponder? = nil

    public class func currentFirstResponder() -> UIResponder? {
        UIResponder._currentFirstResponder = nil
        UIApplication.sharedApplication().sendAction("findFirstResponder:", to: nil, from: nil, forEvent: nil)
        return UIResponder._currentFirstResponder
    }

    internal func findFirstResponder(sender: AnyObject) {
        UIResponder._currentFirstResponder = self
    }
}

সুইফট 4

import UIKit    

extension UIResponder {
    private weak static var _currentFirstResponder: UIResponder? = nil

    public static var current: UIResponder? {
        UIResponder._currentFirstResponder = nil
        UIApplication.shared.sendAction(#selector(findFirstResponder(sender:)), to: nil, from: nil, for: nil)
        return UIResponder._currentFirstResponder
    }

    @objc internal func findFirstResponder(sender: AnyObject) {
        UIResponder._currentFirstResponder = self
    }
}

1
স্থির var সমর্থিত যেখানে swift1.2 এর জন্য পরিবর্তিত উত্তর answer
nacho4d

হাই, আমি যখন ভিডিডআইপিয়ার () এ ব্র্যান্ডের নতুন একক-দর্শন অ্যাপ্লিকেশনটিতে এর ফলাফল মুদ্রণ করি তখন আমি শূন্য হই। ভিউটি প্রথম প্রতিক্রিয়াশীল হওয়া উচিত নয়?
farhadf

@LinusGeffarth না এটা স্ট্যাটিক পদ্ধতি কলে আরো বেশি জানার জন্য currentপরিবর্তে first?
কোড কমান্ডার

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

29

এটি খুব সুন্দর নয়, তবে আমি যেভাবে প্রথম প্রতিবেদককে পদত্যাগ করি যখন আমি জানিনা যে প্রতিক্রিয়াশীল কী তা:

আইবিতে বা প্রোগ্রামগতভাবে একটি ইউআইটিেক্সটফিল্ড তৈরি করুন। এটি গোপন করুন। আপনি যদি আইবিতে তৈরি করেন তবে এটি আপনার কোডের সাথে লিঙ্ক করুন।

তারপরে, আপনি কীবোর্ডটি খারিজ করতে চাইলে, আপনি প্রতিক্রিয়াটিকে অদৃশ্য পাঠ্যের ক্ষেত্রে স্যুইচ করুন এবং তত্ক্ষণাত্ এটিকে পদত্যাগ করুন:

    [self.invisibleField becomeFirstResponder];
    [self.invisibleField resignFirstResponder];

61
এটি একই সাথে ভয়ঙ্কর এবং প্রতিভা উভয়ই। খুশী হলাম।
অ্যালেক্স ওয়েন

4
আমি দেখতে পেয়েছি যে কিছুটা বিপজ্জনক - অ্যাপল একদিন সিদ্ধান্ত নিতে পারে যে কোনও লুকানো নিয়ন্ত্রণ তৈরি করা প্রথম প্রতিক্রিয়াশীল হয়ে ওঠে আচরণের উদ্দেশ্যে নয় এবং আইওএসকে আরও কিছু না করার জন্য "ফিক্স" করা উচিত এবং তারপরে আপনার কৌশলটি কাজ বন্ধ করে দিতে পারে।
থমাস টেম্পেলম্যান

2
অথবা আপনি বর্তমানে ইউএসটিএক্সফিল্ডে প্রথম প্রতিবেদন সরবরাহ করতে পারেন যা বর্তমানে দৃশ্যমান রয়েছে এবং তারপরে সেই নির্দিষ্ট পাঠ্যফিল্ডে ইস্তফা দিয়ে ফার্স্ট রিসপন্ডারকে কল করতে পারেন। এটি একটি লুকানো দর্শন তৈরির প্রয়োজনীয়তা সরিয়ে দেয়। সব একই, +1।
সুইফ্টি ম্যাকস্ফটার্টন

3
আমি বরং এটি কেবল ভয়াবহ বলে মনে করি ... এটি লুকানোর আগে এটি কীবোর্ড বিন্যাস (বা ইনপুট ভিউ) পরিবর্তন করতে পারে
ড্যানিয়েল

19

নেভিনের উত্তরের একটি সুইফ্ট 3 এবং 4 সংস্করণের জন্য :

UIApplication.shared.sendAction(#selector(UIView.resignFirstResponder), to: nil, from: nil, for: nil)

10

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

এটি অ্যাপলের পদ্ধতি পাঠানোর ক্রিয়াকলাপটি উপস্থাপন করে: থেকে: থেকে: forEvent:, যা ইতিমধ্যে জানে প্রথম প্রতিক্রিয়াকারীকে কীভাবে অ্যাক্সেস করতে হয়।

আমাদের কেবল এটি 2 উপায়ে টুইট করতে হবে:

  • প্রসারিত করুন UIResponderযাতে এটি প্রথম প্রতিক্রিয়াকারীটিতে আমাদের নিজস্ব কোড কার্যকর করতে পারে।
  • UIEventপ্রথম উত্তরদাতাকে ফেরত দেওয়ার জন্য সাবক্লাস ।

কোডটি এখানে:

@interface ABCFirstResponderEvent : UIEvent
@property (nonatomic, strong) UIResponder *firstResponder;
@end

@implementation ABCFirstResponderEvent
@end

@implementation UIResponder (ABCFirstResponder)
- (void)abc_findFirstResponder:(id)sender event:(ABCFirstResponderEvent *)event {
    event.firstResponder = self;
}
@end

@implementation ViewController

+ (UIResponder *)firstResponder {
    ABCFirstResponderEvent *event = [ABCFirstResponderEvent new];
    [[UIApplication sharedApplication] sendAction:@selector(abc_findFirstResponder:event:) to:nil from:nil forEvent:event];
    return event.firstResponder;
}

@end

7

প্রথম রেসপনারটি ইউআইআরআইএসপেন্ডার শ্রেণীর কোনও উদাহরণ হতে পারে, তাই অন্যান্য ক্লাসগুলিও রয়েছে যা ইউআইভিউউস সত্ত্বেও প্রথম প্রতিক্রিয়াকারী হতে পারে। উদাহরণস্বরূপ UIViewControllerপ্রথম প্রতিক্রিয়াকারীও হতে পারে।

এই সংক্ষেপে আপনি অ্যাপ্লিকেশনগুলির উইন্ডোজের রুট ভিউকন্ট্রোলার থেকে শুরু করে নিয়ন্ত্রকদের হায়ারার্কির মধ্য দিয়ে লুপ করে প্রথম প্রতিক্রিয়াশীল হওয়ার একটি পুনরাবৃত্ত উপায় খুঁজে পাবেন।

আপনি তারপরে প্রথম প্রতিক্রিয়াশীলটিকে পুনরুদ্ধার করতে পারেন

- (void)foo
{
    // Get the first responder
    id firstResponder = [UIResponder firstResponder];

    // Do whatever you want
    [firstResponder resignFirstResponder];      
}

তবে, যদি প্রথম প্রতিক্রিয়াকারী ইউআইভিউ বা ইউআইভিউউকন্ট্রোলারের সাবক্লাস না হয় তবে এই পদ্ধতির ব্যর্থতা ঘটবে।

এই সমস্যাটি সমাধানের জন্য আমরা একটি UIResponderশ্রেণি তৈরি করে এই শ্রেণীর সমস্ত জীবিত দৃষ্টান্তের অ্যারে তৈরি করতে সক্ষম হওয়ার জন্য কিছু যাদু সুইজেলিং সম্পাদন করে একটি ভিন্ন পদ্ধতি করতে পারি । তারপরে, প্রথম প্রতিক্রিয়াকারী পেতে আমরা সাধারণ পুনরাবৃত্তি করতে পারি এবং প্রতিটি বস্তুকে জিজ্ঞাসা করতে পারি কিনা -isFirstResponder

এই পদ্ধতির এই অন্যান্য টুকরোটিতে প্রয়োগ করা যেতে পারে ।

আশা করি এটা সাহায্য করবে.


7

ব্যবহার সুইফট এবং সঙ্গে নির্দিষ্ট UIViewঅবজেক্ট এই শক্তি সহায়তা:

func findFirstResponder(inView view: UIView) -> UIView? {
    for subView in view.subviews as! [UIView] {
        if subView.isFirstResponder() {
            return subView
        }

        if let recursiveSubView = self.findFirstResponder(inView: subView) {
            return recursiveSubView
        }
    }

    return nil
}

কেবল এটি আপনার মধ্যে রাখুন UIViewControllerএবং এটি ব্যবহার করুন:

let firstResponder = self.findFirstResponder(inView: self.view)

নোটটি নিন যে ফলাফলটি একটি ptionচ্ছিক মান তাই এটি নিরপেক্ষ হবে যদি প্রদত্ত দর্শন সংক্ষিপ্তসারগুলিতে কোনও ফার্স্ট রেসপনার পাওয়া যায় নি।


5

প্রথম প্রতিক্রিয়াকারী হতে পারে এবং - (BOOL)isFirstResponderবর্তমানে তারা কিনা তা নির্ধারণ করতে ব্যবহার করা যেতে পারে এমন মতামতগুলি পর্যালোচনা করুন ।


4

পিটার স্টেইনবার্গার কেবলমাত্র প্রাইভেট নোটিফিকেশন সম্পর্কে টুইট করেছেনUIWindowFirstResponderDidChangeNotification , যা আপনি যদি প্রথম রিসপন্ডার পরিবর্তনটি দেখতে চান তা পর্যবেক্ষণ করতে পারেন।


তিনি প্রত্যাখ্যান করেছেন কারণ একটি প্রাইভেট এপিআই ব্যবহার করা, সম্ভবত একটি ব্যক্তিগত বিজ্ঞপ্তি ব্যবহার করাও একটি খারাপ ধারণা হতে পারে ...
লাসজলো

4

যদি আপনি কেবল কীবোর্ডটি মারতে চান যখন ব্যবহারকারী একটি পটভূমি অঞ্চলে টোকা দেয় কেন কোনও অঙ্গভঙ্গি সনাক্তকারী যুক্ত করে [[self view] endEditing:YES]বার্তাটি প্রেরণে এটি ব্যবহার করবেন না ?

আপনি xib বা স্টোরিবোর্ড ফাইলটিতে ট্যাপ অঙ্গভঙ্গি সনাক্তকারী যুক্ত করতে পারেন এবং এটিকে কোনও ক্রিয়াতে সংযুক্ত করতে পারেন,

এরপরে এমন কিছু দেখাচ্ছে যা শেষ হয়েছে

- (IBAction)displayGestureForTapRecognizer:(UITapGestureRecognizer *)recognizer{
     [[self view] endEditing:YES];
}

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

4

কেবলমাত্র এটি এখানে দুর্দান্ত জাকব এগারের পদ্ধতির সুইফট সংস্করণ:

import UIKit

private weak var currentFirstResponder: UIResponder?

extension UIResponder {

    static func firstResponder() -> UIResponder? {
        currentFirstResponder = nil
        UIApplication.sharedApplication().sendAction(#selector(self.findFirstResponder(_:)), to: nil, from: nil, forEvent: nil)
        return currentFirstResponder
    }

    func findFirstResponder(sender: AnyObject) {
        currentFirstResponder = self
    }

}

3

কোনও মডেলভিউ কনট্রোলারটিতে যখন ব্যবহারকারী সংরক্ষণ / বাতিল করতে ক্লিক করে তখন ইউআইটিেক্সটফিল্ডটি প্রথম রিসপন্ডার কী তা খুঁজে পেতে আমি এটি করেছি:

    NSArray *subviews = [self.tableView subviews];

for (id cell in subviews ) 
{
    if ([cell isKindOfClass:[UITableViewCell class]]) 
    {
        UITableViewCell *aCell = cell;
        NSArray *cellContentViews = [[aCell contentView] subviews];
        for (id textField in cellContentViews) 
        {
            if ([textField isKindOfClass:[UITextField class]]) 
            {
                UITextField *theTextField = textField;
                if ([theTextField isFirstResponder]) {
                    [theTextField resignFirstResponder];
                }

            }
        }

    }

}

2

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

- (UIView*) enumerateAllSubviewsOf: (UIView*) aView UsingBlock: (BOOL (^)( UIView* aView )) aBlock {

 for ( UIView* aSubView in aView.subviews ) {
  if( aBlock( aSubView )) {
   return aSubView;
  } else if( ! [ aSubView isKindOfClass: [ UIControl class ]] ){
   UIView* result = [ self enumerateAllSubviewsOf: aSubView UsingBlock: aBlock ];

   if( result != nil ) {
    return result;
   }
  }
 }    

 return nil;
}

- (UIView*) enumerateAllSubviewsUsingBlock: (BOOL (^)( UIView* aView )) aBlock {
 return [ self enumerateAllSubviewsOf: self.view UsingBlock: aBlock ];
}

- (UIView*) findFirstResponder {
 return [ self enumerateAllSubviewsUsingBlock:^BOOL(UIView *aView) {
  if( [ aView isFirstResponder ] ) {
   return YES;
  }

  return NO;
 }];
}

2

বিভাগে একটি বিভাগ সহ UIResponder, অবৈধভাবে আইনটির কাছে UIApplicationপ্রথমে উত্তরদাতা কে তা আপনাকে বলতে জিজ্ঞাসা করা সম্ভব ।

এটা দেখ:

কোনও আইওএস ভিউ জিজ্ঞাসা করার কোনও উপায় কি এর শিশুদের মধ্যে প্রথম প্রতিক্রিয়াশীল স্থিতি রয়েছে?


2

আপনি UIViewএটি পেতে নিম্নলিখিত এক্সটেনশনটি চয়ন করতে পারেন (ড্যানিয়েলের ক্রেডিট) :

extension UIView {
    var firstResponder: UIView? {
        guard !isFirstResponder else { return self }
        return subviews.first(where: {$0.firstResponder != nil })
    }
}

1

আপনি এটির মতো চেষ্টাও করতে পারেন:

- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) event { 

    for (id textField in self.view.subviews) {

        if ([textField isKindOfClass:[UITextField class]] && [textField isFirstResponder]) {
            [textField resignFirstResponder];
        }
    }
} 

আমি চেষ্টা করে দেখিনি তবে এটি একটি ভাল সমাধান বলে মনে হচ্ছে


1

রোমিও https://stackoverflow.com/a/2799675/661022 থেকে সমাধানটি দুর্দান্ত তবে আমি লক্ষ্য করেছি যে কোডটির আরও একটি লুপ দরকার। আমি টেবিলভিউ কন্ট্রোলারের সাথে কাজ করছিলাম। আমি স্ক্রিপ্টটি সম্পাদনা করেছি এবং তারপরে আমি চেক করেছি। সবকিছু নিখুঁত কাজ করেছে।

আমি এটি চেষ্টা করে পুনরায় চেষ্টা করেছি:

- (void)findFirstResponder
{
    NSArray *subviews = [self.tableView subviews];
    for (id subv in subviews )
    {
        for (id cell in [subv subviews] ) {
            if ([cell isKindOfClass:[UITableViewCell class]])
            {
                UITableViewCell *aCell = cell;
                NSArray *cellContentViews = [[aCell contentView] subviews];
                for (id textField in cellContentViews)
                {
                    if ([textField isKindOfClass:[UITextField class]])
                    {
                        UITextField *theTextField = textField;
                        if ([theTextField isFirstResponder]) {
                            NSLog(@"current textField: %@", theTextField);
                            NSLog(@"current textFields's superview: %@", [theTextField superview]);
                        }
                    }
                }
            }
        }
    }
}

ধন্যবাদ! আপনি সঠিক, এখানে উপস্থাপন করা সর্বাধিক উত্তরগুলি ইউটিউবভিউর সাথে কাজ করার সময় কোনও সমাধান নয়। আপনি আপনার কোডটি অনেক সহজ করতে পারেন, এমনকি if ([textField isKindOfClass:[UITextField class]])ইউটিেক্সটভিউয়ের জন্য ব্যবহারের অনুমতি দিলে তাও বের করে নিতে পারেন এবং প্রথম সংবাদদাতাকে ফিরে আসতে পারেন।
ফ্রেড

1

এটি পুনরাবৃত্তি জন্য ভাল প্রার্থী! ইউআইভিউতে কোনও বিভাগ যুক্ত করার দরকার নেই।

ব্যবহার (আপনার দর্শন নিয়ন্ত্রক থেকে):

UIView *firstResponder = [self findFirstResponder:[self view]];

কোড:

// This is a recursive function
- (UIView *)findFirstResponder:(UIView *)view {

    if ([view isFirstResponder]) return view; // Base case

    for (UIView *subView in [view subviews]) {
        if ([self findFirstResponder:subView]) return subView; // Recursion
    }
    return nil;
}

1

আপনি এটিকে প্রাইভেট এপি বলতে পারেন, আপেল উপেক্ষা করুন:

UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
SEL sel = NSSelectorFromString(@"firstResponder");
UIView   *firstResponder = [keyWindow performSelector:sel];

1
তবে ... দয়া করে চেক করতে '
রেসপন্ডস-নির্বাচনকারী

আমি এখন 'রেসপন্স টো সিলেক্টর' চেক করি তবে আমি এখনও একটি সতর্কতা পেয়েছি, এটি অনিরাপদ হতে পারে। আমি কি কোনওভাবে সতর্কতা থেকে মুক্তি পেতে পারি?
বাস্তু

1

@ থোমাস-মুলারের প্রতিক্রিয়াটির সুইফ্ট সংস্করণ

extension UIView {

    func firstResponder() -> UIView? {
        if self.isFirstResponder() {
            return self
        }

        for subview in self.subviews {
            if let firstResponder = subview.firstResponder() {
                return firstResponder
            }
        }

        return nil
    }

}

1

আমার বেশিরভাগের চেয়ে কিছুটা আলাদা পদ্ধতি আছে। যেটি isFirstResponderসেট করা হয়েছে তার সন্ধানের ভিউ সংগ্রহের মাধ্যমে পুনরাবৃত্তি করার পরিবর্তে , আমিও একটি বার্তা প্রেরণ nilকরি, তবে আমি রিসিভারটি সংরক্ষণ করি (যদি থাকে), তবে সেই মানটি ফিরিয়ে দিন যাতে কলার প্রকৃত উদাহরণটি পায় (আবার যদি থাকে) ।

import UIKit

private var _foundFirstResponder: UIResponder? = nil

extension UIResponder{

    static var first:UIResponder?{

        // Sending an action to 'nil' implicitly sends it to the
        // first responder, where we simply capture it for return
        UIApplication.shared.sendAction(#selector(UIResponder.storeFirstResponder(_:)), to: nil, from: nil, for: nil)

        // The following 'defer' statement executes after the return
        // While I could use a weak ref and eliminate this, I prefer a
        // hard ref which I explicitly clear as it's better for race conditions
        defer {
            _foundFirstResponder = nil
        }

        return _foundFirstResponder
    }

    @objc func storeFirstResponder(_ sender: AnyObject) {
        _foundFirstResponder = self
    }
}

তারপরে আমি এটি করে প্রথম উত্তরদাতা, যদি কোনও হয় তবে পদত্যাগ করতে পারি ...

return UIResponder.first?.resignFirstResponder()

তবে আমি এখন এটিও করতে পারি ...

if let firstResponderTextField = UIResponder?.first as? UITextField {
    // bla
}

1

ইউআইভিউ-র যে কোনও জায়গায় প্রথম প্রতিক্রিয়াকারী হিসাবে সন্ধানের জন্য আমি আমার বাস্তবায়ন আপনার সাথে ভাগ করে নিতে চাই। আমি আশা করি এটি আমার ইংরেজিটির জন্য সহায়তা করে এবং দুঃখিত sorry ধন্যবাদ

+ (UIView *) findFirstResponder:(UIView *) _view {

    UIView *retorno;

    for (id subView in _view.subviews) {

        if ([subView isFirstResponder])
        return subView;

        if ([subView isKindOfClass:[UIView class]]) {
            UIView *v = subView;

            if ([v.subviews count] > 0) {
                retorno = [self findFirstResponder:v];
                if ([retorno isFirstResponder]) {
                    return retorno;
                }
            }
        }
    }

    return retorno;
}

0

কাজের নীচে কোড।

- (id)ht_findFirstResponder
{
    //ignore hit test fail view
    if (self.userInteractionEnabled == NO || self.alpha <= 0.01 || self.hidden == YES) {
        return nil;
    }
    if ([self isKindOfClass:[UIControl class]] && [(UIControl *)self isEnabled] == NO) {
        return nil;
    }

    //ignore bound out screen
    if (CGRectIntersectsRect(self.frame, [UIApplication sharedApplication].keyWindow.bounds) == NO) {
        return nil;
    }

    if ([self isFirstResponder]) {
        return self;
    }

    for (UIView *subView in self.subviews) {
        id result = [subView ht_findFirstResponder];
        if (result) {
            return result;
        }
    }
    return nil;
}   

0

আপডেট: আমি ভুল ছিল। আপনি অবশ্যই UIApplication.shared.sendAction(_:to:from:for:)এই লিঙ্কটিতে প্রদর্শিত প্রথম প্রতিক্রিয়াকারীকে কল করতে ব্যবহার করতে পারেন : http://stackoverflow.com/a/14135456/746890


এখানকার বেশিরভাগ উত্তর সত্যিকারের বর্তমান প্রতিক্রিয়াশীলটিকে সন্ধান করতে পারে না যদি তা ভিউ হায়ারার্কিতে না থাকে। উদাহরণস্বরূপ, AppDelegateবা UIViewControllerসাবক্ল্যাস।

এটির জন্য আপনাকে গ্যারান্টি দেওয়ার একটি উপায় আছে এমনকি যদি প্রথম প্রতিক্রিয়াকারী অবজেক্টটি একটি না হয় UIView

প্রথমে এর বিপরীত সংস্করণটি প্রয়োগ করে এর nextবৈশিষ্ট্যগুলি ব্যবহার করে UIResponder:

extension UIResponder {
    var nextFirstResponder: UIResponder? {
        return isFirstResponder ? self : next?.nextFirstResponder
    }
}

এই গণিত সম্পত্তি সহ, আমরা বর্তমান প্রথম উত্তরদাতা এটি নীচে থেকে উপরে পর্যন্ত সন্ধান করতে পারি যদি তা না হয় UIView। উদাহরণস্বরূপ, একটি থেকে viewকরতে UIViewControllerএটি পরিচালনার হচ্ছে যারা, যদি দৃশ্য নিয়ামক প্রথম উত্তর প্রদানকারী হয়।

তবে, আমাদের এখনও varপ্রথম শীর্ষ প্রতিক্রিয়া পেতে একটি শীর্ষ-রেজোলিউশন, একটি একক প্রয়োজন।

ভিউ হায়ারার্কি সহ প্রথম:

extension UIView {
    var previousFirstResponder: UIResponder? {
        return nextFirstResponder ?? subviews.compactMap { $0.previousFirstResponder }.first
    }
}

এটি প্রথম প্রতিক্রিয়াশীলটিকে পিছনের দিকে সন্ধান করবে এবং এটি যদি এটি খুঁজে না পেল তবে এটির কাজগুলি পর্যালোচনাগুলিকে একই জিনিস করতে বলবে (কারণ এটির সাবভিউটি nextঅগত্যা নিজেই নয়)। এটির সহ আমরা যেকোন দর্শন থেকে এটি খুঁজে পেতে পারি UIWindow

এবং অবশেষে, আমরা এটি তৈরি করতে পারি:

extension UIResponder {
    static var first: UIResponder? {
        return UIApplication.shared.windows.compactMap({ $0.previousFirstResponder }).first
    }
}

সুতরাং আপনি যখন প্রথম উত্তরদাতা পুনরুদ্ধার করতে চান, আপনি কল করতে পারেন:

let firstResponder = UIResponder.first

0

প্রথম প্রতিক্রিয়াশীলকে সন্ধান করার সহজ উপায়:

func sendAction(_ action: Selector, to target: Any?, from sender: Any?, for event: UIEvent?) -> Bool

ডিফল্ট বাস্তবায়ন প্রদত্ত টার্গেট অবজেক্টে অ্যাকশন পদ্ধতিটি প্রেরণ করে বা যদি কোনও লক্ষ্য নির্দিষ্ট না করা হয় তবে প্রথম প্রতিক্রিয়াকারীকে প্রেরণ করে।

পরবর্তী পর্ব:

extension UIResponder
{
    private weak static var first: UIResponder? = nil

    @objc
    private func firstResponderWhereYouAre(sender: AnyObject)
    {
        UIResponder.first = self
    }

    static var actualFirst: UIResponder?
    {
        UIApplication.shared.sendAction(#selector(findFirstResponder(sender:)), to: nil, from: nil, for: nil)
        return UIResponder.first
    }
}

ব্যবহার: শুধু UIResponder.actualFirstআপনার নিজের উদ্দেশ্যে পেতে ।

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