object-c中疑问
*一般是加在方法的返回值类型声明部分的,比如:
-(NSString *)executeSomeThing;
+(NSString *)executeAnotherThing; -(int)addOne; +(int)addTwo; 从上面可以看出,
*是用来表示返回值是指针类型的数据,比如NSString、NSArray、NSNumber等等。
没有*的返回值类型通常都是简单类型,比如int、布尔等等
+表示该方法是类方法,不需要实例化该类就可以调用。
-表示该方法是实例方法,必须要实例化后才能调用。
Object-C中的类方法和实例方法区别
Object-C中方法的概念和Java一样,Object-c中有两种方法—实例方法(需要实例化才能调用的方法)和类方法(类方法也可以说是静态方法,参照Java中的静态方法)。
声明实例方法需要在减号字符(-)作为前缀。声明类方法需要使用加号字符(+)作为前缀。 在Object-c中方法需要在头文件中声明,方法声明示例:
#import <Foundation/Foundation.h>
@class AnotherClass;
@interface TestClass : NSObject {
int age;
NSString *name;
}
-(void) doMethod1;
-(void) doMethod3: (NsString *)str withAnotherPara:(float) value;
+(void) doMethod4;
-(void) doMethod2: (NSString *)str;
@end
方法实现示例:
#import “TestClass.h”
@implementation TestClass
-(void) doMethod1{
--(方法主体)--
}
-(void) doMethod2:(NSString *) str{
--(方法主体)--
}
-(void) doMethod3:(NSString *) str withAnotherPara:(float) value {
--(方法主体)--
}
+(void) doMethod4 {
--(方法主体)--
}
调用方法示例:
TestClass *justTest =[TestClass alloc];
[justTest doMethod1];
[justTest doMethod2 : @”Holle Xiaming”];
[justTest doMethod3 : @”Holle xiaming”withAnotherPara:1.0f];
//类方法可直接使用类名调用//
[TestClass doMethod4];
1.@property与@synthesize配对使用。
@property预编译指令的作用是自动声明属性的setter和getter方法。
@synthesize 创建了该属性的访问代码
功能:让编译好器自动编写一个与数据成员同名的方法声明来省去读写方法的声明。
2.强引用(__strong)和 弱引用(__weak)
在Objective-C的ARC模式中,
1
|
id obj1 = [[NSObject alloc] init]; |
这里虽然没有显示的声明为__strong,但是Objective-C默认声明的一个对象就为__strong,即:
1
|
id obj1 = [[NSObject alloc] init]; |
和
1
|
id __strong obj1 = [[NSObject alloc] init]; |
是等价的。
在强引用中,有时会出现循环引用的情况,这时就需要弱引用来帮忙(__weak)。
强引用持有对象,弱引用不持有对象。
强引用可以释放对象,但弱引用不可以,因为弱引用不持有对象,当弱引用指向一个强引用所持有的对象时,当强引用将对象释放掉后,弱引用会自动的被赋值为nil,即弱引用会自动的指向nil。
下面用代码来说明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
// // main.m // ARC中的强引用和弱引用 // #import <Foundation/Foundation.h> int main( int argc, const char * argv[]) { @autoreleasepool { id __weak obj0 = nil; if (YES) { id obj1 = [[NSObject alloc] init]; obj0 = obj1; NSLog( @"obj0: %@" , obj0); } NSLog( @"obj0: %@" , obj0); } return 0; } /* * 输出结果 * obj0: <NSObject: 0x1003066c0> * obj0: (null) * * 因为obj1生成的默认的为强引用(__strong),在超出if的作用域之后,obj1所持有的对象被释放, * obj0为弱引用,所以obj0不持有对象,在obj1对象释放后,obj0自动的被赋值为nil * 弱引用的特性是,不持有对象,即便是写成id __weak obj1 = [[NSObject alloc] init]; * 此代码系统会给与警告,因为这里obj1被声明成弱引用,那么在赋值之后,alloc出来的对象会被立即释放。 */ |
3.点表达式,可以用来访问对象,类似C语言的结构体访问。
点表达式出现在等号的左边,该变量名称的setter方法将被调用;点表达式出现在等号的右边,该变量名称的getter方法将被调用。
4.什么是Category
Category模式用于向已经存在的类添加方法从而达到扩展已有类的目的,在很多情形下Category也是比创建子类更优的选择。新添加的方法同样也会被被扩展的类的所有子类自动继承。当知道已有类中某个方法有BUG,但是这个类是以库的形式存在的,我们无法直接修改源代码的时候,Category也可以用于替代这个已有类中某个方法的实体,从而达到修复BUG的目的。然而却没有什么便捷的途径可以去调用已有类中原有的那个被替换掉方法实体了。需要注意的是,当准备有Category来替换某一个方法的时候,一定要保证实现原来方法的所有功能,否则这种替代就是没有意义而且会引起新的BUG。和子类不同的是,Category不能用于向被扩展类添加实例变量。Category通常作为一种组织框架代码的工具来使用。
Category的用途
1. 在不创建继承类的情况下实现对已有类的扩展。
2. 简化类的开发工作(当一个类需要多个程序员协同开发的时候,Category可以将同一个类根据用途分别放在不同的源文件中,从而便于程序员独立开发相应的方法集合)。
3. 将常用的相关的方法分组。
4. 在没有源代码的情况下可以用来修复BUG。
Category的用法
在Obj-C中,声明某一个已有类的Category扩展的方法如下:
1
2
3
4
|
@ interface ClassName (CategoryName) -methodName1 -methodName2 @end |
上面的声明通常是在.h文件中,然后我们在.m文件中实现这些方法:
1
2
3
4
|
@implementation ClassName (CategoryName) -methodName1 -methodName2 @end |
我们创建一个iOS Single View Applciation名为CategoryExample。然后为创建一个NSString类的category扩展。File->New->File然后选择 Cocoa Touch Objective-C category.命名为ReverseNSString.系统会自动生成一个固定格式ClassName+CategoryName的.h和.m文件。
声明Category
打开NSString+ReverseNSString.h文件,在里面添加如下代码:
1
2
3
4
|
#import <Foundation/Foundation.h> @ interface NSString (ReverseNSString) + (NSString*) reverseString:(NSString*)strSrc; @end |
实现Category
NSString+ReverseNSString.m文件中实现reverseString方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#import"NSString+ReverseNSString.h" @implementationNSString (ReverseNSString) + (NSString*)reverseString:(NSString*)strSrc; { NSMutableString *reversedString =[[NSMutableString alloc]init]; NSInteger charIndex = [strSrc length]; while (charIndex > 0) { charIndex--; NSRange subStrRange =NSMakeRange(charIndex, 1); [reversedString appendString:[strSrcsubstringWithRange:subStrRange]]; } return reversedString; } @end |
剩下的工作就是验证我们的Category了,在view中添加一个按钮ReverseString,并设置相应的action方法为reverseString.在view上再添加一个label,命名为myString,默认值是”HelloCategory Design Pattern!”。点击按钮反转这个字符串。主要代码如下:
1
2
3
4
|
-(IBAction)reverseString:(id)sender { NSString *test = [NSStringreverseString:_myString.text]; _myString.text = test; } |
代码组织
Category用于大型类有效分解。通常一个大型类的方法可以根据某种逻辑或是相关性分解为不同的组,一个类的代码量越大,将这个类分解到不同的文件中就显得越有用,每个文件中分别是这个类的某些相关方法的集合。
当有多个开发者共同完成一个项目时,每个人所承担的是单独的cagegory的开发和维护。这样就版本控制就更加简单了,因为开发人员之间的工作冲突更少了。
Category VS添加子类
并没有什么界限分明的判定标准来作为何时用Category何时用添加子类的方法的指导。但是有以下几个指导性的建议:
- 如果需要添加一个新的变量,则需添加子类。
- 如果只是添加一个新的方法,用Category是比较好的选择。
5.Class Extension(类扩展)
class extensions用于解决两个问题:
- 允许一个对象可以拥有一个私有的interface,且可由编译器验证。
- 支持一个公有只读,私有可写的属性。
若要定义私有函数,通常是在实现文件中声明一个"Private" category:
@interface MyClass (Private)
- (id)awesomePrivateMethod;
@end
然而,
类的私用方法通常是希望实现在类的@implementation块中的,而不是像上面的Category的方法那样实现在独立的@implementation区块中。事实上,Category仅仅是弥补了Objective-C缺少public/private限定的不足。
真正的问题是Objective-C编译器会认为在Category中声明的方法将会在别处实现,所以编译器并不会尝试确认它们是不是真得都被实现了。也就是说,开发者声明的方法有可能并未实现,而且编译器也不会有什么警告。编译会以为它们将在别的地方或独立的文件中实现。
使用class exteionsion,在其中声明的方法和属性的实现将放在class的@implementation区块中。否则,编译器就会报错。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// someClass.m @ interface someClass () -( void )extend; @end @implementation someClass // 所有声明在头文件或父类中方法的实现 // 或者一些私有函数 -( void )extend { // implement private method here; } @end |
公有可读、私有可写的属性(Publicly-Readable, Privately-Writeable Properties)
实现一个不可变(immutable)的数据结构通常有一个好处是外部代码不能用setter修改对象的状态。然而,可能又希望它在内部又是一个可写的属性。Class
extensions可以做到这一点:在公共接口(类的声明中)中,开发者可以声明一个属性是只读的,随后在类扩展中声明为可写。这样,对外部代码而言,该属性将是只读的,而内部代码却可以使用它setter方法。
1
2
3
4
5
6
7
8
|
@ interface MyClass : NSObject @property (retain, readonly ) float value; @end // 私有的extension, 隐藏在主实现文件中. @ interface MyClass () @property (retain, readwrite) float value; @end |
6.判断对象类型
对象在运行时获取其类型的能力称为内省。内省可以有多种方法实现。
-(BOOL) isKindOfClass: classObj判断是否是这个类或者这个类的子类的实例
-(BOOL) isMemberOfClass: classObj 判断是否是这个类的实例
7.尖括号的含义
声明语句后面的尖括号内的内容标识遵守的协议的名称,如果协议有多个,则在尖括号内部以逗号分隔列出来。
8.self和self class指针的区别
self是实例的指针,[self class]是类的指针,静态方法得用类的指针来调用
9.@optional和@required
如果指定的关键字@required,则该方法是必须实现的,如果指定了@optional,该方法不是必须实现。
10.
object-c中疑问的更多相关文章
- Hadoop 中疑问解析
Hadoop 中疑问解析 FAQ问题剖析 一.HDFS 文件备份与数据安全性分析1 HDFS 原理分析1.1 Hdfs master/slave模型 hdfs采用的是master/slave模型,一个 ...
- 重写Object类中的equals方法
Object是所有类的父亲,这个类有很多方法,我们都可以直接调用,但有些方法并不适合,例如下面的student类 public class Student { //姓名.学号.年纪 private S ...
- [Effective JavaScript 笔记]第47条:绝不要在Object.prototype中增加可枚举的属性
之前的几条都不断地重复着for...in循环,它便利好用,但又容易被原型污染.for...in循环最常见的用法是枚举字典中的元素.这里就是从侧面提出不要在共享的Object.prototype中增加可 ...
- 【Java基础之Object类(一)】Java中Object类中的所有方法(toString、equals、hashCode、clone、finalize、wait和notify等)详解(转载)
java中的hashcode.equals和toString方法都是基类Object的方法. 首先说说toString方法,简单的总结了下API说明就是:返回该对象的字符串表示,信息应该是简明但易于读 ...
- Object类中getClass()
Object类中包含一个方法名叫getClass,利用这个方法就可以获得一个实例的类型类.类型类指的是代表一个类型的类,因为一切皆是对象,类型也不例外,在Java使用类型类来表示一个类型.所有的类型类 ...
- Object类中方法详解
目录 概述 hashCode方法 getClass方法 toString方法 equals方法 clone方法 finalize方法 概述 Object 是类层次结构的根类.每个类都使用 Object ...
- -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中
本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait( ...
- Object类中通用方法之:toString()方法
1.Java所有的对象都是Object类的实例,都可以直接调用该类中定义的方法,这些方法称为通用方法 2.toString()方法即为Object类中定义的通用方法之一 3.平时我们如果在控制台直接打 ...
- wait(),notify(),notifyAll()用来操作线程为什么定义在Object类中?
这些方法存在于同步中: 使用这些方法必须标识同步所属的锁: 锁可以是任意对象,所以任意对象调用方法一定定义在Object类中. Condition是在java 1.5中才出现的,它用来替代传统的Obj ...
- Object类中常见的方法,为什么wait notify会放在Object里边
toString():输出一个对象的地址字符串(哈希code码):可以通过重写toString方法,获取对象的属性! equals():比较的是对象的引用是否指向同一块内存地址, 重写equals() ...
随机推荐
- css 定位(fixed > absolute > relative)与层级zIndex 的权限认知
原则1: fixed > absolute > relative原则2: zIndex 越高越牛逼,不管你是谁无视身份.原则3: 青出于蓝而胜于蓝,儿子永远比父亲强原则4: 平台很重要. ...
- iOS性能优化篇 —— 耗电优化总结
手机App耗电的主要来源有以下四个因素: CPU处理,Processing 网络,Networking 定位,Location 图像,Graphics 耗电优化最终目的:通过尽可能降低CPU ...
- Apache与php快速部署web服务
[本文出自天外归云的博客园] 在一台服务器上临时起个web服务,读取服务器上的cfs文件内容并显示在页面上,做一个简单的web请求处理. 首先找到apache,在conf文件夹下vi httpd.co ...
- Activiti 工作流变量的修改方法
修改方法: //此方法的更新会同时更新 ru_ 和 hi_的数据 @Override public Map<String, Object> updateProcessFormValue(S ...
- STM32串口DMA超时接收方法,可大大节约CPU时间
//超时时间定义#define UART1_TimeoutComp 2 //20ms#define UART2_TimeoutComp 10 //100ms#defin ...
- 简化实现动态行列转置的SQL
动态行列转换的计算在实际业务中非经常见,网上各类技术论坛上都有讨论,比方以下这些问题: http://www.iteye.com/problems/87788 http://bbs.csdn.net/ ...
- linux 查找并kill进程
以php以关键字查找进程 $ ps aux | grep php root 32957 0.0 0.1 2470904 8908 s002 S+ 4:53下 ...
- 手动安装mysql
需要在本机(mac)上装个mysql,看到压缩版的体积最小,结果进入了手工安装的坑(正常有界面可以安装,但安装目录将是/usr/local/mysql),既然入了坑就填上吧. 1.解压到自己选择的目录 ...
- 微信小程序——动态设置swiper的高度
根据小程序的设定,swiper组件默认高度为150px,无法根据内容来撑高.如果里面的内容固定还好说,直接设置一个高度就可以了.要是里面内容是动态变化的,这个特性使得我们使用这个组件的时候感到诸多不便 ...
- tensorflow使用多个gpu训练
关于多gpu训练,tf并没有给太多的学习资料,比较官方的只有:tensorflow-models/tutorials/image/cifar10/cifar10_multi_gpu_train.py ...