關於iOS自定義控件:在view上實現事件和代理


  • 自定義控件.h

#import <UIKit/UIKit.h>

#import "PPViewtouchesBeginDelegate.h"

 

@interface PPView : UIView

 

// 這樣寫避免了內存泄露的問題

@property (nonatomic, strong)UIView *Pview;

 

// 保存鼠標點擊在父視圖上的位置和子視圖的偏移量

@property (nonatomic, assign)CGPoint plusPoint;

 

// 接收傳遞過來的方法和對象:在touchesBegin時使用該對象調用該包裝的方法

@property (nonatomic, strong)id sender;

@property (nonatomic, assign)SEL action;

// 代碼加載完畢,通過方法實現保存了該對象和需要調用的SEL

- (void)addTarget:(id)target andAction:(SEL)action;

 

// 點擊view顯示字符串

@property (nonatomic, strong)NSString *PPText;

// 限定合適的代理(弱引用):觸發是view被點擊時

@property (nonatomic, weak)id<PPViewtouchesBeginDelegate> delegate;

@end


  • 自定義控件代理

#import <Foundation/Foundation.h>

 

// 誰成為我的代理,誰就屬於了我的類型:反向傳值(代理應用_2)

@class PPView;

@protocol PPViewtouchesBeginDelegate <NSObject>

 

// - 確保傳遞出去的形參可以訪問屬性:誰觸發就把誰傳遞出去

- (void)touchesPPVoewBegin:(PPView *)sender;

@end


 

  •  自定義控件.m

#import "PPView.h"

 

@implementation PPView

 

// 1.在原view基礎上添加了一個view:每次創建自定義view就會自帶一個添加了的view

- (instancetype)initWithFrame:(CGRect)frame

{

    // - 讓該視圖在被創建的父視圖的中央

    if (self = [super initWithFrame:frame])

    {

        // > 父類初始化成功后才給子類的frame賦值

        CGFloat width = self.frame.size.width;

        CGFloat height = self.frame.size.height;

        

        // > 需要創建對象

        _Pview = [[UIView alloc] initWithFrame:CGRectMake(width/4, height/4, width/2, height/2)];

        _Pview.backgroundColor = [UIColor purpleColor];

        

        // > 在傳遞過來的父視圖上添加主視圖,而不是在主視圖上:self.view

        [self addSubview:_Pview];

    }

    return self;

}

 

// 2.讓添加的view能在父視圖上移動

 

// - 基於原來的位置移動,而不是把view的center帶到了鼠標點擊的位置

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{

    // > 先記錄下點擊當前視圖的位置

    

    // * 獲取點擊的位置的坐標:通過方法傳遞過來的形參獲取

     CGPoint clickPoint = [[touches anyObject] locationInView:self];

    

    // * 獲取的坐標是相同的

    //[[touches anyObject] previousLocationInView:self];

    

    // > 保存主視圖的中心點和鼠標點擊位置的差值

    _plusPoint.x = _Pview.center.x - clickPoint.x;

    _plusPoint.y = _Pview.center.y - clickPoint.y;

    

   

    // 3.通過保存的對象和SEL:在touchesBegin時使用該對象調用該包裝的方法

    // 注意:是調用被打包的方法,即點擊view后傳遞過來的方法;而不是該類中自定義的事件

    [self.sender performSelector:self.action];

    

    

    // 4.代理:在點擊view時讓view顯示屬性(字符串):系統的TouchesBegin事件觸發時

    // - 判斷代理是否為空

    if (self.delegate!=nil)

    {

        // 判斷代理是否實現了協議內方法

        if ([self.delegate respondsToSelector:@selector(touchesPPVoewBegin:)])

        {

            // >復合是思想:代理被使用代理的類所復合,通過代理調用了代理遵循的方法

            // > 確保傳遞出去的形參可以訪問屬性:誰觸發就把誰傳遞出去

            [self.delegate touchesPPVoewBegin:self];

        }

    }else

    {

        NSLog(@"delegate = nil");

    }

    

}

 

// - 讓鼠標的移動和子視圖的距離變得固定

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{

    CGPoint clickPoint = [[touches anyObject] locationInView:self];

    // > 保存鼠標點擊父視圖上的位置:這個值是不斷變化的

    _Pview.center = (CGPoint){clickPoint.x+_plusPoint.x, clickPoint.y+_plusPoint.y};

}

 

// 3.在view上實現了button的效果

// - 觸發事件時就保存了傳遞過來的對象和被打包的方法

- (void)addTarget:(id)target andAction:(SEL)action

{

    // - 代碼加載完畢,通過方法實現保存了該對象和需要調用的SEL

    self.sender = target;

    self.action = action;

    

}


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM