Xcode & Objective-C 简介 | 青训营笔记

340 阅读4分钟

这是我参与「第四届青训营」笔记创作活动的第2天

一、本堂课重点内容:

本节课介绍了 Xcode 的基础功能,以及专案的结构,结合 Objective-C 语言,带大家完成课程的第一个 Hello World!

image.png

二、详细知识点介绍:

1.Xcode工具

Xcode 是苹果公司推出的一款开发工具,第一个版本于2003时推出,截至目前最新的版本是14.0。
它集合了编译,测试,Git,甚至能直接将你的App提交到AppStore 去做审核。

创建项目

File -> New -> 选择创建 Project , Workspace 或是 Target

工程体系

image.png

Workspace:Workspace 是 Xcode 提供的一个工作空间,一个Workspace可以包含多个project,可以通过多个Project分工组合成一个庞大且复杂的工程。
Project:Project 是一个工程的核心,你可以透过它来管理源代码,资源文件,添加其他三方库...等等,一个Project 可以包含多个 Target。
Target:Target可以看做是一个特定的构建目标,可以是以构建一个App主体为目标,或是构建命令行工具,构建代码二进制库...等。 image.png

2. Objective-C基础

Objective-C是一种通用、面相对象的程序语言,通常我们简称他为OC。它扩充了标准的ANSI C程序语言,可以理解为在C语言之上加了一层,在OC的代码中使用C语言代码也是完全合法可以通过编译的。

介面与实现

编写一个Objective-C的类,由两部分组成,一个是类的定义或叫做介面(接口) Interface,第二个是这个类的实现 Implementation。 image.png

.h 文件 和 .m文件

类的 @interface ,它可以写在 .h文件里也可以放在 .m文件里,@implementation 只能写在 .m文件里。

对象与构造函数

image.png image.png

// main.m
ByteDancer *byteDancer2 = [[ByteDancer alloc] initWithName:@"James"];

函数方法

image.png

3. Objective-C特性

@property属性

基于面相对象封装性的角度,外部想要访问类中的成员变量,最好是要通过Get/Set方法访问的,而不是直接访问变量,因为多个地方都能直接存取变量,会导致这个值容易错乱,于是就有了属性。

image.png

@protocol协议

协议的目的接近于使用父类,就是希望多个不同的类之间都有共通的方法或变量(也就是共通的介面 ),不需要每个类各自的Interface去声明方法。

方法 = 信息传递

在OC里,调用对象的方法,可以看做是给对象发送一个消息,至于他要如何处理这条消息甚至可以到程序在运行时才去决定要如何去回应这个消息。

4.实战

实践练习例子

总结

image.png

三、实践练习例子:

实现一个简易的JSON解析成对象工具

创建project与target

image.png image.png 此时可以看到,Xcode帮我们自动生成了一个main.m文件

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
    }
    return 0;
}

可以看到文件的顶部帮我们引入了Foundation这个框架,Foundation包含了我们常用的许多类,例如字符串 / 数组/ 字典... 等常用的Class,都是系统在Foundation里声明与实现,我们会在下一节课去做介绍。

main函数

接著是main函数,跟C语言一样,main函数是一个程序的主入口,不管是命令行工具还是App,而main函数的参数则是当初启动程序时,外部传入的参数。

自定义解析类(Interface)

新建文件 image.png

//
// MyJsonParser.h
// test1
//

@class** ByteDancer;
@interface** MyJsonParser : NSObject
- (**instancetype**)initWithFile:(NSString *)filePath;
- (ByteDancer *)parse;
@end

自定义解析类(Implementation)

新建文件 image.png

//
//  MyJsonParser.m
//  test1
//

#import <Foundation/Foundation.h>
#import "MyJsonParser.h"
#import "ByteDancer.h"

@implementation MyJsonParser {
    NSString *_filePath;
}

- (instancetype)initWithFile:(NSString *)filePath {
    self = [super init];
    if (self) {
        _filePath = filePath;
    }
    return self;
}

- (ByteDancer *)parse {
    // 读取文件
    NSData *fileContent = [self readFile];
    // 解析JSON内容成字典
    NSDictionary *dictionary = [MyJsonParser parseJsonStr:fileContent];
    // 创建 ByteDancer对象
    ByteDancer *byteDancer = [[ByteDancer alloc] init];
    if ([dictionary objectForKey:@"name"]) {
        byteDancer.name = (NSString *)[dictionary objectForKey:@"name"];
    }
    return byteDancer;
}

- (NSData *)readFile {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSData *content = [fileManager contentsAtPath:_filePath];
    if (!content)
    {
        exit(1);
    }
    return [fileManager contentsAtPath:_filePath];
}

+ (NSDictionary *)parseJsonStr:(NSData *)jsonData {
    return [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
}
@end

其他文件

//
//  ByteDancer.h
//  test1
//

@interface ByteDancer : NSObject
@property (nonatomic, copy) NSString* name;
@end

//
//  ByteDancer.m
//  test1
//

#import <Foundation/Foundation.h>
#import "ByteDancer.h"

@implementation ByteDancer

- (instancetype)init {
    //注意!需要调用父类的init
    self = [super init];
    if (self) {
        self.name = @"郑煜";
    }
    NSLog(@"A ByteDancer Joined!");
    return self;
}

@end

注意:新建一个空文件myjson.json,没有该文件将无法正确运行

设置程序启动参数

image.png image.png 点加号,设置为刚刚新建的.json格式文件的地址

回到main.m

//
//  main.m
//  test1
//

#import <Foundation/Foundation.h>
#import "MyJsonParser.h"
#import "ByteDancer.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        for (int i=0; i<argc; i++)
        {
            NSString *str = [NSString stringWithUTF8String:argv[i]];
            NSLog(@"argv[%d] = '%@'", i, str);
        }
        if (argc < 1) {
            NSLog(@"参数不足");
            return -1;
        }
        NSString *filePath = [NSString stringWithUTF8String:argv[1]];
        MyJsonParser *jsonParser = [[MyJsonParser alloc] initWithFile:filePath];
        ByteDancer *newByteDancer = [jsonParser parse];
        NSLog(@"欢迎! %@", newByteDancer.name);
    }
    return 0;
}

然后点击Xcode左上角的三角形,运行代码,即可得到结果
image.png image.png

产物位置

image.png

image.png
可以在终端用以下方式运行我们的产物
image.png

附图:项目结构
image.png

四、课后个人总结:

  • 本章有什么知识点不容易掌握?
    对于属性、协议、方法要加以区分和掌握

  • 什么地方容易与其他内容混淆?
    区分介面(Interface)和实现(Implementation);区分.h / .m的职责和引入关系

  • 有啥想法?
    实现自己的第一个oc项目,有很多地方不太理解,比如myjson就查了半天,最后发现是个空文件也可以执行.....以我目前的能力,还不知道为啥要这样做.......好歹是做出来了,继续努力吧!

五、引用参考:

学习手册:juejin.cn/post/712271…
课程PPT:Xcode & Objective-C 简介.pptx