項目開發(fā)中封裝一個BarButtonItem類別-很實用

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)化方案還是采用第二種方法吧!至少好記好用點吧!

  • 源碼地址:https://github.com/Tuberose621/-BarButtonItem---

  • 稍后的時間,我會盡量將一些封裝的東西都整理出來,敬請關(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í)行希望向其添加類別的類以及類別的名稱,還可以列出添加的方法不可以添加新的實例變量,類別生命中沒有實例變量部分。
  • 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é)議。 繼承可以增加,修改或者刪除方法,并且可以增加屬性。

另外一篇

類別

  • 有時我們需要在一個已經(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!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 蘋果官方文檔翻譯 《Objective-C語言編程》(Programming with Objective-C) ...
    fever105閱讀 26,321評論 19 129
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,617評論 30 472
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評論 19 139
  • 我這一生渴望被人收藏好,妥善安放,細心保存。那個免我驚,免我苦,免我四下流離,免我無枝可依的人。 我知,我一直知,...
    靡恃閱讀 552評論 0 0
  • (一) 世上本無所謂苦,無所謂痛,因為世事本無所謂好或壞。 世間的能量流動是對等的。 God will hug m...
    情愿簡單閱讀 194評論 0 1

友情鏈接更多精彩內(nèi)容