objective-c 语法快速过(4)
oc 里的字符串
字符串的快速创建(最简单的方法)
NSStirng *str = @“Hello”;//oc的字符串都是@“”形式的
oc的字符串也是类的对象,是NSString类的对象,创建没有那么麻烦不用[ ],使用面向对象的思想来操纵字符串。
char *name = "xxxxx";//c风格字符串
oc使用 %@ 输出字符串,不是%s
NSString *name = @”dashuai”; NSLog(@“我的名字是%@”, name);
c 风格字符串输出解析的用法是%s
NSLog(@"%s", name);//%s是c风格的格式化解析
OC字符串的另一方式,Foundation 框架里的 NSString 类
NSString *newStr = [NSString stringWithFormat:@"My age is %d and no is %d and name is %@", age, no, name]; NSLog(@"---- %ld", [newStr length]);
length方法,返回unsigned long类型
NSString *name = @"哈哈达到";
// length方法算的是字数总数,包含的文字的数目!不是求字符个数!!
int size = [name length];
不懂就去查询文档!百度!
// main.m
#import <Foundation/Foundation.h>
/*
NSString : 不可变字符串
NSMutableString : 可变字符串
*/
int main()
{
NSMutableString *s1 = [NSMutableString stringWithFormat:@"my age is 10"];
// 拼接内容到s1的后面
[s1 appendString:@" 11 12"]; // 获取is的范围
NSRange range = [s1 rangeOfString:@"is"];
[s1 deleteCharactersInRange:range]; NSString *s2 = [NSString stringWithFormat:@"age is 10"]; //新建字符串,拼接好的字符串到新建的字符串里,但是原来的字符串没有变!两个方法不一样。
NSString *s3 = [s2 stringByAppendingString:@" 11 12"];
NSLog(@"s1=%@, s2=%@", s1, s2); return ;
} void stringExport()
{
// 字符串的导出
[@"Jack\nJack" writeToFile:@"/Users/apple/Desktop/my.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil]; NSString *str = @""; NSURL *url = [NSURL fileURLWithPath:@"/Users/apple/Desktop/my2.txt"]; [str writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:nil];
} void stringCreate()
{
/*
1.字符串的创建
*/
NSString *s1 = @"jack"; //NSString *s2 = [[NSString alloc] initWithString:@"jack"];这种方法不推荐! NSString *s3 = [[NSString alloc] initWithFormat:@"age is %d", ]; // C字符串 --> OC字符串
NSString *s4 = [[NSString alloc] initWithUTF8String:"jack"];
// OC字符串 --> C字符串
const char *cs = [s4 UTF8String]; // NSUTF8StringEncoding 用到中文就可以用这种编码
NSString *s5 = [[NSString alloc] initWithContentsOfFile:@"/Users/apple/Desktop/1.txt" encoding:NSUTF8StringEncoding error:nil]; // URL : 资源路径
// 协议头://路径
// 本地文件 file://
// ftp://
// 网页资源 http://weibo.com/a.png
// http://www.baidu.com // NSURL *url = [[NSURL alloc] initWithString:@"file:///Users/apple/Desktop/1.txt"];
NSURL *url = [NSURL fileURLWithPath:@"/Users/apple/Desktop/1.txt"]; NSString *s6 = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSLog(@"s6=\n%@", s6); /*
一般都会有一个类方法跟对象方法配对
[NSURL URLWithString:<#(NSString *)#>];
[NSString stringWithFormat:@""];
[NSString stringWithContentsOfFile:<#(NSString *)#> encoding:<#(NSStringEncoding)#> error:<#(NSError *__autoreleasing *)#>];
*/
}
OC的 set 和 get 方法
类的成员变量尽量不要@public,保持数据的隐蔽性和封装性,使用对象直接访问类的成员变量也不推荐,因为这样类的成员变量可以被随意的修改,不安全,而是应该间接的调用。并且直接调用会让别人一下子就看到了类的内部结构和信息,失去了封装的意义。
set方法
1) 作用:用来设置成员变量,可以在方法里面过滤掉一些不合理的值
2) 命名规范:
- 方法名都是以set开头,而且后面跟上成员变量名,成员变量名的首字母必须大写
- 一定接受参数,且形参名称不要跟成员变量同名
- 返回值void
get方法
1) 作用:返回对象内部的成员变量
2) 命名规范:get方法的名称一般就跟成员变量同名
/*成员变量的命名规范:一定要以下划线 _ 开头
@interface Student : NSObject
{
1.让成员变量和get方法的名称区分开
2.可以跟局部变量区分开,一看到下划线开头的变量,一般都是成员变量
*/
int _no;
Sex _sex;
}
// sex的set和get方法
- (void)setSex:(Sex)sex;
- (Sex)sex;
// no的set和get方法
- (void)setNo:(int)no;
- (int)no;
@end
oc特有的语法—兼容c系列的点语法
可以使用点语法来代替oc古怪的对象调用的形式。这是oc特有的让其他(主要是习惯了 c 系列编程语言的程序员,比如 c,c++,java等)程序员快速看懂的一个做法。
// 点语法的本质还是方法调用
p.age = ; // [p setAge:10];
这里还是古怪,到底是get还是set方法,要看是给它赋值了(set),还是被赋值了(get)。还是和java或c++的点语法区分。
oc 中类的成员变量的作用于
@public : 在任何地方都能直接访问对象的成员变量
@private : 只能在当前类的对象方法中直接访问。私有成员只能在本类被直接访问,子类不可见,只能是set和get方法访问(@implementation中默认是@private,因为一般不会包含实现文件,都是包含头文件,故实现文件默认是私有的)
@protected : 可以在当前类及其子类的对象方法中直接访问 (@interface中默认就是@protected)
@package : 只要处在同一个框架中,就能直接访问对象的成员变量,不常用
@interface和@implementation中不能声明同名的成员变量,同名冲突,很好理解
Xcode的一个特性@property和@synthesize
sɪnθɪˌsaɪz v综合合成;(通过化学或生物)合成;(音响)合成
@property
自动生成set和get方法,类似java的eclipse的 setter 和 getter选项
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
int _age;
int _height;
double _weight;
NSString *_name;
}
// @property:只能用在声明里,可以自动生成某个成员变量的setter和getter声明,并且和java还不一样,xcode把自动的声明隐藏,不可见。这是编译器的特性!
下面这一句,代表注释的那两句。
@property int age;
//- (void)setAge:(int)age;
//- (int)age;
@property int height;//先生成set再get
//- (void)setHeight:(int)height;
//- (int)height;
- (void)test;
@property double weight;
//如果成员变量类型一样,可以合并在一起写,但是实际开发不这样,分开比较好
@property NSString *name;
@end
注意:@property里的变量age如果没有被提前声明,那么也是可以运行的,编译器会自动生成_age成员变量,xcode4.4版本之后有的。这样生成的成员变量,在类声明里是@private。若类声明里存此成员变量,如果@property还是那么写,就不会再自动生成。
@synthesize
只写在实现里。可以自动去类声明里找@property,然后根据它去生成类的成员变量的setter和getter方法的实现,并且会访问这个成员变量
@synthesize age = _age;
如果这样写,默认会访问age这个成员变量,如果没有age,就会自动生成@private类型的age变量,都是自动存在类声明里。
注意:xcode4.4之后,为了让程序员把精力放在业务逻辑上,而不是无谓的垃圾代码的书写上,xcode变得越来越方便,做的东西也越多,现在可以省略类的成员变量的声明,直接@property就可以自动生成变量和配套的set与get方法的声明。同样,4.4之后,类的实现里,@synthesize也不用写了。也就是说,set和get的实现不用写。
意味着,现在的@property 声明,类声明里的@property默认做两个事情,即生成set和get的声明,也生成set和get的实现。当然,如果类声明里没有变量声明,那么还要做第三个事情,自动生成私有的成员变量。
Xcode原则就是:没有,我替你生成,有我就直接用。
这里就可以解释为什么苹果建议类的成员变量前面加下划线?
因为@property 的新特性:自从 xcode4.4之后,@property 就独揽了@synthesize 的功能,也就说,@proeprty 可以同时生成成员变量的 set,get 方法的声明和实现,两个都能。默认的情况下,set 和 get 方法的实现,会去访问下划线的成员变量,故要求类的声明里使用下划线的变量命名方式命名成员变量。说到底:就是因为新特性的@property自动生成set,get方法的声明和实现,默认访问的都是前面带下划线的成员变量。
oc 里的 id 类型(万能指针)
id 是一种类型
类型不能做变量名,好比 int int;是错误的,一个道理。
Id 是万能指针
能指向(操纵)任何的 oc 对象,而且不能加*,只写id就代表指针(因为 id内部已经包含*,见官方文档)。
Person *p = [Person new];//传统的操作人的对象,人类型指针p 指向人的对象
万能指针,id能指向 or 操作任何OC对象,只适合用在 oc 对象上
id d = [Person new];//id 指向人的对象
id 的缺点:
如果同样是指向(调用)类不存在的对象方法,那么编译器直接报错!不会弱语法了
千万别加*
oc 的构造方法和重写
构造方法:用来初始化对象的方法,oc里是个对象方法,-开头 -init
面向对象的语言,都包含的东西---构造方法,用和 c++类似的new 这个类方法创建对象,其实不好。
// Person *p = [Person new];不推荐这样创建对象
new 其实是类方法,是 NSObject 类的方法,可以创建对象,分配内存,但是事实上,我们不常用,因为太死板,做的事情很单调,就是完整的创建一可用对象。
完整地创建一个可用的对象其实分两步:
1.分配存储空间 +alloc
2.初始化 -init
new 方法做这两个事情,new 方法内部,调用两个方法(一个类方法,一个对象方法)完成这个步骤,细节为:
1.调用+alloc分配存储空间
Person *p1 = [Person alloc];//此时对象不可用,没有初始化,返回 id(oc 对象)
2.调用-init进行初始化
Person *p2 = [p1 init];反回 oc 对象(已经初始化之后)本身
说明 new 是两个方法的联合,开发不常用,比较死板,一般分两步做,这样后果是方便选择。因为初始化不一定必须是 init对象方法初始化。。
两步合并的简单写法:掌握,开发常用这个写法,从此不用 new 了。
Person *p4 = [[Person alloc] init];
Oc的构造方法就是-init 方法,用来初始化对象的方法。对象方法,每个对象内部的成员变量默认都初始化为0,
创建 person 对象,保证她的_age 默认都是10,不是0,怎么做?
需要重写 –init方法,覆盖父类 –init方法
重写构造方法的目的:
为了让对象创建出来,成员变量就会有一些固定的值
重写构造方法的注意点
1.先调用父类的构造方法([super init])
2.再进行子类内部成员变量的初始化,和 c++类似。
Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property int age;
@end Person.m
#import "Person.h"
@implementation Person
// 重写-init方法,其实 id 有些类似 c++的模板的应用。
//- (id)init
//{
// 1、一定要先调用super的init方法:先初始化父类中声明的一些成员变量和其他属性
self = [super init]; // 返回的是当前oc对象,一定用 self接受,这里需要好好研究,先知道。
// 2.如果父类对象初始化成功,才有必要进行接下来的初始化
// if (self != nil)
// {
// _age = 10;
// }
//
// 3.返回一个已经初始化完毕的oc对象
// return self;
//}
//综合的写法,熟练之后如下这样写:
- (id)init
{
if ( self = [super init] )
{
_age = ;
}
return self;
}
@end
要求:
学生类的学生对象,初始化完毕之后,年龄都是10,学号都是1.还是重写构造方法-init
Student.h继承 person 类
#import "Person.h"
@interface Student : Person
@property int no;
@end Student.m
#import "Student.h"
@implementation Student
// 学生对象初始化完毕后,年龄就是10,学号就是1
- (id)init
{
if ( self = [super init] )
{
_no = ;
}
return self;
}
@end main.h
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main()
{ // 每个stu对象创建出来,他的_age都是10,学生学号都是1,isa 指向本身
每个 p4对象创建出来,她的 _age 都是10,isa 指向本身类
Person *p4 = [[Person alloc] init];
Student *stu = [[Student alloc] init];
return ;
}
student 继承了 person ,而 person继承了 NSObject,比如 student 对象内部有三个成员变量,分别为: student 自己的_no,和继承自父类 person 类的_age,还有 person 最开始就继承的父类NSObject 的 isa指针,这个三个成员变量,都是 student 对象 stu 包含的!
因为student 类 创建 student 对象的时候,先进入 student 类查找-init,(因为 oc 里规定,如果父类和子类有同名方法,子类对象优先调用子类同名方法),然后 在 student 类里发现- (id)init方法,之后又发现:
{ if ( self = [super init] )这句话,那么编译器会率先进入到父类 person,因为 super 的作用 { _no = ; } return self; }
然后先调用直接父类 person 的 –init,而 person 的-init为:
- (id)init { if ( self = [super init] )还是执行到此,我们发现调试就进不去了,因为 super 调用的是 NSObject,苹果是不开源的,但是事实还是进去偷着执行 NSobject 的-init 方法,初始化isa 指针, 把 isa 初始化为指向student 类本身,记住是当前的类,初始化完毕,程序执行回到 person 类,继续向下执行_age=。(同时student 的成员变量 age 变为10) { _age = ; } return self;最后返回的 self 指向的是 当前student 的对象 }
当person的-init 调用完毕,最后才回到 子类student 类,继续执行 student 的-init, 执行_no=1,继承来的 isa 初始化为指向本身 student 类,这才初始化完毕。
person 对象初始化的时候,同理,先在本类查找初始化方法,发现 super 语句,然后再去父类 NSObject 类 里查找-init方法,(这里先记住 self=[super init]的写法,下来再深入),NSObject 做一件事,那就是初始化 isa,把 isa 指向 person 类本身,(指向当前类,这个类是毕源的,看不到内部代码)然后回到 person类,_age=10。执行完毕。
再看一看 student 对象,创建的时候,先初始化,同理在本类,然后 发现 super,那么去父类 person 执行-init,还是发现 super,还是去 NSObject执行-init,把 isa 指向 student 类本身,(当前类不是 person,是 student 了)然后回到 person,_age=10.回到student,_no=1,执行完毕,再回main 函数,初始化,完毕。
oc构造方法的自定义
oc自定义构造方法的规范
1.一定是对象方法, 故一定以 - 开头
2.返回值一般是id类型
3.方法名一般以initWith开头
这让我想起了,c++构造函数的含参构造和默认构造,和不带参数的构造,意义是类似的。其实就是带参构造。和 c++大同小异。
Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property NSString *name;
@property int age;
- (id)initWithName:(NSString *)name;
- (id)initWithAge:(int)age;
- (id)initWithName:(NSString *)name andAge:(int)age;
@end Person.m
#import "Person.h"
@implementation Person
- (id)initWithName:(NSString *)name
{
if ( self = [super init] )固定写法,记住
{
_name = name;
}
return self;
}
- (id)initWithAge:(int)age
{
if ( self = [super init] )
{
_age = age;
}
return self;
}
- (id)initWithName:(NSString *)name andAge:(int)age
{
if ( self = [super init] )
{
_name = name;
_age = age;
}
return self;
}
@end Student.h继承 person 类
#import "Person.h"
@interface Student : Person
@property int no;//_no 是子类 student 自己的属性
- (id)initWithNo:(int)no;
- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no;
@end student.m
#import "Student.h"
@implementation Student
- (id)initWithNo:(int)no
{
if ( self = [super init] )
{
_no = no;
}
return self;
}
// 要理解和接受这个做法和思想:
// 父类的属性交给父类方法去处理,子类方法处理子类自己的属性
- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no
{
// 将name、age传递到父类方法中进行初始化,no 在本类初始化
使用了自定义的构造方法
if ( self = [super initWithName:name andAge:age])
{
_no = no;
}
return self;
}
@end main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Student *p = [[Student alloc] initWithName:@"Jim" andAge: andNo:];
}
return ;
}
每个对象创建之后,都有一个默认名,年龄,和学号,但是每个人的结果不一样。此时,需要使用自定义构造方法初始化。否则重写构造方法初始化的话(不带参数)导致名称都是一样的。不符合程序要求。
首先,创建 student 对象,初始化对象指针 p(指向对象),先在本类找 initWithName 方法,确实有,然后进入执行,将name和age(都是继承来的属性)传到父类方法中进行初始化:这样分工明确(其实和 c++一样的思路),自己做自己的事情,体现了良好的架构思想,还有这样做的好处是,如果我们都统一在子类初始化,那么一旦父类的成员变量名称改变了,会导致子类的代码出错,需要修改,一旦工程较大,后果不堪设想,而分工明确,自己做自己的事情,把父类的成员让父类去初始化,子类只管自己的,就能做到不变应万变。
欢迎关注
dashuai的博客是终身学习践行者,大厂程序员,且专注于工作经验、学习笔记的分享和日常吐槽,包括但不限于互联网行业,附带分享一些PDF电子书,资料,帮忙内推,欢迎拍砖!
objective-c 语法快速过(4)的更多相关文章
- Objective-C基础语法快速入门
Objective-C基础语法快速入门 2010-11-04 16:32 折酷吧 zheku8 字号:T | T 假如我们对面向对象的思维已经C语言都很熟悉的话,对于我们学习Objective-C将会 ...
- jenkins2 pipeline 语法快速参考
jenkins2 pipeline中常用的语法快速参考. 文章来自:http://www.ciandcd.com文中的代码来自可以从github下载: https://github.com/ciand ...
- Razor 语法快速参考
Razor 语法快速参考 本文引自:http://haacked.com/archive/2011/01/06/razor-syntax-quick-reference.aspx 语法名称 Raz ...
- 第二章 C#语法快速热身
C#语法快速热身 语法 if(条件表达式){ 代码块 } 语法 if(条件表达式){ 代码块 }else{ 代码块2 } 语法 if(条件表达式1){ 代码块1 if(条件表达式1)){ }else{ ...
- Less 语法快速入门
Less 语法快速入门 Less 是一门 CSS 预处理语言其可以运行在 Node 或浏览器端. 它将传统的 css 样式结构单一的排版顺序进行了优化,让我们可以通过层级嵌套的方式将 css 类名与H ...
- objective-c 语法快速过(6)内存管理原理
内存管理基本原理(最重要) 移动设备的内存极其有限(iphone 4内存512M),每个app所能占用的内存是有限制的(几十兆而已). 当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不 ...
- objective-c 语法快速过(1)
有一定 c++或者 java 基础,过一遍 oc 语法即可,都是相通的,个人认为难点是 oc 的内存管理,虽然有了 ARC,但是也需要学习下,因为有旧软件的维护. 建立在C语言的基础上,增加了一层小范 ...
- Emmet语法 —— 快速生成HTML结构
快速生成HTML结构语法 1.生成单个标签 : 标签名+tab,比如 div 然后tab 键, 就可以生成 <div></div> 2.生成多个相同标签 div*3 + tab ...
- objective-c 语法快速过(8)
Block(oc 的数据类型,很常用,本质是c结构体) 类似内联函数,从源代码层看,有函数的结构,而在编译后,却不具备函数的性质.编译时,类似宏替换,使用函数体替换调用处的函数名 Block封装了一段 ...
随机推荐
- 关于C#的微信开发的入门记录一
在之前老是看到一些微信开发的例子,但是作为初学者会有很多问题,之前我也找了很多帖子,但是最终也没能解决,现在刚好手里有一个项目,总结一下分享给准备做却动不了手的朋友们,本文只是以我个人的经验作为浅谈( ...
- css中关于居中的问题
居中是最常用的一种css格式,不同的居中方法适和不同的环境中,下面总结了几种常用的居中方法,你可以不用它,但是无论你是一个资深前端大牛,还是小小初学者,当你见到它的时候不认识它就是你的不对啦!!! h ...
- Daily Scrum02 12.16
鉴于近期数据库大作业提交到了关键时期,大家的时间都十分的紧张,因而,我们决定全团队成员交替作业,不在每日每个成员都分配任务,而只需要每个成员保证每两天一次的工作量,以此方式给大家腾出去完成自己的事情. ...
- Allegro之Win7下不能实时刷新操作显示的问题
Allegro软件主界面下: setup-> user preferences-> display->opengl中选定disable_opengl,即关掉OpenGL后,再重新启动 ...
- jQuery代码节选(事件)
事件 1.ready()$(document).ready(function() { //代码});简写:$(function( { //代码});该事件是会在页面加载完后执行,相当于onloca() ...
- php将html转成word文档下载
<meta charset="utf-8" /> <?php class word{ function start(){ ob_start(); echo '&l ...
- WPF整理-使用用户选择主题的颜色和字体
“Sometimes it's useful to use one of the selected colors or fonts the user has chosen in theWindows ...
- 谢欣伦 - OpenDev原创例程 - 串口助手Comm Assist
前一段时间,一位博友发邮件给我.他跟我讲说没太看懂<化繁为简系列原创教程 - 通信专题 - 串口类CxComm的使用>,请我做一个DEMO工程给他.我抽了一天时间编写并上传了一个DEMO工 ...
- ex2-注释和井号
代码: print("I could have code like this.") # and the commnt after is ignored.# You can also ...
- 深入NSQ 之旅[转载]
介绍 NSQ是一个实时的分布式消息平台.它的设计目标是为在多台计算机上运行的松散服务提供一个现代化的基础设施骨架.这篇文章介绍了 基于go语言的NSQ的内部架构,它能够为高吞吐量的网络服务器带来 性能 ...