黑马程序员-IOS学习笔记(一)Objective-C概述

来源:互联网 发布:ubuntu隐藏顶栏 编辑:程序博客网 时间:2024/05/04 05:02

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!-------

Objective-C概述:

一、面向对象简介:

 

面向对象程序设计(英语:Object-oriented programming,缩写:OOP),指一种程序设计范型,同时也是一种程序开发的方法。对象指的是类的集合。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。[1]

 

二、面向对象与面向过程

 

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。

 

三、对象、类、方法

 

请查阅:面向对象程序设计也可以看下图简单理解一下:

 

Alt text

 

四、Objective-c中的类

 

1、 OC类的结构

 

||扩展名 || 源类型 || ||.h|| 头文件。头文件包含类、类型、函数和常量声明,类的声明使用关键字@interface 和 @end。|| ||.m || 实现文件。具有此扩展名的文件可以同时包含 Objective-C 代码和 C 代码。有时也称为源文件,类的实现使用关键字 @implementation 和 @end 。|| ||.mm || 实现文件。具有此扩展名的实现文件,除了包含 Objective-C 代码和 C || 代码以外,还可以包含 C++ 代码。仅当您实际引用您的 Objective-C 代码中的 C++ 类或功能时,才使用此扩展名。||

 

注意:.h中的方法只是做一个声明,并不对方法进行实现。也就是说,只是说明一下方法名、方法的返回值类型、方法接收的参数类型而已,并不会编写方法内部的代码。

 

2、 方法

 

方法的声明和实现,都必须以 + 或者 - 开头

 

表示类方法(静态方法)

表示对象方法(动态方法)

在.h中声明的所有方法作用域都是public类型,不能更改。

类方法和实例方法的区别在于,类方法不能使用实例变量使用类方法主要原因有:

 

1.类方法的使用不依赖于实例化一个对象,也就是说如果一个功能的实现不需要实例化对象,就可以用类方法来实现。

2.类方法可以隐藏单例,将类方法和单例结合,可以在应用程序的任何地方访问静态实例,而无需使用指向对象的指针或保存他的实例变量。

3.类方法和内存管理相关,分配一个NSArray,可以【NSArrayalloc】init,也可以【NSArray array】,但是前者必须释放,而后者返回一个随时准备好自动释放的数组对象,并不需要你进行release操作

 

四、创建一个类

 

1、 声明:

下图中的语法声明名为 MyClass 的类,它是从基础类(或根类)NSObject 继承而来的。(根类是供其他类直接或间接继承的类。)类声明以编译器指令 @interface 开始,以 @end 指令结束。类名称后面(以冒号分隔),是父类的名称。在 Objective-C 中,一个类只能有一个父类。

 

Alt text

 

在 @interface 指令和 @end 指令之间,编写属性和方法的声明。这些声明组成了类的公共接口。分号标记每个属性和方法声明的结尾。如果类具有与其公共接口相关的自定函数、常量或数据类型,请将它们的声明放在@interface …@end 块之外。

 

注意、:上面的成员变量命名有所不规范,我们通常会在前面加上 _ (下划线)以和其他变量或者方法区分,这里的成员变量作用域有三种类型,分别是@public,@protected,@private,如果没有指定类型,则默认为@protected.

 

方法声明包含方法类型标识符、返回类型、一个或多个签名关键词,以及参数类型和名称信息。以下是 insertObject:atIndex: 实例方法的声明。

 

Alt text

 

一个方法的实际名称 (insertObject:atIndex:) 是包括冒号字符在内的所有签名关键词的串联。冒号字符表明有参数存在。在上述示例中,该方法采用两个参数。如果方法没有参数,则省略第一个(也是仅有的一个)签名关键词后面的冒号。

声明如下的方法:

 

- (void)setName:(NSString *)name :(int)agewidth:(int)width;

则方法名为:setName::width:

2、 实现:

类实现的语法与类接口文件类似。它以 @implementation 编译器指令开始(接着是该类的名称),以 @end 指令结束。中间是方法实现。(函数实现应在 @implementation …@end 块之外。)一个实现应该总是将导入它的接口文件作为代码的第一行。

 

#import "MyClass.h"

@implementation MyClass

- (id)initWithString:(NSString *)aName

{   

   // code goes here

}

+ (MyClass *)myClassWithString:(NSString*)aName{   

   // code goes here

}

@end

对于包含对象的变量,Objective-C 既支持动态类型化,也支持静态类型化。静态类型化的变量,要在变量类型声明中包括类名称。动态类型化的变量,则要给对象使用类型 id。您会发现在某些情况下,会需要使用动态类型化的变量。例如,集 (collection) 对象,如数组,在它包含对象的类型未知的情况下,可能会使用动态类型化的变量。此类变量提供了极大的灵活性,也让 Objective-C 程序拥有了更强大的活力。

 

下面的例子,展示了静态类型化和动态类型化的变量声明:

 

MyClass *myObject1;  // Static typing

id      myObject2;  // Dynamic typing

NSString *userName;  // From Your First iOS App (static typing)

请注意第一个声明中的星号 (*)。在 Objective-C 中,执行对象引用的只能是指针。如果您还不能完全理解这个要求,不用担心。并非一定要成为指针专家才能开始 Objective-C 编程。只需要记住,在静态类型化的对象的声明中,变量的名称前面应放置一个星号。id 类型意味着一个指针。

 

四、实例化对象

 

#import<Foundation/Foundation.h>

#import "MyClass.h"

int main(int argc, const char * argv[])

{

 @autoreleasepool {

     MyClass * class = [MyClass alloc]; //调用Myclass类的静态方法alloc分配存储空间

     class = [class init];             //调用对象class的动态方法init进行初始化

  }

 return 0;

}

alloc、:会返回分配好内存的Myclass对象,在等号左边用了一个指向Myclass类型的指针变量class来接收这个对象,注意class左边的*号。所有OC对象都是用指针变量来接收的,如果你不了解指针,你记住下面这点就行了:利用类名定义一个变量时,类名后面一定要带个*号。

init、:由于init是动态方法,所以这里使用stu变量来调用,并不是使用类名来调用。init会返回已经初始化完毕的对象,再次赋值给了stu变量。这时候的Student对象stu才能正常使用。

当然你也可以写成如下两种方式:

 

1、 Myclass * class =[[Myclass alloc] init];

2、 Myclass * class =[Myclass new];

还有一点需要明确一下,如果你创建一个新对象(入用alloc),就会在内存中为它保留足够的空间用于存储对象数据,这包括它的实例变量的空间,另外再多一些记录其他信息,还有一点就是使用init后示例变量会进行初始化,通常都会为0.

 

五、释放对象(销毁对象)

 

在Xcode4.2之前需要程序员进行手动释放对象,那么就要使用如下的代码进行:

[class release],class是我们上面实例化的对象。

 

当然现在Xcode已经更新到了5.0版本,则默认为启用ARC(全称:Automatic Reference Counting)机制,此时释放对象的任务就交由系统进行处理,如果你使用的是5.0版本,并且想手动释放对象的话,那么可以在Build Settings 里面找到Apple LLVM 5.0 – Language – Objective C的下面把Objective-C Automatic ReferenceCounting 的值设置为NO。

 

否则你使用 release 的时候Xcode就会报如下错误:

‘release’ is unavailable: not available in automatic referencecounting mode ARC forbids explicit message send of ‘release’

 

四、”.”语法

 

在说.语法之前,让我们来看看getter和setter方法,下面我们给MyClass类添加两个动态方法:

 

- (int)age;          

- (void)setAge:(int)age;

1、上面的age为getter方法,oc习惯把getter方法命名和实例变量名一样。

2、上面的setAge为setter方法,同样习惯于使用set开头,并且后面也与实例变量名相同,而且首字母要大写。

 

除了上面的方法,OC同时提供了使用.语法进行访问类方法,请看下面的代码

 

//使用[]语法,访问age的getter方法、setter方法

[class age];

[class setAge:28];

//使用.语法,访问age的getter方法

class.age

class.age = 28;

这里要说明的是 class.age 等于 [class.age],class.age = 28 等于 [class setAge:28],.语法其实就是访问对象方法的getter和setter方法。至于到底使用哪个方法,取决于你怎么用。

 

五、构造方法

 

在Objective-c中,init就是默认的构造方法,它不接受任何参数。我们可以看到在Foundation框架里对init的如下声明:

 

- (id)init;

一般来说,我们编写的类可能会在初始化的时候进行对象变量的赋值,所以我们要重构构造方法,可以使用如下的方式:

 

//声明

- (id)initWithMyClass:(int)age;

//实现

- (id)initWithMyClass:(int)age {

   self = [super init];

   if(self){

       \_age = age;

    }

   return self;

}

通过上面的代码我们可以看出,构造方法的返回值类型为id,现在可以把id理解为任何类型的类型。

上面使用了 [super init],这是调用父类的init方法进行初始化,并返回赋值给当前对象self,接下来判断是否为真,如果是则对_age赋值,否则不做任何操作,最后返回当前对象self;

 

如果我们重构了构造方法,那我们就可以使用如下方式进行创建对象,并初始化了。

 

Myclass *class = [MyclassinitWithMyClass:28];

六、便利构造器

 

便利构造器其实就是内方法,里面会把创建的对象进行autorelase,所以不用手动释放内存。

 

+ (id)myClassWithName:(NSString *)nameage:(int)age {

   MyClass * myc = [[[MyClass alloc] init] autorelease];

   if (myc) {

       myc.name = name;

       myc.age = age;

    }

   return myc;

}

上面的IF是为了判断对象是否创建成功,防止为空的情况。

 

七、单例模式

 

使用单例模式多次调用此类方法创建对象时,指向的是同一块内存,因为方法中有判断语句,只要指针myc非空,就直接返回指针myc。

 

+ (id)shareInstance {

   static MyClass * myc = nil;

   @synchronized(self){ //关键字,同步,表示同一时间只能有一个线程在访问

       if (!myc) {

           myc = [[MyClass alloc] init];

       }

    }

   return myc;

}

使用dispatch_once_t:

 

+ (id)shareInstance {

   static MyClass * myc = nil;

   static dispatch_once_t once;

   dispatch_once(&once, ^{

       MyClass = [[self alloc] init];

    });

   return myc;

}

1.这个方法可以在创建单例或者某些初始化动作时使用,以保证其唯一性。

2.该方法是线程安全的,所以请放心大胆的在子线程中使用。(前提是你的dispatch_once_t *predicate对象必须是全局或者静态对象。这一点很重要,如果不能保证这一点,也就不能保证该方法只会被执行一次。)

 

当然,如果我们为了保证单例的唯一性,那么我们可以进行重载如下几个系统方法:

 

1、allocWithZone

 

- (id)allocWithZone:(NSZone *)zone

{

   return [[self MyClass] retain];

}

2、copyWithZone

 

- (id)copyWithZone:(NSZone *)zone

{

   return self;

}

3、retain

 

- (id)retain

{

   return self;

}

4、release

 

- (void)release

{

 

}

5、retainCount

 

- (void)retainCount

{

   return UINT_MAX;

}

6、autorelease

 

- (void)autorelease

{

   return self;

}

不过作为程序员,应该去遵循某些原则,使用单例的时候尽量不要直接用alloc等方法。

 

八、Self关键字

 

Objective-c中的self代表当前方法的调用者,并且可以用在动态方法与静态方法中。

 

- (void)test1(){

   [self test2];

}

+ (void)test2(){

   [Myclass test1];

   [self test1];

}

通过上面的代码我们可以看到不管是在动态方法和静态方法中,都可以使用self关键字调用其他方法,并且等于 [Myclass test1]这种方式。

 

如果细分一下的话,可以理解为:

静态方法:self代表这个类。

动态方法:self代表这个对象。

 

0 0
原创粉丝点击