Objective-C基础入门

最新需要适配iPhoneX相关的webiview页面,由于没有真机(九千大洋的手机简直了),为了测试及检验适配效果,决定学习iOS开发并在模拟器上对页面进行适配。大概看了一下iOS的Demo代码,感觉Objective-C的语言风格有点魔幻,因此在这里稍作梳理。我只是抱着能在APP中运行webview的目的而已

<!—more—>

发现一个很奇特的现象,与其他语言相比,网上关于OC基础教程居然很少~

1. 开发环境

目前使用的是Xcode(Version 9.0.1 (9A1004))进行开发

  • 使用XCode集成开发环境,新建项目->Mac OS Application项目->Command Line项目即可
  • XCode设置字体时,可以command + A全选所有,然后统一设置字体,

感觉编译还是挺快的,跟写web刷新一下页面的速度差不多,不过没有livereload、热更新等插件,哈哈~

2. 简单梳理

  • OC跟C++类似,均为C语言的扩展,尽管已经有30多年的历史了,但国内大多数人接触并学习OC是起源于2010年之后(iPhone发布)
  • @符号在OC中有特殊用法,编译器会找到他然后做特殊处理,比如区分C字符串和OC字符串
  • 声明变量及初始化与C语言十分相似, 相关运算符也基本通用,支持变量随用随声明
  • 基本数据类型,包括int,float,double,char
  • 限定词long,long long,short,sunsigned,signed
  • 分支运算与循环运算与C基本相似,OC居然支持goto!!!
  • 函数定义包括返回类型,函数名和形参类型,包括完整的函数签名,貌似函数不支持默认参数
  • NSLog输出变量使用NSLog(@"%@", varName)

3. 面向对象

这里参考: iOS - OC 面向对象语法

PS:写OC代码的感觉就是不用按住Shift键来输入小括号了,这个感觉确实不错,虽然写其他语言的代码习惯了。

3.1. 类的声明和实现

类的声明和实现是分开的,以.h文件和.m文件区分

// person.h
@interface Person: NSObject{
      // 成员变量
    @private
        int _age;
    @public
        NSString *_name;
}

// 方法声明

// 构造函数
- (id)initWithAgeAndName:(int)age name:(NSString *)name;

// 静态方法
+ (Person *)getInstance;

// setter和getter
- (int)age;
- (void)setAge: (int)age;

- (void)setName: (NSString *)name;

- (void)introduceSelf;
- (void)greet:(NSString *)name age:(int)age;
// person.m
#import "Person.h"

@implementation Person: NSObject

// 方法实现,回忆起了重写一遍方法声明的恐惧吗
- (id)initWithAgeAndName:(int)age name:(NSString *)name{
    if(self = [super init]){
        _age = age;
        _name = name;
    }

    return self;
}

// 使用静态方法实现单例
static Person *person;
+ (Person *) getInstance{
    if (person == nil){
        person = [[Person alloc] init];
    }
    return person;
}

- (int) age {
    return _age;
}

- (int) age {
    return _age;
}

- (void)setAge:(int)age {
    _age = age;
} 

- (void)setName:(NSString *)name {
    _name = name;
}

- (void)greet:(NSString *)name age:(int)age {
    NSLog(@"Hello %@, you are %d years old",name, age);
}

// 这里没有在类中声明该方法,也可以通过编译
- (void)nothing{
    NSLog(@"Nothing");
}

- (void)introduceSelf {
    NSLog(@"My name is %@", _name);
      // 通过self关键字访问当前对象
    [self nothing];
}

@end
#import "Person.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p1 = [[Person alloc] init]; // init 是NSObject的默认构造函数

          // 方法调用
        [p1 setAge:10];
        int age = [p1 age];

        // int age = p1.age; // 与[p1 age]等价
        NSLog(@"%d", age);

          NSString *str = [[NSString alloc] initWithFormat:@"%@",@"Txm"];
        [p1 greet: str age:24];
        [p1 setName:str];
          // 使用公共属性
        NSLog(@"%@", p1->_name);

          // 使用构造函数
          Person *p2 = [[Person alloc] initWithAgeAndName:24 name:@"Txm"];
        [p2 introduceSelf];

          // 以类名直接调用静态方法
          Person *p3 = [Person getInstance];
        Person *p4 = [Person getInstance];

        NSLog(@"%@", p3 == p4 ? @"same" : @"different");
    }
    return 0;
}

可以发现类的定义和实现与C++比较相似,除了写法略有区别之外。而实例化对象和方法调用就有很大的差别了

  • 减号方法,指普通对象方法声明;加号方法,指类的静态方法声明
  • OC中的点语法是Xcode的高级功能,它将点语法会自动转换成getter,setter方法,这意味着使用点方法必须有两个条件:
    • 必须是属性
    • 有对应的setter和getter

3.2. 封装

访问权限也是通过protect,private,public来实现的,这里的做法和使用方式跟C++比较相似

@private
    int _age;
@public
    NSString *_name;
public:
    int a;
private:
    int b;

不同的是,OC中的方法是没有修饰符的概念的,默认均为public访问,这跟其他面向对象语言略有差异。实现私有方法的方法是:在.m文件中实现该方法,却不在.h文件中声明该方法(比如上面例子中的nothing方法)。

3.3. 继承

OC是单继承,通过super关键字指向父类,该关键字的含义是变化的,指向当前的调用者

// student.h
#import "Person.h"

@interface Student : Person
{
    int _grade;
}
- (int) grade;
- (void) setGrade:(int)grade;

// 覆盖父类方法
- (void)introduceSelf;
@end
// Student.m
#import "Student.h"

@implementation Student

- (int) grade{
    return _grade;
}

- (void) setGrade:(int) grade{
    _grade = grade;
}

- (void)introduceSelf {
      // super关键字调用父类,父类方法中的self不受影响
    [super introduceSelf];
    NSLog(@"I'm student");
}

@end
// main.m
Student *st = [[Student alloc] init];
[st setGrade:100];
[st setName:@"Txm"];

NSLog(@"grade is %d", st.grade);

// 调用父方法
[st greet:@"Txm" age:24];
// 覆盖父类方法并调用
[st introduceSelf];

3.4. 多态

多态是一个非常重要的特性。OC中的多态比C++要简单很多。

Person *p5;
// p5 = [[Person alloc] init]; 
p5 = [[Student alloc] init];

[p5 setName:@"Txm"];
[p5 introduceSelf]; // 根据对象具体的类型调用其方法

4. 小结

尽管OC的写法跟之前学习的其他语言有比较大的出入(C++我忘得一干二净了),但是我觉得:面向对象的特性与语言无关,抛开语言特性,大部分东西都是相同的,因此不必过于拘泥于语法。

不要忘记初衷啊~我只是想试试IOS的webview,学iOS开发真的不是我的本意...