iOS 分类的基本使用(更改frame)以及全局变量.pch的使用
2015-08-25 23:01
453 查看
iOS分类基础以及基本应用
Objective-C提供了一个非常灵活的类(Class)扩展机制-类别(Category)。类别用于对一个已经存在的类添加方法(Methods)。你只需要知道这个类的公开接口,
不需要知道类的源代码。需要注意的是,类别不能为已存在的类添加实例变量(Instance Variables)。
注意几点:
1.现有类的类名位于 @interface之后
2.括号中是类别的名称(只要名称唯一,可以添加任意多的类别)
3.类别没有实例变量部分
分类的作用:
(1)将类的实现分散到多个不同文件或多个不同框架中。
(2)创建对私有方法的前向引用。
(3)向对象添加非正式协议。
类别的局限性
有两方面局限性:
(1)无法向类中添加新的实例变量,类别没有位置容纳实例变量。
(2)名称冲突,即当类别中的方法与原始类方法名称冲突时,类别具有更高的优先级。类别方法将完全取代初始方法从而无法再使用初始方法。
无法添加实例变量的局限可以使用字典对象解决.
What’s more?
创建一个NSObject的类别称为“创建一个非正式协议”。因为,NSObject是顶级父类,在NSObject中添加了该方法,也就是说通过继承关系,所有的类中都有该方法。
正式协议是通过protocol指定的一些列方法的声明,然后由实现该协议的类自己去实现这些方法。
而非正式协议是通过向NSObject中添加一个类别来实现,然后子类去继承NSObject。其实都差不多。
不过,非正式协议已经渐渐被正式协议取代,正式协议最大的优点就是可以使用泛型约束
下面就具体如何使用类别举例:
假设一个Teacher类,在.h中暴露一个teach(讲课)的方法,实现文件.m中又定义了一个preteach(备课)的私有方法,一般情况下无法访问到这个没有暴露在接口文件的私有方法。下面我用分类对它进行访问。
新建类Teacher
#import <Foundation/Foundation.h> @interface Teacher : NSObject - (void)teach; @end
在实现文件中实现方法:
#import "Teacher.h" @implementation Teacher - (void)teach{ NSLog(@"方法--老师讲课"); } - (void)preteach{ NSLog(@"方法--老师备课"); }//该方法没有在接口中定义,为私有的 @end
接下来,新建分类
可以看到xcode左边列表中:
分类文件名的形式正如上图所见,当然这是xcode帮我们加的,有利于编辑,并非OC语法规定是这种形式。
Teacher+Extension.h中:
@interface Teacher (Extension) - (void)preteach; @end
Teacher+Extension.m中
@implementation Teacher (Extension) @end
这时在.m文件中会出现如下警告(如果没有出现警告,可用cmd+B编译一下):
出现这个警告的原因应该是Apple建议要在.m文件中实现接口中定义的方法。不过我这里就不实现了,因为我是为了访问之前的私有方法,当在分类中找不到调用的方法时,会向上即父类寻找调用的方法,这时就给我们访问Teacher类中的私有方法的契机。
接下来,在ViewController.m中,导入 #import “Teacher+Extension.h”
- (void)viewDidLoad { [super viewDidLoad]; Teacher *t = [[Teacher alloc] init]; [t teach]; [t preteach]; }
现在cmd+R运行一下,此时Teacher中的私有方法 preteach得意访问了<( ̄︶ ̄)>
iOS中的应用举例
一般情况下,直接更改控件或者视图的位置是不行的,如果有n个视图的位置需要改,如何用最简单最直接的方法?let’s see…
首先,在ViewController中初始化一个UILabel,并添加到当前视图中。并尝试修改它的frame:
UILabel *label = [[UILabel alloc] init]; label.backgroundColor = [UIColor purpleColor]; label.frame = CGRectMake(100, 100, 100, 30); label.frame.size.width = 300; [self.view addSubview:label];
这时你会得到编译器的警告:
由于只读属性的问题,我们无法直接修改,如何解决?
解决方法一:
CGRect *rect = CGRectMake(100,100,200,30);
label.frame = rect;
运行一下,观察目前的位置:
这个通过间接更换一个frame。但是如果n个要修改,岂不是会让人die of coding?
解决方法二:
使用分类的方法
新建分类
在UIView+Extension.h中
@interface UIView (Extension) @property (nonatomic,assign) CGFloat width; @property (nonatomic,assign) CGFloat height; @property (nonatomic,assign) CGFloat x; @property (nonatomic,assign) CGFloat y; @end
在UIView+Extension.m中,为属性设置getter,setter方法(实质是重写了原属性的getter,setter方法)
@implementation UIView (Extension) - (void)setWidth:(CGFloat)width{ CGRect frame = self.frame; frame.size.width = width; self.frame = frame; } - (CGFloat)width{ CGRect frame = self.frame; return frame.size.width; } -(void)setHeight:(CGFloat)height{ CGRect frame = self.frame; frame.size.height = height; self.frame = frame; } - (CGFloat)height{ CGRect frame = self.frame; return frame.size.height; } - (void)setX:(CGFloat)x{ CGRect frame = self.frame; frame.origin.x = x; self.frame = frame; } - (CGFloat)x{ CGRect frame = self.frame; return frame.origin.x; } - (void)setY:(CGFloat)y{ CGRect frame = self.frame; frame.origin.y = y; self.frame = frame; } - (CGFloat)y{ CGRect frame = self.frame; return frame.origin.y; } @end
这样,你就可以直接随意更改frame的大小位置啦~
在ViewController中
先导入:#import "UIView+Extension.h" 在实例化好的Label下: label.width = 300; label.height = 50; label.x = 10; label.y = 10;
但是这样还存在一个问题,如果在n个视图控制器中都要调整frame,是不是意味着要#import n次呢?这样效率会非常低,为了解决之,可以使用.pch
.pch 概述:.pch表示”precompiled header”,这是一个你工程要用到的来自于外部框架的头文件列表,在里面往往写一些经常使用的框架头文件或者一些宏定义的URL地址。xcode将编译这些头到文件,这将减少开发时间、代码维护时间。下面是实用步骤:
cmd+N添加新文件:
在新建的.pch文件中,加入
#import "UIView+Extension.h"
然后点击单击项目,在Building Settings中,levels栏目中,搜索”header”,将Pleaserecompile Prefix Header选项设置为YES
接着在Prefix Header 内容中双击,输入一下内容:
/fenlei 是该项目的名字,/Globe.pch 是刚刚新建的.pch文件
这样,系统编译每个.m文件前,都会先imort你写入的文件头
ps:刚入门iOS不久,若有错误之处,还请多多指教,吾必虚心接受并思之改之( ̄▽ ̄)~*
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- Lua中的全局变量、非全局变量总结
- js DOM 元素ID就是全局变量
- c语言全局变量和局部变量问题及解决汇总
- 深入探讨C语言中局部变量与全局变量在内存中的存放位置
- 深入uCOS中全局变量的使用详解
- Ruby 中$开头的全局变量、内部变量、隐藏变量介绍
- nodejs实现获取某宝商品分类
- 全局变量与局部变量在内存中的区别详细解析
- php通过分类列表产生分类树数组的方法
- 关于全局变量和局部变量的那些事
- javascript中局部变量和全局变量的区别详解
- javascript 用局部变量来代替全局变量第1/2页
- 探讨JavaScript中声明全局变量三种方式的异同