1、类的定义与实现 1.1说明
所有的类都是继承NSObject。类的接口与实现是分开的,一般类的定义是放在.h文件【包含类的名称、成员变量、方法、属性、继承关系、遵从的协议】;实现部分是放在.m文件中【包含每个属性和方法的具体实现以及协议的方法实现】
语法:【类的定义以@interface开头以@end结束;类的实现以@implementation关键字开头以@end结束】
Person.h
@interface Person:NSObject{ //类的成员变量区【类的成员变量声明】 } //类的方法与属性区【类的方法与属性的定义】 @end
Person.m
#import “Person.h” @implementation Person{ } @end
1.2实例化alloc
实例一个新的对象需要调用类的alloc静态方法。alloc方法一旦调用就表明了向内存申请了一个空间用来保存该类的信息。
具体流程是:alloc会查看所有该类及所有基类,统计出这些类一共定义了哪些成员变量,总共需要多大的内存空间用来保存这些信息,然后向操作系统发出请求申请这些空间,如果成功,alloc方法会将所有的成员亦是置为0,除了一个特殊的指向其类元对象的成员之外,然后返回这块申请下来的空间的首地址
流程图:
2、成员变量与方法
2.1变量
变量分为成员变量和类的静态变量。
成员变量
可访问性:@protected、@private、@public
关键字
可见性
描述
@protected
当前类及子类的实例方法可见
默认值,类里声明的成员变量的可访问级别默认为@protected。
@private
只对当前类的实例方法可见
私有访问级别
@publice
成员变量对外可见
变量的声明
@interface Person:NSObject{ @private NSString*_name; int_age; }
静态变量
使用static关键字表示,定义在类的实例部分中所有实例方法之外。类的静态变量对于实例方法和类方法都是可见的。
@implementation Person staticint NumberPerson=0; @end
2.2方法
方法的声明语法
+|-(返回值类型)方法名;
+|-(返回值类型)参数1说明:(参数1类型)参数1名称 参数2说明: (参数2类型)参数2名称;
+:加号表示该方法是一个类的方法,类的静态方法,它不属于类的任何实例只属于该类。【类似于Java中的static方法】 调用格式为 [类 方法名] 例: [PersonsetMaxAge:20];
-:减号表示该方法的实例方法,属于实例。调用时必须先将实例化,然后再调用。调用格式为[类的实例方法名]
例:Person *xiaoMing=[[Person alloc] init];//实例化
[xiaoMing setName:@”90worker”];
注意:
-(BOOL)likeFood:(NSString *)food;
方法名为likeFood: 【注意有个冒号】
-(id) initWithcName:(NSString *)name andAge:(int) age;
方法名为initWithcName: andAge: 【注意有多个冒号】
2.3选择器@select
每一个Objective C方法都对应一个选择器,即SEL类型的对象。
Objective C运行时通过方法对应的选择来定位其实现代码。可以通过@select指令,传入方法名,可以获取该方法的选择器
用法 : SELinitMethodSelect=@select(initWithName:age:);
用途:通常用于指定回调方法。
2.4属性@property
语法:@property (属性的附加特性) 类型名称;.m文件实现用@synthesize关键字。【@synthesize 属性名称|@synthesize 属性名称=成员变量名称】
声明:@property (nonatomic,copy) NSString *name;
实现:@synthesize name;
属性的附加特性:
关键词
描述
nonatomic
线程安全的,编译器默认会生成额外的代码以保证访问属性的线程安全,会牺牲一定的性能。
readonly
属性只可读,@synthesize指令只会生成get方法还没有set方法
readwrite
默认值。可读写
geter=get方法名,
setter=set方法名
当声明一个属性用@synthesize指令会生成相应的get方法和set方法,但可以通过getter和setter来手动指定get方法和set方法
assign、retain、copy
调用:对过点.来实现调用
xiaoMing.name=@”90worker”;
点语法oc2.0以后
为什么设计点语法
1、为了方便别的程序员转到OC开发来
2、为了让程序设计简单化
3、隐藏了内存管理细节
4、隐藏了多线程、同步、加锁细节
2.5@class关键字
@class为前向声明
现有两个类的声明
Wheel代表着轮子,Bike代表着自行车,我们知道Bike是需要Wheel的
于是有以下的代码
Bike.h
@intefrace Bike:NSObject{ Wheel* _frontWheel, *_rearWheel; } @end
在这里我们用到了Wheel类,那么我们到底是用#import还是用@class呢?我们用一个表格来说明#import和@class
关键字
描述
#import
将Wheel类的外部接口Wheel.h整个导入,这样会产生编译依赖和编译时间的浪费。如果Bike.h中导入了Wheel.h而Bike.h文件又被很多其他的类导入 了,那么这些类也会导入了Wheel.h,一旦Wheel.h修改了,所有导入了Wheel.h的文件都发生了变化需要重新编译。
@class
1、可以有效的解除上面所说的编译依赖。如果Wheel.h修改了,对于那些导入了Bike.h的文件并没有发生变化所以也不需要重新编译。使用了@class关键字只是在类的定义中前身引用了,但在Bike类的内部实现中还是需要导入Wheel.h的,因为可能需要使用到Wheel.h中的某些定义方法
2、可以解决循环引用
2.6self关键字
self表示当前引用对象
记住以下两句话:
1、谁在执行该函数 self就表示谁
2、super表示该对象的父对象
+(int)maxAge{ // 在+类方法 (静方法) self表示本类【抽象】 对象是具体的、实例的 }
+(id) person{ idobj=[[self alloc] init]; //用法==[[Person alloc]init]; == [[[self class ] alloc] init] //self=Person returnobj; } //调用 [xxx 方法名] maxAge方法里面的self表示 int maxAge=[Person maxAge];
2.7dealloc函数
dealloc【只调用一次】
对象从内存中销毁前夕调用的函数
在对象完全消失的时候调用 对象的计数器为0的时候会自动调用dealloc 不能人为的去调用此方法。应用这样调用:[xxrelease] //release计数器1减到0 系统就会自动的调用dealloc
-(void)dealloc{ //在调用父类之前做一些处理 [superdealloc]; }
2.8 initialize函数
+(void)initialize NSObject 这个类的第一次实例化的时候调用第一次调用alloc 或者调用init的时候就会调用 【只调用一次】 类方法在该类第一次实例化的时候调用 并且只调用一次 在这里做一些static变量的初始化操作
目标:
//
// ViewController.h
// hhhh
//
// Created by bitcar on 12-7-10.
// Copyright (c) 2012年 bitcar . All rights reserved.
//
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
@interface ViewController : UIViewController
{
IBOutlet UITextField *passwordlength;
IBOutlet UITextField *password;
IBOutlet UISwitch *includeUpperCase;
IBOutlet UISwitch *includeLowerCase;
IBOutlet UISwitch *includeNumbers;
}
@property (nonatomic, retain) UITextField *passwordlength;
@property (nonatomic, retain) UITextField *password;
@property (nonatomic, retain) UISwitch *includeUpperCase;
@property (nonatomic, retain) UISwitch *includeLowerCase;
@property (nonatomic, retain) UISwitch *includeNumbers;
//-(IBAction)setPassword:(id)sender;
- (IBAction)onPasswordButtonClick:(id)sender;
@end
#import "ViewController.h"
@implementation ViewController
@synthesize passwordlength, password;
@synthesize includeLowerCase, includeNumbers, includeUpperCase;
#define RANDOM_SEED() srandom(time(NULL))
//定义随机值,用最小值和最大值和随机数来计算,返回整数值
#define RANDOM_INT(_MIN_, _MAX_) ((_MIN_) +random() % ((_MAX_ +1) - (_MIN_)))
//控件输入返回判定方法
- (BOOL) textFieldShouldReturn: (UITextField*)textField
{
if(textField == password)
{
[password resignFirstResponder];//隐藏密码文本框输入的键盘
}
if(textField == passwordlength)
{
[passwordlength resignFirstResponder];//隐藏密码长度文本框输入的键盘
}
return YES;
}
//button方法,点击的密码显示在文本框里
//-(IBAction)setPassword:(id)sender
- (IBAction)onPasswordButtonClick:(id)sender
{
//输入密码长度
NSInteger iPasswordLength = [passwordlength.text intValue];
//打开字母小写
BOOL bIncludeLowerCase = includeLowerCase.on;
//打开字母大写
BOOL bIncludeUpperCase = includeUpperCase.on;
//打开数字
BOOL bIncludeNumbers = includeNumbers.on;
NSString *passwordText = @"";
//定义a到z字母
NSString *lowercaseChars = @"abcdefghijklmnopqrstuvwxyz";
//定义A到Z字母
NSString *uppercaseChars = @"ABCDEFGHIGKLMNOPQRSTUVWXYZ";
//定义数字
NSString *numbersChars = @"1234567890";
//随机变量
RANDOM_SEED();
//字符对象为空
NSString *passwordChars = @"";
//字母小写的条件语句
if(bIncludeLowerCase)
{
passwordChars =
[NSString stringWithFormat:@"%@%@", passwordChars, lowercaseChars];
}
//字母大写的条件语句
if (bIncludeUpperCase) {
passwordChars =
[NSString stringWithFormat:@"%@%@", passwordChars, uppercaseChars];
}
//字母为数字的条件语句
if (bIncludeNumbers) {
passwordChars =
[NSString stringWithFormat:@"%@%@", passwordChars, numbersChars];
}
//数值从0开始,当数值小于密码长度,取得数字字符,获取的数据转换为文字格式
for (NSInteger i=0; i<iPasswordLength; i++)
{
int index = RANDOM_INT(0, [passwordChars length]-1);
NSRange range = NSMakeRange(index,1);
NSString *passwordChar = [passwordChars substringWithRange:range];
passwordText =
[NSString stringWithFormat:@"%@%@", passwordText, passwordChar];
}
password.text = @"";
password.text = passwordText;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) dealloc
{
[passwordlength release];
[password release];
[includeNumbers release];
[includeLowerCase release];
[includeUpperCase release];
[super dealloc];
}
@end
当把所有字母大写小写和数字开启时。
当只把字母大写关闭时。
当把数字开启时。
//-(IBAction)setPassword:(id)sender;
这次的编码因为系统误认set,get的原因让程序不能执行,我将记录下并分析其中的原因。
当把“按扭生成密码“这个方法写成setPassword时,系统出现如下的警告:
原因是运行时程序将这个方法误认为set get。导致程序不能执行。
如果把它改成- (IBAction)onPasswordButtonClick:(id)sender;便没问题了。
编写多线程程序是为了实现多任务的并发执行,从而能够更好地与用户交互。一般有三种方法,Thread,Runnable,Callable.
Runnable和Callable的区别是,
(1)Callable规定的方法是call(),Runnable规定的方法是run().
(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值得
(3)call方法可以抛出异常,run方法不可以
(4)运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
1、通过实现Runnable接口来创建Thread线程:
步骤1:创建实现Runnable接口的类:
class SomeRunnable implements Runnable
{
public void run()
{
//do something here
}
}
步骤2:创建一个类对象:
Runnable oneRunnable = new SomeRunnable();
步骤3:由Runnable创建一个Thread对象:
Thread oneThread = new Thread(oneRunnable);
步骤4:启动线程:
oneThread.start();
至此,一个线程就创建完成了。
注释:线程的执行流程很简单,当执行代码oneThread.start();时,就会执行oneRunnable对象中的void run();方法,
该方法执行完成后,线程就消亡了。
2、与方法1类似,通过实现Callable接口来创建Thread线程:其中,Callable接口(也只有一个方法)定义如下:
public interface Callable<V>
{
V call() throws Exception;
}
步骤1:创建实现Callable接口的类SomeCallable<Integer>(略);
步骤2:创建一个类对象:
Callable<Integer> oneCallable = new SomeCallable<Integer>();
步骤3:由Callable<Integer>创建一个FutureTask<Integer>对象:
FutureTask<Integer> oneTask = new FutureTask<Integer>(oneCallable);
注释:FutureTask<Integer>是一个包装器,它通过接受Callable<Integer>来创建,它同时实现了Future和Runnable接口。
步骤4:由FutureTask<Integer>创建一个Thread对象:
Thread oneThread = new Thread(oneTask);
步骤5:启动线程:
oneThread.start();
至此,一个线程就创建完成了。
3、通过继承Thread类来创建一个线程:
步骤1:定义一个继承Thread类的子类:
class SomeThead extends Thraad
{
public void run()
{
//do something here
}
}
步骤2:构造子类的一个对象:
SomeThread oneThread = new SomeThread();
步骤3:启动线程:
oneThread.start();
至此,一个线程就创建完成了。
注释:这种创建线程的方法不够好,主要是因为其涉及运行机制问题,影响程序性能。
转自:http://blog.csdn.net/xtwolf008/article/details/7713580