سؤال

لقد قمت بتطبيق uisearchbar في عرض جدول وكل شيء تقريبًا يعمل باستثناء شيء صغير واحد: عندما أدخل النص ثم اضغط على زر البحث على لوحة المفاتيح ، تختفي لوحة المفاتيح ، ونتائج البحث هي العناصر الوحيدة الموضحة في الجدول ، يبقى النص في uisearchbar ، ولكن يتم تعطيل زر الإلغاء.

لقد كنت أحاول الحصول على قائمتي بالقرب من وظائف تطبيق Apple Contacts ، وعندما تضغط على البحث في هذا التطبيق ، فإنه لا يقوم بتعطيل زر الإلغاء.

عندما نظرت إلى ملف رأس UISearchBar ، لاحظت علامة لـ AutodisableCancelButton تحت هيكل _searchbarflags ولكنه خاص.

هل هناك شيء أفتقده عند إعداد uisearchbar؟

هل كانت مفيدة؟

المحلول

لقد وجدت حلاً. يمكنك استخدام هذا الحلقة للحلق على الرؤية الفرعية لشريط البحث وتمكينه عند الضغط على زر البحث على لوحة المفاتيح.

for (UIView *possibleButton in searchBar.subviews)
{
    if ([possibleButton isKindOfClass:[UIButton class]])
    {
        UIButton *cancelButton = (UIButton*)possibleButton;
        cancelButton.enabled = YES;
        break;
    }
}

نصائح أخرى

اضطررت إلى تعديل هذا قليلاً للحصول على العمل من أجلي في iOS7

- (void)enableCancelButton:(UISearchBar *)searchBar
{
    for (UIView *view in searchBar.subviews)
    {
        for (id subview in view.subviews)
        {
            if ( [subview isKindOfClass:[UIButton class]] )
            {
                [subview setEnabled:YES];
                NSLog(@"enableCancelButton");
                return;
            }
        }
    }
}

هناك طريقتان لتحقيق ذلك بسهولة

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
    //  The small and dirty
    [(UIButton*)[searchBar valueForKey:@"_cancelButton"] setEnabled:YES];

    // The long and safe
     UIButton *cancelButton = [searchBar valueForKey:@"_cancelButton"];
    if ([cancelButton respondsToSelector:@selector(setEnabled:)]) {
         cancelButton.enabled = YES;
    }
}

يجب أن تذهب مع الثانية ، ولن تعطل تطبيقك إذا كانت Apple ستغيره في الخلفية.

راجع للشغل قمت باختباره من iOS 4.0 إلى 8.2 ولا توجد تغييرات ، وأيضًا أستخدمه في طلب متجري المعتمد دون أي مشاكل.

هذا ما جعل الأمر يعمل على iOS 6 بالنسبة لي:

searchBar.showsCancelButton = YES;
searchBar.showsScopeBar = YES;
[searchBar sizeToFit];
[searchBar setShowsCancelButton:YES animated:YES];

إليكم الحل الذي يعمل لجميع المواقف في جميع إصدارات iOS.

أي أن الحلول الأخرى لا تتعامل عندما يتم رفض لوحة المفاتيح لأن المستخدم قام بسحب طريقة عرض التمرير.

- (void)enableCancelButton:(UIView *)view {
    if ([view isKindOfClass:[UIButton class]]) {
        [(UIButton *)view setEnabled:YES];
    } else {
        for (UIView *subview in view.subviews) {
            [self enableCancelButton:subview];
        }
    }
}

// This will handle whenever the text field is resigned non-programatically
// (IE, because it's set to resign when the scroll view is dragged in your storyboard.)
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
    [self performSelector:@selector(enableCancelButton:) withObject:searchBar afterDelay:0.001];
}

// Also follow up every [searchBar resignFirstResponder];
// with [self enableCancelButton:searchBar];

لم تعمل أي من الإجابات بالنسبة لي على الإطلاق. أنا أستهدف iOS 7. لكنني وجدت إجابة.

ما أحاول هو شيء مثل تطبيق Twitter iOS. إذا قمت بالنقر فوق الزجاج المكبرة في علامة التبويب الجداول الزمنية ، UISearchBar يظهر مع تنشيط زر الإلغاء ، وظهر لوحة المفاتيح ، وشاشة عمليات البحث الحديثة. قم بتمرير شاشة عمليات البحث الحديثة ويخفي لوحة المفاتيح ولكنه يحافظ على تنشيط زر الإلغاء.

هذا هو رمز العمل الخاص بي:

UIView *searchBarSubview = self.searchBar.subviews[0];
NSArray *subviewCache = [searchBarSubview valueForKeyPath:@"subviewCache"];
if ([subviewCache[2] respondsToSelector:@selector(setEnabled:)]) {
    [subviewCache[2] setValue:@YES forKeyPath:@"enabled"];
}

وصلت إلى هذا الحل عن طريق ضبط نقطة توقف في عرض الجدول الخاص بي scrollViewWillBeginDragging:. نظرت إلى بلدي UISearchBar و Bared آراءها الفرعية. لديها دائمًا واحدة فقط ، وهي من النوع UIView (متغير بلدي searchBarSubview).

enter image description here

ثم ، ذلك UIView يحمل NSArray اتصل subviewCache ولاحظت أن العنصر الأخير ، وهو الثالث ، من النوع UINavigationButton, ، ليس في واجهة برمجة التطبيقات العامة. لذلك قمت بتعيين لاستخدام ترميز القيمة الرئيسية بدلاً من ذلك. لقد راجعت إذا UINavigationButton يستجيب إلى setEnabled:, ولحسن الحظ ، فإنه يفعل. لذلك قمت بتعيين العقار على @YES. تبين أن ذلك UINavigationButton هو زر إلغاء.

هذا لا بد أن ينهار إذا قررت Apple تغيير تنفيذ أ UISearchBarالأزرق ، ولكن ماذا بحق الجحيم. إنه يعمل الآن.

حسب جوابي هنا, ، ضع هذا في مندوب SearchBar:

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{   
    dispatch_async(dispatch_get_main_queue(), ^{
        __block __weak void (^weakEnsureCancelButtonRemainsEnabled)(UIView *);
        void (^ensureCancelButtonRemainsEnabled)(UIView *);
        weakEnsureCancelButtonRemainsEnabled = ensureCancelButtonRemainsEnabled = ^(UIView *view) {
            for (UIView *subview in view.subviews) {
                if ([subview isKindOfClass:[UIControl class]]) {
                    [(UIControl *)subview setEnabled:YES];
                }
                weakEnsureCancelButtonRemainsEnabled(subview);
            }
        };

        ensureCancelButtonRemainsEnabled(searchBar);
    });
}

بالنسبة إلى Monotouch أو Xamarin iOS ، لدي حل C# التالي يعمل لـ iOS 7 و iOS 8:

foreach(UIView view in searchBar.Subviews)
{
    foreach(var subview in view.Subviews)
    {
        //Console.WriteLine(subview.GetType());
        if(subview.GetType() == typeof(UIButton))
        {
            if(subview.RespondsToSelector(new Selector("setEnabled:")))
            {
                UIButton cancelButton = (UIButton)subview;
                cancelButton.Enabled = true;
                Console.WriteLine("enabledCancelButton");
                return;
            }
        }
    }
}

تستند هذه الإجابة على ديفيد دوغلاس المحلول.

إجابة أكثر اكتمالا:

  • منذ iOS 7 ، هناك مستوى إضافي من الرؤية الفرعية تحت شريط البحث
  • مكان جيد لتمكين زر الإلغاء في searchBarTextDidEndEditing

.

extension MyController: UISearchBarDelegate {
  public func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
    DispatchQueue.main.async {
    // you need that since the disabling will
    // happen after searchBarTextDidEndEditing is called
      searchBar.subviews.forEach({ view in
        view.subviews.forEach({ subview in
          // ios 7+
          if let cancelButton = subview as? UIButton {
            cancelButton.isEnabled = true
            cancelButton.isUserInteractionEnabled = true
            return
          }
        })
        // ios 7-
        if let cancelButton = subview as? UIButton {
          cancelButton.isEnabled = true
          cancelButton.isUserInteractionEnabled = true
          return
        }
      })
    }
  }
}

إليك حل Swift 3 الذي يستخدم الإضافات للحصول على زر الإلغاء بسهولة:

extension UISearchBar {
    var cancelButton: UIButton? {
        for subView1 in subviews {
            for subView2 in subView1.subviews {
                if let cancelButton = subView2 as? UIButton {
                    return cancelButton
                }
            }
        }
        return nil
    }
}

الآن للاستخدام:

class MyTableViewController : UITableViewController, UISearchBarDelegate {

    var searchBar = UISearchBar()

    func viewDidLoad() {
        super.viewDidLoad()
        searchBar.delegate = self
        tableView.tableHeaderView = searchBar
    }

    func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
        DispatchQueue.main.async {
            if let cancelButton = searchBar.cancelButton {
                cancelButton.isEnabled = true
                cancelButton.isUserInteractionEnabled = true
            }
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top