首页 > 其他分享 >ObjectiveC-03-XCode的使用和基础数据类型

ObjectiveC-03-XCode的使用和基础数据类型

时间:2024-03-30 15:30:08浏览次数:19  
标签:03 int NSLog XCode 数据类型 long char main 代码

本节做为Objective-C的入门课程,笔者会从零基础开始介绍这种程序设计语言的各个方面。

术语

  • ObjeC:Objective-C的简称,因为完整的名称过长,后续会经缩写来代替;
  • 项目/工程:也称工程,指的是一个App的源文件的文件夹包和结构,有时也称为工程或项目工程。
  • 项目模板:不只ObjC,用不同编程语言开发App时其源码都会包含源文件、集成框架、配置文件、资源图片等,这些元素需要放在同一个文件中并要符合某种规则,而针对不同类型的App其元素和组织又不一样,这个工作比较费时,所以为了效率考虑一般会经一个母版进行修改,这个母版就称为项目模板;

Command Line Tool工程

首先,我们需要创建一个Command line tool工程项目(即不带图形化界面的项目)。
在这里插入图片描述
在上述工程创建界面上有很多模板项目,可以按需要选择相应的模板开发,这样省去了好多搭建框架的时间,但也可以选择从空项目开始。多数模板可以从字面意思就可以了解。

  • 现在我们只需要知道Command Line Tool工程模板就足够了(一种无UI界面的可在命令行执行的脚本工程模板);
  • 后续在涉及AppKit之前的所有代码我们全会以这类工程为载体演示代码,其它的工程模板在讲到其内容时再详细解释。

创建HelloWorld工程

按照惯例,我们还是以一个Hello Word项目做为开始,了解一下ObjC(ObjectiveC简称)项目结构和基础语法。项目名称暂时称为helloWorld,项目设置采用默认即可,不需要做任何改变,项目结构如下:

在这里插入图片描述

打开main.m文件,我们所有的测试代码暂时全写在这里面,.m是ObjC代码文件的后缀(.c是C语言的源码文件),运行时会交由程序编译器LLVM处理和运行。

//
//  main.m
//  helloWorld
//
//  Created by 刘东 on 2023/12/20.
//

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool { // 自动释放池,由系统来管理变量的内存
        // insert code here...
        NSLog(@"Hello, World!"); // 打包日志函数,用@修饰表示NSString对象
    }
    return 0;  // 规定 0 表示程序正常结束,其它值都是非正常结束
}

除了上述.m文件外还可以兼容几下以类源码文件:

  1. .c:C文件
  2. .cc, .cpp:C++文件
  3. .h:头文件
  4. .mm:Objective-C++文件,可以同时使用ObjectiveC和C++语法;
  5. .pl:Perl文件
  6. .o:ObjectiveC编译后的文件
  7. .m:Objective-c文件

代码注释

在ObjC中只有两种注释:

  • //:行注释,一般用于代码行或代码后面;
  • /* */:块注释,一般用于类说明,方法说明或代码块说明使用;
  • #pragma mark *** String funnel methods ***,这是一种特殊格式的指令,也能起到注释的作用,详细可参考代码导航一节;
// Secondary text that may be displayed

/*
 Secondary text that may be displayed adjacent to or below the primary title depending on the configuration of the window.
 A value of empty string will remove the subtitle from the window layout.
*/

模块导入

格式为:#import <Foundation/Foundation.h> 注意最后面没有;分号,表示为当前类的实现添加相关的模块依赖。如果导入的是自定义的实现,则需要用双引号(本地)替换<>(系统)。

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

上述所谓的系统其实称为框架更合适,比如Foundation、AppKit框架,每个框架都有一个主头文件,它包含了框架内所有的头文件,只需导入一次就可以使用此框架内所有的功能,这样就省去了一个个导入的麻烦。

MAC OS所有框架的目录位于 /System/Library/Frameworks 目录下。

入口函数main

程序运行的主入口函数,格式为:int main(int argc, const char * argv[]),程序的执行入口和java的main函数功能相同,每个App最多只能允许存在一个main函数。一般练习时用main函数调用就行,如果是大型项目ObjC也提供了专门的单元测试框架,后续会讲到,main.m语法格式如下:

static void method(){
}

/*
argc:命令行输入的参数个数
argcv:字符指针数组,即参数值
*/
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //代码位置
    }
    return 0;
}

运行传参

函数说明:int main(int argc, const char * argv[])

  • argc:命令行输入的参数个数
  • argcv:字符指针数组,即参数值,argcv[0]指向一个函数,argcv[1]为一个字符数组
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        struct entry dict[100] = {
            {"abyss", "a bottomless pit"},
            {"addle", "to become confused"}
        };
        
        int entries = 10;
        int entryNumber;
        int lookup(struct entry dict[], char search[], int entries);
        
        if (argc!=2){
            NSLog(@"no word typed on the command line.");
            return 1;
        }
        
        entryNumber = lookup(dict, argv[1], entries);
        if(entryNumber!=-1){
            NSLog(@"%s", dict[entryNumber].definition);
        }
    }
    return 0;
}

调用方法如下,可从命令行,也可从Xcode中执行

clang -fobjc -arc main.m lookup abyss - 

上述程序会调用函数lookup,然后在dict字典中查找argv[1]中的单词,如果找到就返回详细的解释。

添加函数

在main函数所在的类中也可以添加自定义的方法,但方法的命名方式和ObjC的语法有很大不同,这一点需要额外注意。在main中定义的方法是C语言的语法。

#import <Foundation/Foundation.h>

//无参方法,在方法前面也可以添加static关键字
void nsRangeTest(){
    NSRange range1 = {17, 4};
}

//有参方法
NSComparisonResult *compareArray(id element, id compareEle){
    return [[compareEle name] compare: [element name]];
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        nsRangeTest();
    }
    return 0;
}

打印函数NSLog

打印函数,相当于C语言或JAVA语言的print()函数,这里需要注意写法,一定是以@开头,这也说明了NSLog函数的入参是一个NSString类型的对象(在ObjC语言中,字符串用@""表示),另外所有的Cocoa函数和对象全部以NS做为命名前缀(也被称命名空间),也有一些老的API是采用CF开头的但不建议使用了。

NSLog(@"Hello, World!");
int sum = 20+25;
NSLog(@"The sum is %i", sum); //NSLog函数如果发现%,则视为占位符,这样的占位符有很多,后续会讲到

也可以用printf()函数来代码,但不是太建议,因为NSLog添加了很多格式化的信息,注意看下面代码的输出

        NSLog(@"Hello, World!\n");
        printf("Hello, World!\n");
        
        ~~~~
        2024-03-26 19:31:52.091265+0800 helloWorld[46546:5251675] Hello, World!
        Hello, World!

键盘输入

scanf()函数也可以使用占位符,因为键盘接收的原始数据全是字符串,在程序中需要做一些类型转换工作。下在程序运行后在scanf处会卡住,然后在控制台输入相应字符后就会往下执行了。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int age;
        scanf("%i", &age); //注意&的用法,它表示一个指针引用,
        NSLog(@"age is %i", age);
    }
    return 0;
}

/*~~
aaa
2024-03-27 14:39:56.103878+0800 objcBase[59017:6048518] age is 32759
Program ended with exit code: 0
*/

程序运行

除了使用Xcode工具运行,还可以使用命令行工具执行。其命令如下,其中prog1为重命名的项目名称。但这种方式并友好,因为还在设置PATH等资源目录。

(base) MacBook:~ liudong$ clang -fobjc-arc main.m -o prog1

(base) MacBook:~ liudong$ clang -fobjc-arc -framework Foundation main.m -o prog1

输入类似下面的界面:
在这里插入图片描述
用NSLog输出时,上面的4596表示当前应用的进程ID号。另外编译好的文件一般会存放在以下目录中,其中helloWorld-ghwqfuwptpnvhtfpzqoxxzcbnzow是一串随机值。不同版本的OS操作系统存放的位置有可能不太一样。

~/Library/Developer/Xcode/DerivedData/helloWorld-ghwqfuwptpnvhtfpzqoxxzcbnzow/Build/Products/Debug

进入这个目录下可以执行./helloWorld就可以直接运行应用了。
在这里插入图片描述

程序中止

有两种方式一种是在main函数中中止,一种是在方法中强制中止,在main函数中直接使用retrun 0即可,则在方法中需要使用以下代码。

exit(0);

设置XCode

首先来讲,苹果公司通常喜欢在不同版本的XCode中增加或移动一些功能,而且这些功能对开发代码的效率是非常高的。下面就以XCode V13版本为例来说明下这些设置如何操作。

主界面

在这里插入图片描述

  • 导航器:用来显示项目的源码,最上面的有9个左右的工具栏,包括:符号、搜索、总是、调试、断点和日志等,快捷键盘是command+数字1~9;
  • 工具栏:这里最主要的是库面板,需要从菜单View-Show Toolbar打开;
  • 检查器:不同的文件会有不同的设置,也就是属性设置面板;
  • 代码编辑区:在最上面有一个面包屑栏和工具栏,工具栏上有导航文件功能,面包屑栏显示了当前文件一些内容。这块的功能比较简单,点一次就可以记住了;

环境下载

在Preferences偏好设置中可以下载不同的运行环境:
在这里插入图片描述

代码自动完成

XCode有代码提示功能,输入一个字符会有默认提示,通过ESC键来打开或关闭提示框,然后通过Control+/-可实现快速翻页。
在这里插入图片描述

  • # :代表define指令;
  • m :表示method;
  • f :表示函数;
  • c :表示类

代码导航

可以通过在源码中设置特殊的标识来把需要关心的代码加入到代码面包屑工具栏中,这些标识在编译时会被编译器忽略掉。
在这里插入图片描述
这些特殊标记通常用:

  1. -,减号实现一个分隔线,见上图
  2. whatever,任意字符;
  3. //开头的特殊标记,以关键字+冒号+空格+文字描述格式,比如//TODO: 未完成的工作,这些关键字一般有TODO:、FIXME:、!!!:、???:

快捷键

  1. 鼠标左键+option,然后点击某个类型,在弹出窗口点击相应的类型名可直接跳转到document;

  2. control+i,格式化代码;

  3. command+d,删除行(需要在keymap中搜索delete line自行设置);

  4. command+左/右箭头,快速移到行首和行尾

  5. command+shift+o,快速查找;

  6. command+option+左/右箭头:展开和折叠代码,功能们于Edit-Code Folding下面

  7. command+option+shift+左/右箭头:展开和折叠所有方法

  8. command+r,运行程序

  9. command+u,测试程序

另外可供编辑使用的快捷键盘就是电脑上的触摸屏,可通过Edit-Customizer Touch bar 来设置,如下:
在这里插入图片描述

程序调试

主要使用以下几个工具,依次是:跳到下一个断点、下一行、进入被调用的方法、跳出被调用的方法。分别对应快捷键F5~F8。

在这里插入图片描述

另一个调试窗口在导航区上,与调试区联动,主要是下图中这两个标签页,一个是性能查看,另一个是断点浏览
在这里插入图片描述
鼠标悬浮到某个程序变量上也会显示相应的信息
在这里插入图片描述
还有一些更高级的功能可以在控制台输入相应的指令,比如:

  • call [exp]:调用给定对象的方法;
  • print [exp]:打印表达式的原始值,比如print [int] [obj length];
  • print-object [exp]:打印表达式的对象值;
  • set [v] = [exp]:给表达式赋值;
  • whatis [exp]:判断变量的类型;
  • help:帮助;
    在这里插入图片描述

静态检查器

这个功能是不是一个新的功能,很多IDE都有此种能力,有些还会以插件的形式存在,比如sonna, understand或是idea中的各种分析插件。

静态检查器的功能就是不运行代码来分析代码中可能存在的一些问题,在xcode中其功能集中在菜单"project-Analyze"中,它可以检查代码中的:

  1. 安全问题;
  2. 并发问题;
  3. 逻辑问题;
  4. 冗余代码;
    在这里插入图片描述
    疑似有问题的代码可以在导航面板中查看,找到问题后可在面板中点Fix来修复这些警告信息。
    在这里插入图片描述
    有时也会误报,因为检查器毕竟也是一段逻辑固定的程序,没办法覆盖所有的代码模式,如果发现了语报除了用上面 Fix 来关闭外,也可以在方法后加一个特殊标识来告诉检查器这块的这个问题不要检查了,比如:
//类似这样的标签还有很多,可以按需选择
static void dataFun (void) NS_RETURNS_RETAINED {  }

基础数据类型

基础数据类型

布尔类型

关键字BOOL,其值默认只有YES或NO,在Objc中只可与1和0相互转换,占8位存储空间,在写程序时也可以用#define把TRUE和FALSE定义为1 和 0,示例如下:

BOOL areIn(int thing, int ti){
    if (thing == ti){
        return (YES);
    }
    return NO;
    
    //return thing = ti; 这行代码有问题,因为ObjC中只有0和1来平替YES和NO
}
NSString *bool2Str(BOOL y){
    if (y == YES){
        return @"yes";
    }else{
        return @"no";
    }
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        BOOL *boolV = areIn(1, 2); 
        NSLog(@"%d = %@", boolV, bool2Str(boolV)); //0 = no
        
        NSLog(@"%d = %@", 1, bool2Str(1)); //1 = yes
        NSLog(@"%d = %@", YES, bool2Str(YES)); //1 = yes
        
    }
    return 0;
}

char字符类型

单个字符,用’'单引号表示

char c = 'a';

int整数类型

int i = 1000;

float浮点类型

带小数点的变量,比如

float f = 123.95;

double双精度浮点数

双精度

double d = 8.44e+11;

字符串常量

字符不是一个基本类型,它是一个对象,在使用时除了用对象实例化后,简单的可以直接用@“”,来表示:

NSString *str = @"korgs";
创建一个可变字符串
NSMutableString *stringM1 = [[NSMutableString alloc] initWithString:@"字符串"];

可用cString打印字符串内容,它返回的是一个char *指针地址。

 NSString *string = @"abdc";
        NSLog(@"%@, %s", string, [string cString]);

类型限定词

ObjC中的数据类型定义非常有意思,支持组合定义,这些限定词主要包括:long, long long, short, unsigned和signed这几个,它的作用是扩充原有数字的表述范围,具体的范围会根据系统决定,比如

long int factorial; //声明为long的整形变量

long, long long, short, unsigned和signed

类型运算符

  1. 四则运算: +、 -、 *、 \、 %、++、–
  2. -(负号)
  3. 类型强转,这里和java一样, 比如这样的写法 int a = (int)f,f为一float类型
  4. 赋值运算:=、!=、+=、-=、/=、*=
  5. 三元运算符:condition ? expression1: expression2
  6. 位运算:&、 |、 ^、 ~(求反)、 << 、>>
  7. 关系运算:==、!=、< 、 > 、 <= 、 >=

运算规则

主要是数值上面:

  • 同类型的的数相互运算,结果是同类型;
  • bool, char, short, int, bit field, enum全部转为int再运算;
  • 大类型与小类型运算结果为大类型,比如long int / short int = long int;

数据打印

以上类型如果需要用NSLog等函数打印时,其占位符表示都不太一样,大体如下。当用%@时表示可以打印任何内容。看似很复杂,其实就四个特殊的,float, long, unisigned, long long,分别用f, l(L), u(U), ll(LL)来表示,其它的不是太常用

类型实例示例NSLog字符
char‘a’ ‘\n’%c
short int123%hi, %hx, ho
unsigned short int123%hu, %hx, %ho,%hx
int12, -97, 0177(8进制)0xFEE0(16进制)%i, %x, %o
unsigned int12u, 100U, 0xFFU%x, %0, %u
long int12L, -2001, 0xFFFFL%li, %lx, %lo
unsigned long int12UL, 100ul, 0xFFFFUL%lu, %lx, %lo
long long int500ll, 0xe5e5e5LL%llu, %llx, %llo
float12.32f, 3.1e-5f%f, %e, %,g, %a
double12.32, 3.1e-5%f, %e, %g, %a
long double12.34L, 3.1e-5l%Lf, %Le, %Lg
idnil%p
**p(指针)%@
  1. %@:是一个通用字符可表示任何数据,可归类为打印对象,它会调用类的description:方法;
  2. %s:打印字符串

标签:03,int,NSLog,XCode,数据类型,long,char,main,代码
From: https://blog.csdn.net/liudonglovehemin/article/details/137172809

相关文章

  • 2024-03-30:用go语言,集团里有 n 名员工,他们可以完成各种各样的工作创造利润, 第 i 种工
    2024-03-30:用go语言,集团里有n名员工,他们可以完成各种各样的工作创造利润,第i种工作会产生profit[i]的利润,它要求group[i]名成员共同参与,如果成员参与了其中一项工作,就不能参与另一项工作,工作的任何至少产生minProfit利润的子集称为盈利计划,并且工作的成员总数最多为......
  • Java的基本数据类型
    Java是一种强类型语言,这意味着每个变量和每个表达式都有一个明确的类型,这些类型在编译时期就已经确定。在Java中,基本数据类型(PrimitiveTypes)是构建复杂数据结构的基础,它们是不可再分的数据,直接存储值,而非引用。Java定义了八种基本数据类型,分为四类:整型、浮点型、字符型和布尔......
  • centos7提示 file /root/.serverauth.13703 does not exist
    情况背景:安装虚拟数据服务器,使用系统为centos7,安装完成后,开始安装图形化程序,在虚拟服务器上一切正常,输入startx也会正常显示图形操作界面问题来源:现在通过其他电脑远程连接虚拟数据服务器,输入地址进入也是正常,但是输入“startx”命令后就显示失败代码,无法进入图形操作界面,如......
  • 003 git的日常操作-新建分支
    新建分支一、本地仓库与远程仓库都无此分支创建本地分支dev并将其关联到远程仓库的origin/dev分支。步骤:检查当前所在分支,确保不在dev分支上:gitbranch如果不在dev分支上,切换到master或其他主分支-取决于你想让该分支拥有那个分支的数据:gitcheckoutmaster......
  • 20240328
    续昨天。T8洛谷P4150最短路问题行数很小,考虑使用矩阵。对于一个区间\([l,r]\),维护\(ll_{i,j},rr_{i,j},lr_{i,j}\)分别表示\((i,l)\rightarrow(j,l)\)、\((i,r)\rightarrow(j,r)\)、\((i,l)\rightarrow(j,r)\)的最小代价。为了转移方便,再维护\(lm_{i......
  • 20240329打卡
    第五周第一天第二天第三天第四天第五天第六天第七天所花时间20h4h4h2h3h代码量(行)877164371214478博客量(篇)11111知识点了解navigation路由配置,jetpackcompose组件运用,容器封装第一次结对作业开始Web搓后端ing~完成了大部分个人W......
  • 2024-03-29
    2024-03-29LOG对于小于等于\(s\)的数\(x\),最多被选\(x\)次大于\(s\)的数最多被选\(s\)次看所有小于等于\(s\)的数字的和加上\(s\)乘大于\(s\)的数字的个数这个值是不是大于等于\(c\timess\)就行离散化之后权值线段树维护一下离散化之后线段树右边界应该......
  • clean maven工程报错: Cannot find JRE '1.8 (1)'. You can specify JRE to run maven
    在双击Maven的clean时,报错:CannotfindJRE'1.8(1)'.YoucanspecifyJREtorunmavengoalsinSettings原因可能是自己之前下载的是JDK17,并且IDEA认为该JDK为默认JDK,而我的Maven项目设置使用的是JDK8,因此报错。解决方案如下:点击File-settingBuild,Execution,Deploy......
  • 20240329
    没想好副标题。上午打了一场NOIP模拟赛,有两道题因为忘了判\(1\)的情况挂了73pts,痛失rk1,最后rk5。然后T4还是把「NOIP2020排水系统」那道题魔改之后的sb题,实际上多打一个DAG上拓扑排序就好了。蚌,下午听线段树与平衡树,但实际上几乎没讲怎么实现,一直在讲题讲题讲......
  • 2024年03月CCF-GESP编程能力等级认证C++编程八级真题解析
    本文收录于专栏《C++等级认证CCF-GESP真题解析》,专栏总目录:点这里。订阅后可阅读专栏内所有文章。一、单选题(每题2分,共30分)第1题为丰富食堂菜谱,炒菜部进行头脑风暴。肉类有鸡肉、牛肉、羊肉、猪肉4种,切法有肉排、肉块、肉末3种,配菜有圆白菜、油菜、豆腐3种,辣度有......