Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа 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; причина использования Трассировки стека
Загрузите изображение где-нибудь в Интернете, добавьте его в свой проект и установите изображение UIButton
на только что загруженное изображение.
Я не нашел то же, что использовал Apple но я нашел этот . Просто измените цвет в Pixelmator или Photoshop.
Вот решение, которое работает с элементом кнопки 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. Не стесняйтесь улучшаться, если знаете лучший способ, спасибо.
UIView *itemView = (UIView *)[self.navigationItem.rightBarButtonItem performSelector:@selector(view)];
в Свифт?
– Hans Brende
20 November 2015 в 00:16
На основании ответа @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)
tempItem.value(forKey: "view")
- это нуль, а принудительная развертка дает ошибку.
– Denis Balko
8 August 2017 в 13:27
2017/10/05 не работает в iOS 11.0.1
blockquote>для быстрого 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; }
Все значки системы iOS можно извлечь, используя удобное небольшое приложение (достаточно подходящее) iOS Artwork Extractor. Я использую его все время, когда я хочу имитировать поведение системы iOS.
Загрузите проект Xcode по адресу:
Как уже упоминалось в комментариях к ответу @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 +): -)
Я использовал его для 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;
}
tintColor
. Не должно быть проблем, поскольку вы можете просто изменить его цвет в Photoshop или Pixelmator. – yoeriboven 17 January 2014 в 16:32