• 自定义控件.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;

}


关于iOS自定义控件:在view上实现事件和代理的更多相关文章

  1. iOS 自定义控件开发(上)

    工作需要,最近在进行iOS方面的图表工作.找了很多第三方库都无法实现效果,所以决定自己写一个控件. <iOS 自定义控件开发(上)> <iOS 自定义控件开发(中)> #0 目 ...

  2. iOS 自定义控件开发(中)

    <iOS 自定义控件开发(上)> <iOS 自定义控件开发(中)> 接上篇iOS自定义控件开发之后,我们尝试另外一种. 在Xcode的右边,会看到如下的图 其中,上面有一个:C ...

  3. android view、viewgroup 事件响应拦截处理机制

    文章中会用到部分网络资源,首先将原作者的链接附上. 但是还是会附上数量较大的关于此部分内容的自己的思考. ----------------------------------------------- ...

  4. view上添加点手势 button无法响应点击事件

    在view 上添加手势 有的时候  会把Button的 点击事件盖掉,这个 时候 我们用UITapGestureRecognizer的代理方法 //手势的代理方法 - (BOOL)gestureRec ...

  5. AJ学IOS 之控制器view显示中view的父子关系及controller的父子关系_解决屏幕旋转不能传递事件问题

    AJ分享,必须精品 一:效果 二:项目代码 这个Demo用的几个控制器分别画了不通的xib,随便拖拽了几个空间,主要是几个按钮的切换,主要代码展示下: // // NYViewController.m ...

  6. iOS constraint被应用于view上的时间

    在viewdidload时,constraint是没有被应用的,之后在layoutSubviews时,系统应用了constraint.但是我感觉在viewWillLayoutSubviews函数时就已 ...

  7. iOS自定义控件教程:制作一个可重用的旋钮

    当你的APP需要一些新功能时,自定义UI控件会十分有用,尤其是这些自定义控件可以在其他APP里面很好的重用.Colin Eberhart写过一篇很棒的介绍自定义UI控件的教程.这个教程涉及的是一个继承 ...

  8. iOS 开发总结(上)

    来源:蝴蝶之梦天使 链接:http://www.jianshu.com/p/d333cf6ae4b0 在iOS开发中经常需要使用的或不常用的知识点的总结,几年的收藏和积累(踩过的坑). 一. iPho ...

  9. [iOS UI进阶 - 3.1] 触摸事件的传递

    A.事件的产生和传递 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发 ...

随机推荐

  1. Struts2的运行机制简介

    1.客户端通过URL请求tomcat 2.URL找到对应站点的WEB.xml  发现里面有  struts2配置 3.执行StrutsPrepareAndExecuteFilter类的init方法 4 ...

  2. 简单粗暴的“Debug模式”

    在项目中,通常会遇到:调试程序和程序在线上运行时程序运行的参数不一样, 例如线上运行时程序是获取线上的机器的ip,而调试程序时,我们会指定一个ip进行调试. 又或者项目要与多个系统进行数据交换,调试的 ...

  3. oracle-查询执行速度慢的sql

    Oracle 查询每天执行慢的SQL 2014-12-11 18:00:04 分类: Oracle 链接:http://blog.itpub.net/28602568/viewspace-136484 ...

  4. eclipse的调试方法的简单介绍

    声明:本文不是自己 作为编程人员,程序的调试是一项基本功.在不使用IDE的时候,程序的调试多数是通过日志或者输入语句(System.out.println)的方式.可以把程序运行的轨迹或者程序运行过程 ...

  5. loadrunner基本概念、安装及术语(一)

    一.初识loadrunner: LoadRunner,是一种预测系统行为和性能的负载测试工具.通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题,LoadRunner能够对整个企业架 ...

  6. http://www.iteye.com/job/topic/1133159

    Lucene 的索引体系是一个写独占,读共享的结构,这意味着,我们在使用多线程进行添加索引时,性能并不会得到明显的提升,所以任何时刻只能有一个线程对索引进行写 入操作,而保障这个操作的安全性则是来自于 ...

  7. CDN(转载)

    CDN是什么? 谈到CDN的作用,可以用8年买火车票的经历来形象比喻: 8年前,还没有火车票代售点一说,12306.cn更是无从说起.那时候火车票还只能在火车站的售票大厅购买,而我所住的小县城并不通火 ...

  8. jquery_api(CSS)

    outerWidth([options]) 获取第一个匹配元素外部宽度(默认包括补白和边框). 此方法对可见和隐藏元素均有效. outerHeight([options]) 获取第一个匹配元素外部高度 ...

  9. js 判断网页类型

    <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>标题页</title ...

  10. 关于Context []startup failed due to previous errors有效解决方式

    http://blog.csdn.net/mcpang/article/details/5468386