Objective-C中.h文件、.m文件中@interface、@synthesize及其它
很多开发iOS好几年的老鸟,可能都不太分的清.h文件和.m文件里各种结构的用途和区别。最近仔细研究了一下,写一篇文章记下来。
一般的,写一个Class的时候,经常是这种格式(以UIViewController
为例):
.h文件:
@interface ClassName{
NSString* _value1;
}
@property(nonatomic,assign)NSString* value1;
-(void)func1;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
.m文件:
@interface ClassName(){
}
@end
@synthesize value1;
@implementation ClassName
-(void)func1{
}
@end
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
大体上就是这个格式。很多人,包括我,在创建和使用Class时,直接就使用这样的模板。这个模板里有一些有意思的小东西,值得探讨,比如:
1. 为什么.h文件和.m文件里各有1个@interface
?它们分别有什么用?
2. .h中,value1为什么要定义2遍?
3. @synthesize
有什么用?
还有一些其它的问题,今天先解决上面提到的这几个。
为什么.h文件和.m文件里各有1个@interface?它们分别有什么用?
.h里面的@interface
,不消说,是典型的头文件,它是供其它Class调用的。它的@property
和functions,都能够被其它Class“看到”。
而.m里面的@interface
,在OC里叫作Class Extension,是.h文件中@interface
的补充。但是.m文件里的@interface
,对外是不开放的,只在.m文件里可见。
因此,我们将对外开放的方法、变量放到.h文件中,而将不想要对外开放的变量放到.m文件中(.m文件的方法可以不声明,直接用)。
有的同学看到Class Extension,可能会想到OC里的@protocol
。是的,它们都是对一个Class的扩展。不过它们的区别也很明显:
Class Extension只能用在能得到源代码的情况下,而@protocol
在得不到源码的时候也可以使用。
因此@protocol
一般用作对一些系统Class的扩展,常见的比如对NSString、UIView等。
.h中,value1为什么要定义2遍?
当然,现在@interface{}
里的定义也可以省略掉了,不过原理还是要搞清楚。
严格来说@interface{}
里定义的变量,叫作instance variable,它是这个Class内部真正的全局变量。然而这个instance variable是不对外公开的,因此我们还需要一个对外公开的东西来调用,就是@property
@property是对外的,它其实是告诉大家,我这个Class里,有一个变量的set/get方法。比如,@property NSString* string;
就是说,本Class里有一个getString/setString供你们调用。
因此需要2次声明。当然现在lldb也升级了,只要你声明了@property
,它就可以自动创建对应的全局变量。
@synthesize有什么用?
@property
一个变量后,在@implementation
里再@synthesize
一下,相信是很多人的习惯。但是为什么要有这个@synthesize方法呢?
@property
是对外声明了Class的get/set方法,然后我们就需要在.m文件里手写get/set方法。这可就麻烦了,1个变量对应2个方法,假如一个Class里有10个变量,那岂不是要写20个方法?烦也烦死唠。
@synthesize帮我们解决了这个问题。@synthesize
在.m文件里自动生成了get/set方法。因此,我们只要在@implementation
后面加上一行:@synthesize
就可以自动生成get/set方法了,省掉了很多麻烦。比如@synthesize value1 = _value1;
的意思就是,将instance variable _value1用作getValue1和setValue1方法里。
get/set方法有时候是比较复杂的,因为它和变量的属性相关,就是@property(nonatomic, assign/retain(strong/weak))
这就和内存有关了。然而@synthesize为我们做了这些事情,就不要再为这些事情烦恼了!
更方便的是,从Xcode4.4开始,编译器会自动为每一条@property
都添加一条对应的@synthesize
,因此以后我们只要写一个@property就可以了!
PS:这些在Swift貌似都不是个事儿了。话说到现在都没怎么接触过Swift,真是罪过罪过。
Objective-C中.h文件、.m文件中@interface、@synthesize及其它的更多相关文章
- iOS开发之解决CocoaPods中“.h”头文件找不到的问题,简单粗暴的方法
如果是拖进工程中的framework或者第三方文件,如果找不到,删除了重新添加或者修改search path地址,如果不知道怎么修改,在工程文件夹中,找到对应的文件,然后将文件拖到修改文件地址的位置, ...
- Visual Studio 2010中的stdafx.h和targetver.h两个头文件是有什么用?
来自百度~stdafx.h中没有函数库,只是定义了一些环境参数,使得编译出来的程序能在32位的操作系统环境下运行. Windows和MFC的include文件都非常大,即使有一个快速的处理程序,编译程 ...
- C++中#include包含头文件带 .h 和不带 .h 的区别
C++中#include包含头文件带 .h 和不带 .h 的区别? 如 #include <iostream> 和 #include <iostream.h> 包含的东西有哪些 ...
- C++中头文件(.h)和源文件(.cpp)都应该写些什么
头文件(.h): 写类的声明(包括类里面的成员和方法的声明).函数原型.#define常数等,但一般来说不写出具体的实现. 在写头文件时需要注意,在开头和结尾处必须按照如下样式加上预编译语句(如下): ...
- Visual Studio 中使用万能头文件 #include <bits/stdc++.h>
最近开始使用VS,之前用的DEV C++软件可直接使用 #include <bits/stdc++.h> ,但VS中并没有,为了使用方便,可直接在VS中添加此头文件,方法如下: 1.在安 ...
- C++ 中头文件(.h)和源文件(.cc)的写法简述
用C++编写比较大型的项目时,文件的分割管理确实确实是非常必要的 .下面就非常简洁明了地谈谈头文件(.h)和源文件(.cc)应该怎么写. 头文件(.h):写类的声明(包括类里面的成员和方法的声明).函 ...
- vc++中 .H 头文件引用的顺序与符号关系
在使用 #include "math.h" 和 #include <math.h>时,引号 与尖括号的区别如下 此时math.h_1 在工程文件中 math.h_2 ...
- C 语言项目中.h文件和.c文件的关系
http://blog.csdn.net/xingkong_678/article/details/38639847 关于两者以前的关系,要从N年以前说起了~ long long ago,once a ...
- xcode中的.h和.m文件分别是什么意思?各有什么用?
.h 表示头文件,用来声明各种成员变量,方法,属性之类的.在import的时候用头文件. .m 主要用来实现.h 里声明的方法.举个例子,如果要写一个方法,你要在.h里先声明: - (void)myM ...
- [Swift]在Swift项目中创建桥接头文件,Swift文件和Objective-C文件相互调用
创建一个Swift项目[demo],以下内容Swift文件和Objective-C文件相互调用都是在Swift项目中. 一.Swift文件调用Objective-C文件 新建文件夹[SupportFi ...
随机推荐
- 自定义标签(JspFragment类、invoke方法、开发带属性的标签)
自定义标签(JspFragment类.invoke方法.开发带属性的标签) 一.JspFragment类 javax.servlet.jsp.tagext.JspFragment类是在JSP2.0中定 ...
- [Todo]非常好的免费IT书籍资源 & Github排名
今天看github排名,看到排在第二位的是免费书籍: https://github.com/vhf/free-programming-books/blob/master/free-programmin ...
- python中常用的推导(字典推导和列表推导)
在python开发中经常需要书写这样的代码 result = list() for data in datas: if data not in ['a', 'b']: result.append(da ...
- HTTP代理神器Fiddler
HTTP代理神器Fiddler Fiddler是一款强大Web调试工具,它能记录所有客户端和服务器的HTTP请求. Fiddler启动的时候,默认IE的代理设为了127.0.0.1:8888,而其他浏 ...
- thinkphp3.2中在模板页面使用运算符
首先要明确的是,ThinkPHP 内置模板引擎支持在模板中使用算术运算符(+.-.*./ 和 %),例子: public function index(){ $x = 1; $y = 2; $z = ...
- 2017.12.25 Mybatis物理分页插件PageHelper的使用(二)
参考来自: 官方文档的说明:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md 上篇博客 ...
- centos/7/isos/x86_64 下载
为了节约有限的可用带宽. 不从mirror.centos.org下载iso映像 以下镜子应该可用的ISO映像: http://mirrors.aliyun.com/centos/7/isos/x86_ ...
- swift基础语法之控件使用02
//第一个控制器:显示基础控件 import UIKit class ViewController: UIViewController { var label: UILabel = UILabel() ...
- list中依据map<String,Object>的某个值排序
private void sort(List<Map<String, Object>> list) { Collections.sort(list, new Comparato ...
- 类非静态成员的函数指针 的使用 Function pointer of a non-static member function of a class
you can get the pointer of the method, but it has to be called with an object typedef void (T::*Meth ...