как добавить значок UIBarButtonSystemItem в TableViewCell? [Дубликат]

Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int:

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

Exception, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num. Перед созданием объекта вы получите NullPointerException. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

В этом случае вы не создаете объект obj, скорее предполагая, что он был создан до вызова метода doSomething. К сожалению, этот метод можно вызвать следующим образом:

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

28
задан Wain 17 January 2014 в 16:16
поделиться

8 ответов

Загрузите изображение где-нибудь в Интернете, добавьте его в свой проект и установите изображение UIButton на только что загруженное изображение.

Я не нашел то же, что использовал Apple но я нашел этот . Просто измените цвет в Pixelmator или Photoshop.

8
ответ дан yoeriboven 19 August 2018 в 03:38
поделиться
  • 1
    Я пробовал, но не могу его найти. – ZviBar 17 January 2014 в 16:18
  • 2
    Как насчет этого: icons8.com/icons / # / 1942 / trash – yoeriboven 17 January 2014 в 16:19
  • 3
    Не удалось заставить его работать с tintColor. Не должно быть проблем, поскольку вы можете просто изменить его цвет в Photoshop или Pixelmator. – yoeriboven 17 January 2014 в 16:32
  • 4
    Действительно грустно, что принятый ответ должен нарушать правила авторских прав ... «скопировать изображение где-нибудь и добавить его в ваш проект». – Lepidopteron 1 March 2017 в 08:08
  • 5
    @ Lepidopteron на самом деле существует много "где-то" которые сделаны именно для этой цели – quemeful 10 March 2017 в 17:30

Вот решение, которое работает с элементом кнопки ANY System bar +, оно поддерживает tintColor:

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.button setImage:[self imageFromSystemBarButton:UIBarButtonSystemItemTrash]
                 forState:UIControlStateNormal];

    self.button.tintColor = [UIColor redColor];
}

- (UIImage *)imageFromSystemBarButton:(UIBarButtonSystemItem)systemItem {
    // Holding onto the oldItem (if any) to set it back later
    // could use left or right, doesn't matter
    UIBarButtonItem *oldItem = self.navigationItem.rightBarButtonItem;

    UIBarButtonItem *tempItem = [[UIBarButtonItem alloc]
                                 initWithBarButtonSystemItem:systemItem
                                 target:nil
                                 action:nil];

    // Setting as our right bar button item so we can traverse its subviews
    self.navigationItem.rightBarButtonItem = tempItem;

    // Don't know whether this is considered as PRIVATE API or not
    UIView *itemView = (UIView *)[self.navigationItem.rightBarButtonItem performSelector:@selector(view)];

    UIImage *image = nil;
    // Traversing the subviews to find the ImageView and getting its image
    for (UIView *subView in itemView.subviews) {
        if ([subView isKindOfClass:[UIImageView class]]) {
            image = ((UIImageView *)subView).image;
            break;
        }
    }

    // Setting our oldItem back since we have the image now
    self.navigationItem.rightBarButtonItem = oldItem;

    return image;
}

P.S. Не стесняйтесь улучшаться, если знаете лучший способ, спасибо.

13
ответ дан Islam Q. 19 August 2018 в 03:38
поделиться
  • 1
    Спасибо, это очень помогло мне. Я обнаружил, что могу использовать tempItem прямо в панели. Хотя не совсем UIButton, мне было трудно найти ответ. – Gram 27 July 2015 в 16:15
  • 2
    Пожалуйста. Я попытался сломать его как можно больше, так что это легко понять. – Islam Q. 27 July 2015 в 16:25
  • 3
    Как вы переведете UIView *itemView = (UIView *)[self.navigationItem.rightBarButtonItem performSelector:@selector(view)]; в Свифт? – Hans Brende 20 November 2015 в 00:16
  • 4
    Не сделали этого в Swift, но я надеюсь, что ответы на этот вопрос помогут. – Islam Q. 20 November 2015 в 05:44
  • 5
    Одна ловушка скрыта ;-) Этот код работает только, если UINavigationItem в настоящее время отображается на экране. Например, он не работает, если контроллер просмотра в настоящий момент не загружен (например, если он является одним из не выбранных контроллеров представления в UITabBarController). – LaborEtArs 1 February 2016 в 08:46

На основании ответа @yycking я написал подходящее расширение Swift 3/4:

//
//  UIImage+imageFromSystemBarButton.swift
//

import UIKit

extension UIImage{

    class func imageFromSystemBarButton(_ systemItem: UIBarButtonSystemItem, renderingMode:UIImageRenderingMode = .automatic)-> UIImage {

        let tempItem = UIBarButtonItem(barButtonSystemItem: systemItem, target: nil, action: nil)

        // add to toolbar and render it
        let bar = UIToolbar()
        bar.setItems([tempItem], animated: false)
        bar.snapshotView(afterScreenUpdates: true)

        // got image from real uibutton
        let itemView = tempItem.value(forKey: "view") as! UIView

        for view in itemView.subviews {
            if view is UIButton {
                let button = view as! UIButton
                let image = button.imageView!.image!
                image.withRenderingMode(renderingMode)
                return image
            }
        }

        return UIImage()
    }
}

Пример с кнопкой действия (по умолчанию):

let actionImage = UIImage.imageFromSystemBarButton(.action)   
let myButton = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
myButton.setImage(actionImage, for: .normal)

view.addSubview(myButton)

Если вы хотите, чтобы ваше изображение всегда обрабатывалось как шаблон независимо от контекста, установите renderMode в .alwaysTemplate

 let actionImage = UIImage.imageFromSystemBarButton(.action, renderingMode: .alwaysTemplate) 
6
ответ дан Peter Kreinz 19 August 2018 в 03:38
поделиться
  • 1
    цвет меняется! цвет по умолчанию синий, но цвет вывода вашего кода черный. Любое решение? – Sanju 18 March 2017 в 06:20
  • 2
    @sanju: я обновил режим рендеринга по умолчанию на .automatic (синий цвет по умолчанию) – Peter Kreinz 20 March 2017 в 11:21
  • 3
    @Sanju, это потому, что UIBarButtonItem использует шаблон изображения. Изображения черные, но когда они нарисованы с оттенком цвета панели. Подробнее о режиме рендеринга шаблонов. – kelin 11 April 2017 в 11:00
  • 4
    Спасибо за ответ Питер, я просто хочу указать, что он больше не работает для Swift 4, tempItem.value(forKey: "view") - это нуль, а принудительная развертка дает ошибку. – Denis Balko 8 August 2017 в 13:27
  • 5
    Я продолжаю получать нулевой доход на линии .... пусть itemView = tempItem.value (forKey: & quot; view & quot;) как! UIView – RubberDucky4444 18 January 2018 в 09:57

2017/10/05 не работает в iOS 11.0.1

для быстрого 3/4 (назовите его в основном потоке)

extension UIBarButtonSystemItem {
    func image() -> UIImage? {
        let tempItem = UIBarButtonItem(barButtonSystemItem: self,
                                       target: nil,
                                       action: nil)

        // add to toolbar and render it
        let bar = UIToolbar()
        bar.setItems([tempItem],
                     animated: false)
        bar.snapshotView(afterScreenUpdates: true)

        // got image from real uibutton
        let itemView = tempItem.value(forKey: "view") as! UIView
        for view in itemView.subviews {
            if let button = view as? UIButton,
                let image = button.imageView?.image {
                return image.withRenderingMode(.alwaysTemplate)
            }
        }

        return nil
    }
}

UIBarButtonSystemItem.play.image()

Для Objective-C:

+ (UIImage *)imageFromSystemBarButton:(UIBarButtonSystemItem)systemItem {
    UIBarButtonItem* tempItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:systemItem target:nil action:nil];

    // Add to toolbar and render it
    UIToolbar *bar = [[UIToolbar alloc] init];
    [bar setItems:@[tempItem] animated:NO];
    [bar snapshotViewAfterScreenUpdates:YES];

    // Get image from real UIButton
    UIView *itemView = [(id)tempItem view];
    for (UIView* view in itemView.subviews) {
        if ([view isKindOfClass:[UIButton class]]) {
            return [(UIButton*)view imageForState:UIControlStateNormal];
        }
    }

    return nil;
}
15
ответ дан Sayka 19 August 2018 в 03:38
поделиться
  • 1
    чтобы изображение использовало цвет оттенка кнопки, добавьте .imageWithRenderingMode (.AlwaysTemplate) – Frans 20 September 2016 в 10:40
  • 2
    Больше не работает в Xcode 9. Изображение должно быть отображено перед его извлечением. – David 23 June 2017 в 16:56
  • 3
    Это решение не работает в Xcode 9 / iOS 11. Пожалуйста, обновите ответ охранником как? Просмотрите и не разматывайте разворот. Из-за этого мое приложение разбилось. – Darkwonder 18 July 2017 в 09:06
  • 4
    @David, я нашел другой способ сделать это. – yycking 21 September 2017 в 07:22
  • 5
    @Darkwonder, потому что элемент не отображает – yycking 21 September 2017 в 07:23

Все значки системы iOS можно извлечь, используя удобное небольшое приложение (достаточно подходящее) iOS Artwork Extractor. Я использую его все время, когда я хочу имитировать поведение системы iOS.

Загрузите проект Xcode по адресу:

https://github.com/0xced/iOS- Произведение-экстрактор

3
ответ дан DKLA 19 August 2018 в 03:38
поделиться

Как уже упоминалось в комментариях к ответу @Islam Q, представленное решение может потерпеть неудачу, если UINavigationItem в настоящее время не отображается на экране. Он не работает, например, если контроллер просмотра в настоящий момент не загружен. Фактически проблема заключается в недостатке макета UINavigationBar в этих случаях.

Более «пуленепробиваемой» версией будет использование специально созданного объекта UINavigationBar только для получения изображений элементов системы. Это также сделает сохранение и восстановление любых существующих UIBarButtonItems устаревшими.

Я упаковал это в небольшой вспомогательный класс:

LEABarButtonSystemItemImage.h:

#import <UIKit/UIKit.h>


/**
 LEABarButtonSystemItemImage interface

 */
@interface LEABarButtonSystemItemImage : NSObject

+ (UIImage *)imageFromBarButtonSystemItem:(UIBarButtonSystemItem)pBarButtonSystemItem;
+ (UIImage *)customImageForBarButtonSystemItem:(UIBarButtonSystemItem)pBarButtonSystemItem;

+ (NSDictionary<__kindof NSNumber*, __kindof UIImage*> *)barButtonItemImages;

@end

LEABarButtonSystemItemImage.m

#import "LEABarButtonSystemItemImage.h"


/**
 LEABarButtonSystemItemImage implementation

 */
@implementation LEABarButtonSystemItemImage

/*
 imageFromBarButtonSystemItem:

 */
+ (UIImage *)imageFromBarButtonSystemItem:(UIBarButtonSystemItem)pBarButtonSystemItem {

    static const CGFloat    defaultNBBtnHW  = 44.0;

    UINavigationBar *   tempNavigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, defaultNBBtnHW, defaultNBBtnHW)];
    UINavigationItem *  tempNavigationItem = [[UINavigationItem alloc] init];
    UIBarButtonItem *   tempBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:pBarButtonSystemItem target:nil action:NULL];

    tempNavigationBar.items = @[tempNavigationItem];
    tempNavigationItem.rightBarButtonItems = @[tempBarButtonItem];

    UIImage *           barButtonSystemItemImage = nil;
    @try {
        UIView *        barButtonItemView = [tempBarButtonItem valueForKey:@"view"];
        for (UIView* subview in barButtonItemView.subviews) {
            if ([subview isKindOfClass:UIImageView.class]) {
                barButtonSystemItemImage = ((UIImageView *)subview).image;
                break;
            }
        }
    } @catch (...) { NSLog(@"%s: Exception while retrieving image from UIBarButtonItem!", __PRETTY_FUNCTION__); }

    return (barButtonSystemItemImage ?: [LEABarButtonSystemItemImage customImageForBarButtonSystemItem:pBarButtonSystemItem]);
}

/*
 customImageForBarButtonSystemItem:

 */
+ (UIImage *)customImageForBarButtonSystemItem:(UIBarButtonSystemItem)pBarButtonSystemItem {

    NSString *  customBarButtonSystemItemImageName = nil;
    switch (pBarButtonSystemItem) {
        case UIBarButtonSystemItemDone:             customBarButtonSystemItemImageName = @"customBarButtonSystemItemDone";          break;
        case UIBarButtonSystemItemCancel:           customBarButtonSystemItemImageName = @"customBarButtonSystemItemCancel";        break;
        case UIBarButtonSystemItemEdit:             customBarButtonSystemItemImageName = @"customBarButtonSystemItemEdit";          break;
        case UIBarButtonSystemItemSave:             customBarButtonSystemItemImageName = @"customBarButtonSystemItemSave";          break;
        case UIBarButtonSystemItemAdd:              customBarButtonSystemItemImageName = @"customBarButtonSystemItemAdd";           break;
        case UIBarButtonSystemItemCompose:          customBarButtonSystemItemImageName = @"customBarButtonSystemItemCompose";       break;
        case UIBarButtonSystemItemReply:            customBarButtonSystemItemImageName = @"customBarButtonSystemItemReply";         break;
        case UIBarButtonSystemItemAction:           customBarButtonSystemItemImageName = @"customBarButtonSystemItemAction";        break;
        case UIBarButtonSystemItemOrganize:         customBarButtonSystemItemImageName = @"customBarButtonSystemItemOrganize";      break;
        case UIBarButtonSystemItemBookmarks:        customBarButtonSystemItemImageName = @"customBarButtonSystemItemBookmarks";     break;
        case UIBarButtonSystemItemSearch:           customBarButtonSystemItemImageName = @"customBarButtonSystemItemSearch";        break;
        case UIBarButtonSystemItemRefresh:          customBarButtonSystemItemImageName = @"customBarButtonSystemItemRefresh";       break;
        case UIBarButtonSystemItemStop:             customBarButtonSystemItemImageName = @"customBarButtonSystemItemStop";          break;
        case UIBarButtonSystemItemCamera:           customBarButtonSystemItemImageName = @"customBarButtonSystemItemCamera";        break;
        case UIBarButtonSystemItemTrash:            customBarButtonSystemItemImageName = @"customBarButtonSystemItemTrash";         break;
        case UIBarButtonSystemItemPlay:             customBarButtonSystemItemImageName = @"customBarButtonSystemItemPlay";          break;
        case UIBarButtonSystemItemPause:            customBarButtonSystemItemImageName = @"customBarButtonSystemItemPause";         break;
        case UIBarButtonSystemItemRewind:           customBarButtonSystemItemImageName = @"customBarButtonSystemItemRewind";        break;
        case UIBarButtonSystemItemFastForward:      customBarButtonSystemItemImageName = @"customBarButtonSystemItemFastForward";   break;
        case UIBarButtonSystemItemUndo:             customBarButtonSystemItemImageName = @"customBarButtonSystemItemUndo";          break;
        case UIBarButtonSystemItemRedo:             customBarButtonSystemItemImageName = @"customBarButtonSystemItemRedo";          break;
        case UIBarButtonSystemItemPageCurl:         customBarButtonSystemItemImageName = @"customBarButtonSystemItemPageCurl";      break;
        default:    break;
    }

    return (customBarButtonSystemItemImageName
            ? [UIImage imageNamed:customBarButtonSystemItemImageName]
            : nil);
}

/*
 barButtonItemImages

 */
+ (NSDictionary<__kindof NSNumber*, __kindof UIImage*> *)barButtonItemImages {

    NSMutableDictionary<__kindof NSNumber*, __kindof UIImage*> *    barButtonItemImages = [NSMutableDictionary dictionary];
    // From:    https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/UIKit.framework/UIBarButtonItem.h
    //          unsigned int systemItem : 7;
    for (NSUInteger uIndex = 0; uIndex < (1<<7); ++uIndex) {
        UIImage*    systemImage = [LEABarButtonSystemItemImage imageFromBarButtonSystemItem:uIndex];
        if (systemImage) {
            [barButtonItemImages setObject:systemImage forKey:@(uIndex)];
        }
    }
    NSLog(@"%s: %@", __PRETTY_FUNCTION__, barButtonItemImages);
    return barButtonItemImages;
}

@end

Как добавление / отключение, метод возвращает пользовательский образ, если изображение системы не может быть восстановлено. Конечно, эти пользовательские изображения должны присутствовать в пакете приложений.

Последний метод «barButtonImages» был реализован только для любопытства ... в заголовке UIBarButtonItem член systemItem объявлен для использования 7 бит (0. 0,127). В настоящее время только 22 значения документируются из UIBarButtonSystemItemDone в UIBarButtonItemSystemItemPageCurl ... и фактически; Я нашел некоторые недокументированные изображения, начиная с индексов выше 100 (тестировался на iOS 9.3 в симуляторе 6S +): -)

4
ответ дан LaborEtArs 19 August 2018 в 03:38
поделиться

Я использовал его для imageView в ячейке таблицы, и как-то оттенок цвета не работал, где бы я его не установил ... Итак, я закончил с этим кодом, где вы задали цвет для изображения.

+ (UIImage *)imageFromSystemBarButton:(UIBarButtonSystemItem)systemItem :(UIColor *) color {
    UIToolbar *bar = UIToolbar.new;
    UIBarButtonItem *buttonItem = [UIBarButtonItem createWithItem:systemItem];
    [bar setItems:@[buttonItem] animated:NO];
    [bar snapshotViewAfterScreenUpdates:YES];
    for (UIView *view in [(id) buttonItem view].subviews)
        if ([view isKindOfClass:UIButton.class]) {
            UIImage *image = [((UIButton *) view).imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
            UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
            [color set];
            [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
            image = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            return image;
    }
    return nil;
}
0
ответ дан Renetik 19 August 2018 в 03:38
поделиться
0
ответ дан eharo2 30 October 2018 в 15:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: