加载带有手势识别器的XIB文件时的注意事项

  首先新建一个继承自UIView的类,并创建相应的XIB文件

#import <UIKit/UIKit.h>

@interface ZHDemoView : UIView

+ (instancetype)demoView;

@end

  提供一个类方法以供快速创建当前类

  在.m中实现类方法,通常从XIB中加载出来的是一个数组,所以用到了lastObject方法

+ (instancetype)demoView
{
    NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:@"ZHDemoView" owner:nil options:nil];
    return [nibArray lastObject];
}

  在awakeFromNib中添加相应的手势

- (void)awakeFromNib
{
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click)];
    [self addGestureRecognizer:tap];
}

- (void)click
{
    NSLog(@"%s", __func__);
}

  另外,测试用的XIB长这样:

  在根控制器添加一个这样的View,运行并点击,结果是

2015-08-11 13:44:44.988 XIB注意[1797:362096] -[ZHDemoView click]

  一切正常,接下来我们不在代码中添加手势,直接在XIB中添加(之前添加手势的代码已清除):

  运行结果:

2015-08-11 14:02:12.747 XIB注意[1962:374487] -[UITapGestureRecognizer superview]: unrecognized selector sent to instance 0x7fe47af49c60

  可以看到是消息发送错误,UITapGestureRecognizer中没有superview方法。

  回到这张图

  

  我们可以看到Objects栏下方有手势识别器和DemoView两个对象,那么是否有可能是因为XIB加载的对象错误呢?

  因为之前提供的类方法中我们使用的是lastObject方法,这次我们使用firstObject试一试

  更改类方法如下:

+ (instancetype)demoView
{
    NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:@"ZHDemoView" owner:nil options:nil];
    return [nibArray firstObject];
}

  结果:

2015-08-11 14:13:16.847 XIB注意[2064:382058] -[ZHDemoView click:]

  一切正常。

结论:

  从XIB加载出来的是一个对象数组,通常情况下,我们只需要用到一个对象,此时用firstObject或者lastObject皆可。但是当你要使用手势识别器时,别弄错你取出的对象。建议不要在XIB中直接添加手势识别器,通过代码手动创建更稳妥和易于维护。

时间: 2024-10-16 16:01:01

加载带有手势识别器的XIB文件时的注意事项的相关文章

自定义类加载器——加载任意指定目录的class文件

public class MyClassLoader extends ClassLoader{ String path;//自定义类加载器所负责的文件夹 public MyClassLoader(String path) { super(); this.path = path; } @SuppressWarnings("deprecation") @Override protected Class<?> findClass(String name) throws Class

cordova加载层、进度条、文件选择插件

在做cordova项目的时候,感觉应用的响应速度跟原生应用比相差甚远,一个主要问题就是如加载层.进度条等弹出对话框的效率不行.毕竟项目中的这些弹框都是用dom拼成的,dom的渲染效率和原生控件比起来慢也是正常的.为了能够让应用尽可能的接近原生应用的效果,我业余时间做了一套对话框插件,使用后应用的使用体验立马有了很大的提升.兼容ios和安卓平台.插件包括加载层.进度条.文件选择.项目已经放到了github,有兴趣的小伙伴可以下载试一试. 插件只支持cordova5.0及以上版本,初始化如下: co

使用requireJS加载不符合AMD规范的js文件:shim的使用方式和实现原理

我们知道在javascript中定义全局变量有2种方式,本质上是等价的,都是向window对象注入属性或者方法. // global.js var g_name = "aty"; window.g_age = 25; 当global.js加载的时候,浏览器的全局对象window就会多出2个属性:g_name和g_age. 我们编写一个js工具类或者是js框架,通常有2种方式: 方式1:dateUtil.js (function(window) { var DateUtils = {};

tomcat 无法加载js和css 等静态文件的问题

前段时间做了个网站,在本地tomcat测试都没有问题,但是部署到阿里云上之后,系统样式全没了.jsp等动态页面访问正常. 打开浏览器监控发现所有的css 和js 文件返回都是404 .直接访问单个的css 文件也同样是404.以为是路径错了,于是一一对了一遍各个文件的路径和服务器上 tomcat路径方面的设置 发现路径没有问题.在网站更目录创建一个css文件和html文件均不能访问.确认不是网站路径的问题. 然后怀疑是tomcat 和 Apache 冲突了,或者可能是Apache 的设置不对.因

SpringMVC 无法加载js,css等静态资源文件

最近在一些技术群里看到有些朋友的馈,SpringMVC 无法加载js,css等静态资源文件,运行时报无法找到异常.下面说下原因及解决方法: 由于SpringMVC支持较优雅的Rest风格的URL,url-patten又是配置的支持所有的模式,所以对于静态资源(css,js,html等)也会去进行匹配,一旦匹配失败控制台会抛URI匹配异常. 这种情况下,需要在SpringMVC配置中增加默认的配置 <mvc:default-servlet-handler/> 增加了上面这个配置之后,原来的Req

android 代码加载 已知文件名 的资源文件

Android开发中如果需要用到某个资源,直接使用R.drawable.**文件即可.但是如果一开始无法知道具体加载哪个资源文件,必须在程序中动态获取ID值并加载.而加载过程是使用文件名来加载的,方式如下: public static String RESOURCE_PATH = "android.resource://packagename/"; 假设存在一个名为content_icon的资源图片 public Uri getIconUri(String drawableName)

Spark中加载本地(或者hdfs)文件以及SparkContext实例的textFile使用

默认是从hdfs读取文件,也可以指定sc.textFile("路径").在路径前面加上hdfs://表示从hdfs文件系统上读 本地文件读取 sc.textFile("路径").在路径前面加上file:// 表示从本地文件系统读,如file:///home/user/spark/README.md ‍ 网上很多例子,包括官网的例子,都是用textFile来加载一个文件创建RDD,类似sc.textFile("hdfs://n1:8020/user/hdfs

Egret的config加载类,支持多个文件加载

ResUtils.ts /** * Created by yangsong on 15-2-11. * 资源加载工具类, * 支持多个resource.json文件加载 */ class ResUtils { private static instance:ResUtils; private _configs: Array<any>; private _onConfigComplete: Function; private _onConfigCompleteTarget: any; publi

开发必备知识点--django项目启动时,url加载之前,执行某个.py文件

django项目启动时,自定义执行某个py文件 在任意的app下的apps.py中的Config类下自定义ready()方法,并且调用autodiscover_modules. app01/apps.py 1 from django.apps import AppConfig 2 from django.utils.module_loading import autodiscover_modules 3 4 5 class App01Config(AppConfig): 6 name = 'ap