Encapsulates a TabBarItem--封裝一個BarButtonItem類
- 在我們程序的導(dǎo)航欄的左邊或右邊一般都會有這樣的BarButtonItem,用來界面之間的跳轉(zhuǎn)
- 如果我們有很多的控制器,那么我們就會有很多的BarButtonItem要寫
- 所以我們要對它進行封裝,今后可以更方便的使用它,拿起來就可以用

-
有幾個小點:
- 代碼設(shè)置按鈕尺寸和要設(shè)置的圖片尺寸一樣
第一種方式:
UIImage *image = [UIImage imageNamed:@"tupian"];
UIImage *image =[button backgroundImageForState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, image.size.width, image.size.height);
第二種方式:
UIImage *image = [UIImage imageNamed:@"tupian"];
UIImage *image = button.currentbackgrundImage;
button.frame = CGRectMake(0, 0, image.size.width, image.size.height);
第三種方式:
UIImage *image = [UIImage imageNamed:@"tupian"];
UIImage *image =[button backgroundImageForState:UIControlStateNormal];
[button sizeToFit];
- 每一個導(dǎo)航控制器都可以設(shè)置對應(yīng)的按鈕
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:@"MainTagSubIcon"] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:@"MainTagSubIconClick"] forState:UIControlStateHighlighted];
[button sizeToFit];
[button addTarget:self action:@selector(CYEssenceClick) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
- (void)CYEssenceClick
{
NSLog(@"%s",__func__);
}
- 如果設(shè)置的按鈕一邊有兩個,就放在數(shù)組中,數(shù)組中的順序和它顯示的順序有關(guān)

UIButton *moonButton = [UIButton buttonWithType:UIButtonTypeCustom];
[moonButton setBackgroundImage:[UIImage imageNamed:@"mine-moon-icon"] forState:UIControlStateNormal];
[moonButton setBackgroundImage:[UIImage imageNamed:@"mine-moon-icon-click"] forState:UIControlStateHighlighted];
[moonButton sizeToFit];
[moonButton addTarget:self action:@selector(moonClick) forControlEvents:UIControlEventTouchUpInside];
UIButton *settingButton = [UIButton buttonWithType:UIButtonTypeCustom];
[settingButton setBackgroundImage:[UIImage imageNamed:@"mine-setting-icon"] forState:UIControlStateNormal];
[settingButton setBackgroundImage:[UIImage imageNamed:@"mine-setting-icon-click"] forState:UIControlStateHighlighted];
[settingButton sizeToFit];
[settingButton addTarget:self action:@selector(settingClick) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.rightBarButtonItems = @[
[[UIBarButtonItem alloc] initWithCustomView:settingButton],
[[UIBarButtonItem alloc] initWithCustomView:moonButton]
];
- (void)moonClick
{
NSLog(@"%s",__func__);
}
- (void)settingClick
{
NSLog(@"%s",__func__);
}
- 從上面也可以看出來:這樣寫的話,代碼量就多了,所以要進行代碼的封裝
第一種方式
- 新建一個ItemTool類
- CYItemTool.h文件中
#import <UIKit/UIKit.h>
@interface CYItemTool : NSObject
+ (UIBarButtonItem *)itemWithImage:(NSString *)image highImage:(NSString *)highImage target:(id)target action:(SEL)action;
@end
- CYItemTool.m文件中
#import "CYItemTool.h"
@implementation CYItemTool
+ (UIBarButtonItem *)itemWithImage:(NSString *)image highImage:(NSString *)highImage target:(id)target action:(SEL)action
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:highImage] forState:UIControlStateHighlighted];
[button sizeToFit];
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
return [[UIBarButtonItem alloc] initWithCustomView:button];
}
@end
- 因為這個抽取的工具類在項目中很多地方基本都能用到,所以寫入到pch文件之中
- pch文件中
#ifndef ___________0901_PrefixHeader_pch
#define ___________0901_PrefixHeader_pch
#import <UIKit/UIKit.h>
#import "CYItemTool.h"
// Include any system framework and library headers here that should be included in all compilation units.
// You will also need to set the Prefix Header build setting of one or more of your targets to reference this file.
// 日志輸出
#ifdef DEBUG // 開發(fā)階段 -DEBUG階段:使用Log
#define CYLog(...) NSLog(__VA_ARGS__)
#else // 發(fā)布階段——上線階段:移除Log
#define CYLog(...)
#endif
// 方法輸出
#define CYLogFunc CYLog(@"%s",__func__)
#endif
第二種方式
新建一個擴展類(更推薦這種)
也就是對UIBarButtonItem這個類擴充方法
UIBarButtonItem+CYExtension.h文件中:
#import <UIKit/UIKit.h>
@interface UIBarButtonItem (CYExtension)
+ (instancetype)itemWithImage:(NSString *)image highImage:(NSString *)highImage target:(id)target action:(SEL)action;
@end
- UIBarButtonItem+CYExtension.m文件中
#import "UIBarButtonItem+CYExtension.h"
@implementation UIBarButtonItem (CYExtension)
+ (instancetype)itemWithImage:(NSString *)image highImage:(NSString *)highImage target:(id)target action:(SEL)action
{
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:highImage] forState:UIControlStateHighlighted];
[button sizeToFit];
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
return [[self alloc] initWithCustomView:button];
}
}
@end
- 同樣將頭文件導(dǎo)入到pch文件中去
#ifndef ___________0901_PrefixHeader_pch
#define ___________0901_PrefixHeader_pch
#import <UIKit/UIKit.h>
#import "UIBarButtonItem+CYExtension.h"
// Include any system framework and library headers here that should be included in all compilation units.
// You will also need to set the Prefix Header build setting of one or more of your targets to reference this file.
// 日志輸出
#ifdef DEBUG // 開發(fā)階段 -DEBUG階段:使用Log
#define CYLog(...) NSLog(__VA_ARGS__)
#else // 發(fā)布階段——上線階段:移除Log
#define CYLog(...)
#endif
// 方法輸出
#define CYLogFunc CYLog(@"%s",__func__)
#endif
- 那么在封裝后我們在每個控制器去設(shè)置它們各自的BarButtonItem的時候,就可以這么去設(shè)置了
- 上面圖中的例子
#import "CYMeViewController.h"
#import "CYSettingViewController.h"
@interface CYMeViewController ()
@end
@implementation CYMeViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"我的";
// 我的導(dǎo)航欄右邊的內(nèi)容
UIBarButtonItem *moonButton = [UIBarButtonItem itemWithImage:@"mine-moon-icon" highImage:@"mine-moon-icon-click" target:self action:@selector(moonClick)];
UIBarButtonItem *settingButton = [UIBarButtonItem itemWithImage:@"mine-setting-icon" highImage:@"mine-setting-icon-click" target:self action:@selector(settingClick)];
self.navigationItem.rightBarButtonItems = @[settingButton,moonButton];
}
- (void)moonClick
{
CYLogFunc
}
- (void)settingClick
{
CYSettingViewController *setting = [[CYSettingViewController alloc] init];
[self.navigationController pushViewController:setting animated:YES];
}
@end
- 在另外一個控制器的設(shè)置,同樣
#import "CYFocusViewController.h"
@interface CYFocusViewController ()
@end
@implementation CYFocusViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"我的關(guān)注";
// 設(shè)置導(dǎo)航欄左邊的內(nèi)容
self.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithImage:@"friendsRecommentIcon" highImage:@"friendsRecommentIcon-click" target:self action:@selector(CYFocusViewClick)];
}
- (void)CYFocusViewClick
{
CYLogFunc
UITableViewController *focus = [[UITableViewController alloc] init];
focus.navigationItem.title = @"百科不是全書";
[self.navigationController pushViewController:focus animated:YES];
}
這樣就方便多了,直接調(diào)用方法,也不用擔(dān)心會寫錯
個人愚見--不管是新建一個類還是擴展一個類,都是差不多的,也看個人喜好。但是實際開發(fā)中,類方法的擴展可能有成百上千個的時候,你一個個新建類的話,不太現(xiàn)實,所以為了追求最優(yōu)化方案還是采用第二種方法吧!至少好記好用點吧!
稍后的時間,我會盡量將一些封裝的東西都整理出來,敬請關(guān)注!
下面的內(nèi)容,感興趣的朋友可以研究一下!
擴充說明--類別
網(wǎng)上copy過來的,有助于大家理解為什么選用類別優(yōu)于新建一個類
下面文字copy源于:http://www.2cto.com/kf/201502/376993.html
原文內(nèi)容如下:
類別是一種為現(xiàn)有的類添加新方法的方式
利用Objective-C的動態(tài)運行時分配機制,可以為現(xiàn)有的類添加新方法,這種為現(xiàn)有的類添加新方法的方式稱為類別catagory。
他可以為任何類添加新的方法,包括那些沒有源代碼的類。
類別使得無需創(chuàng)建對象類的子類就能完成同樣的工作
創(chuàng)建類別
- 1、聲明類別聲明類別與聲明類的形式很相似
@interface NSString(NumberConvenience)-(NSNumber *)lengthAsNumber;@end//NumberConvenience
- 這個聲明有兩個特點:
- (1)現(xiàn)有的類位于@interface關(guān)鍵字之后,其后是位于圓括號中的類別名稱。
+ 類別名稱是NumberConvenience
+ 而且該類別將向NSString類中添加方法
+ 換句話說:“我們向NSString類中添加一個名稱為NumberConvenience的類別。
+ 同名類別有唯一性,但是可以添加任意多的不同名類別。 - (2)可以執(zhí)行希望向其添加類別的類以及類別的名稱,還可以列出添加的方法不可以添加新的實例變量,類別生命中沒有實例變量部分。
- (1)現(xiàn)有的類位于@interface關(guān)鍵字之后,其后是位于圓括號中的類別名稱。
- 2、實現(xiàn)類別
@implementation NSString(NumberConvenience)-(NSNumber *)lengthAsNumber{unsigned int length = [self length];return ([NSNumber numberWithUnsignedInt : length]);} **//lengthAsNumber**@end **//NumberConvenience
- 在實現(xiàn)部分也包括類名、類別名和新方法的實現(xiàn)代碼
-
3、類別的局限性有兩方面局限性:
- (1)無法向類中添加新的實例變量,類別沒有位置容納實例變量。
- (2)名稱沖突,即當類別中的方法與原始類方法名稱沖突時,類別具有更高的優(yōu)先級。類別方法將完全取代初始方法從而無法再使用初始方法。無法添加實例變量的局限可以使用字典對象解決
-
4、類別的作用
- 類別主要有3個作用:
- (1)將類的實現(xiàn)分散到多個不同文件或多個不同框架中。
- (2)創(chuàng)建對私有方法的前向引用。
- (3)向?qū)ο筇砑臃钦絽f(xié)議。 繼承可以增加,修改或者刪除方法,并且可以增加屬性。
- 類別主要有3個作用:
另外一篇
類別
有時我們需要在一個已經(jīng)定義好的類中增加一些方法,而不想去重寫該類。比如,當工程已經(jīng)很大,代碼量比較多,或者類中已經(jīng)包住很多方法,已經(jīng)有其他代碼調(diào)用了該類創(chuàng)建對象并使用該類的方法時,可以使用類別對該類擴充新的方法。
注意:類別只能擴充方法,而不能擴充成員變量。-
實例分析:
- 1、目的:在我的工程中,我需要對圖片進行壓縮,此時我想到類別,利用類別對UIImage類進行擴展,增加圖片壓縮方法。
- 2、類別定義:
類別.h聲明文件
#import <Foundation/Foundation.h>
@interface UIImage (UIImageExt)
//這個方法就是我添加的圖片壓縮的方法
- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize;
@end
- 類別.m實現(xiàn)文件
#import "UIImageExt.h"
@implementation UIImage (UIImageExt)
- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize
{
UIImage *sourceImage = self;
UIImage *newImage = nil;
CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
CGPoint thumbnailPoint = CGPointMake(0.0,0.0);
if (CGSizeEqualToSize(imageSize, targetSize) == NO)
{
CGFloat widthFactor = targetWidth / width;
CGFloat heightFactor = targetHeight / height;
if (widthFactor > heightFactor)
scaleFactor = widthFactor; // scale to fit height
else
scaleFactor = heightFactor; // scale to fit width
scaledWidth= width * scaleFactor;
scaledHeight = height * scaleFactor;
// center the image
if (widthFactor > heightFactor)
{
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
}
else if (widthFactor < heightFactor)
{
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
}
UIGraphicsBeginImageContext(targetSize); // this will crop
CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width= scaledWidth;
thumbnailRect.size.height = scaledHeight;
[sourceImage drawInRect:thumbnailRect];
newImage = UIGraphicsGetImageFromCurrentImageContext();
if(newImage == nil)
NSLog(@"could not scale image");
//pop the context to get back to the default
UIGraphicsEndImageContext();
return newImage;
}
@end
- 3、如何使用類別
- 在上文我已經(jīng)對UIImage進行了擴展,下面如何將演示在我的工程中如何調(diào)用該方法:
//根據(jù)圖片tag顯示圖片
-(void)showPhotoBySerialNumber:(int)imageTag;
{
//這個largeImageArray是NSMutableArray類型的,存放圖片存儲路徑,根據(jù)路徑得到UIImage
UIImage *img = [UIImage imageWithContentsOfFile:[self.largeImageArray objectAtIndex:imageTag]];
//MyScrollView是我自定義的ScrollView,目的是使ScrollView響應(yīng)點擊事件,關(guān)于如何自定義的ScrollView在以后的博客中,我將會闡述
MyScrollView *scrView = [[MyScrollView alloc] initWithFrame:CGRectMake(340*imageTag, 0, 320, 480)];
scrView.host = self;
//這句就是調(diào)用了類別,通過UIImage實例對象,調(diào)用imageByScalingAndCroppingForSize:類別
scrView.image = [img imageByScalingAndCroppingForSize:CGSizeMake(320.0, 480.0)];
scrView.tag = imageTag+100;
//下面這句,就是把上面的scrView塞到imageScrollView上,imageScrollView是UIScrollView類型
[self.imageScrollView addSubview:scrView];
[scrView release];
}
二、協(xié)議
協(xié)議(protocol)類似于java語言里的接口(interface),定義了一組方法,而不提供具體實現(xiàn), 只有那些“遵守”(conform to)或“采用”(adopt)了這些Protocol的類來給出自己的實現(xiàn)。
協(xié)議不是類本身,它們僅定義了其它對象有責(zé)任實現(xiàn)的接口。當在自己的類中實現(xiàn)協(xié)議的方法時,用戶的類就是遵守這個協(xié)議的,協(xié)議聲明的方法可以被任何一個類實現(xiàn)。
1、協(xié)議的語法結(jié)構(gòu)如下:
@protocol ProtocolName //協(xié)議名
methodDeclaration; //方法名 @end
- 2、如何使用協(xié)議
- 而在類聲明時,語法如下:
@interface ClassName : ParentClassName < ProtocolName>
- 然后在該類的實現(xiàn)文件中,實現(xiàn)該協(xié)議的方法methodDeclaration
實例分析
- 下面以在我的工程項目中協(xié)議的使用方法,這里只要講我自己定義的協(xié)議。
- 1)該實例的目的:使在ScrollView上面的UIImageView響應(yīng)點擊事件
- 2)協(xié)議定義:
- 在類的.h聲明文件中定義協(xié)議
#import <Foundation/Foundation.h>
//協(xié)議ImageTouchDelegate
@protocol ImageTouchDelegate
//協(xié)議中聲明的方法
-(void)imageTouch:(NSSet *)touches withEvent:(UIEvent *)event whichView:(id)imageView;
@end
@interface ImageTouchView : UIImageView {
id<ImageTouchDelegate> delegate;
}
@property(nonatomic,assign)id<ImageTouchDelegate> delegate;
@end
- 該類的.m實現(xiàn)文件如下
#import "ImageTouchView.h"
@implementation ImageTouchView
@synthesize delegate;
-(id)initWithFrame:(CGRect)frame
{
if (self == [super initWithFrame:frame])
{
[self setUserInteractionEnabled:YES];
}
return self;
}
-(BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
{
return YES;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[delegate imageTouch:touches withEvent:event whichView:self];
}
@end
-
3)如何使用協(xié)議?
前面我已經(jīng)定義了ImageTouchDelegate,那么如何使用該協(xié)議的方法呢?
當某個類要采用該協(xié)議時,在類的聲明中列出協(xié)議的名稱即可,如果要采用多個協(xié)議時,在后面的尖括號中以逗號分隔,加入即可。
當在類采用了該協(xié)議時,就要在除了.h文件中進行聲明外,還必須在它的.m實現(xiàn)文件中對聲明的協(xié)議中的方法進行實現(xiàn)。還以上述我們已經(jīng)定義好的協(xié)議為例,演示在我的工程中如何實現(xiàn)該協(xié)議。
在我的類中,首先在.h聲明文件中,采用協(xié)議ImageTouchDelegate
#import <UIKit/UIKit.h>
//引入定義協(xié)議ImageTouchDelegate的頭文件
#import "ImageTouchView.h"
//把協(xié)議名放到父頭后面的尖括號里面,如果有多個協(xié)議,用逗號分隔
@interface PhotoOnShotViewController : UIViewController<ImageTouchDelegate> {
}
@end
- 下面要在類的.m實現(xiàn)文件中實現(xiàn)該協(xié)議定義的方法
#import "PhotoOnShotViewController.h"
@implementation PhotoOnShotViewController
//實現(xiàn)協(xié)議中定義的方法,
-(void)imageTouch:(NSSet *)touches withEvent:(UIEvent *)event whichView:(id)imageView{
}
- 可以的話,Give me a star!