Objective-C大爆炸:从零到单例模式

oc学习笔记(一)

文章目录

  • oc学习笔记(一)
    • oc与c语言的区别
      • #import的用法
      • foundation框架
      • NSLog函数
      • NSString类型
      • @符号的作用
        • oc中的数据类型
    • 类与对象
      • 概念:
    • 创建第一个类
      • 类的定义
      • 类的实现
      • 类加载
      • 对象的产生和使用
    • self语法
    • id类型
    • 方法
      • 形参个数可变的方法
    • 单例模式(Singleton)
    • 分组导航标记
    • 总结

oc与c语言的区别

c语言是面向过程语言,oc则是面向对象是语言,这两者之间究竟有什么区别呢?

面向过程的语言:主要是用于单片机,嵌入式的开发,因为这些编程需要实例化,对内存等资源开销较大,性能是其判断优劣最重要的因素,其缺点就是:相对于面向对象语言来说,较难维护,且不易扩用和扩展

面向对象的语言:易于维护,复用和扩展,由于面向对象语言所用的三个特点,分装,继承和多态,会比较容易写出低耦合,高复用的程序,使得系统更加灵活,易于维护。当然与面向过程的语言比起来,性能会较低。

举个例子吧,如果说面向过程是一份蛋炒饭的话,那么面向对象则更像一份盖浇饭,怎么理解呢?
对于蛋炒饭来说,饭中的每一种配料——即为功能,都非常均匀的融合在了一起,他的突出特点就是香——即性能一般来说高于盖浇饭,但是如果不想要蛋炒饭的某种东西,比如香菜,那么你只能将整份饭重做一遍。
对于盖浇饭来说呢,就是将浇盖的内容和饭分别准备好,如果你不喜欢吃香菜,那我们只需要做一份去掉香菜的盖浇内容,饭和菜之间的耦合度很低,相对的可维护性就较好,对于盖浇饭能够任意的根据需求组合出任意的搭配。

oc相对于c语言

  1. 在c语言的基础上增加了部分面向对象的语法
  2. 将c语言较为复杂的封装语法简化
  3. oc完全兼容c语言
  4. main函数仍为函数的主入口

**oc程序的后缀:**oc文件的后缀名为.m,m代表oc中的一个重要机制message机制

#import的用法

作为oc中特有的预处理指令,它其实就是#include的升级版:

  • 无论如何我们#import一个文件多少次,只会包含一次,即我们不用像在c语言中配合条件编译指令,可以无脑#import
  • 在#import指令运行过程中,指令本身先会判断这个文件本身是否被引用,若没有被引用则才会被引用

foundation框架

框架:将在一些开发程序的过程中,把事先需要使用的功能写好,把这些功能分装在类或者函数之中。框架即为类与函数的集合,类比为c语言的函数库。

只要#import <Foundation/Foundation.h> ,就可以使用foundation框架的内容

NSLog函数

NSLog函数是增强版的printf函数

NSLog(@"输出的内容");

其优点相对于printf来说有以下几点:

  1. 会输出打印出执行该行的时间,输出程序的名称,进程编号:线程编号,双引号的内容
  2. NSLog会自动换行
  3. NSLog函数还是可以使用与printf相同的占位符

注:NSLog函数的第一个参数为oc字符串,实参的第一个必须以@开头

NSString类型

oc设计了一个更适合存储字符串的类型,专门用来存储oc字符串的地址。
"String"是c语言的字符串,@"string"是一个oc的字符串,其区别就在与字符串前的@

所以NSString就是只能用于存储oc字符串的地址
NSString *s = @"string"

如果在NSLog函数中想打印出NSString类型的字符串,占位符为%@

@符号的作用

  1. 将c字符串转化为oc字符串
  2. oc的关键字大多数以@开头
oc中的数据类型

支持c语言中的数据类型

  1. 基本数据类型:int char ……
  2. 结构类型:结构体
  3. 指针类型:int*
  4. 空类型:void

oc特有的数据类型bool

  1. 可以存储YES或NO的值
  2. 一般用于存储条件表达式子的结果
  3. 本质为有符号的char变量,YES为1,NO为0

boolean

  1. 本质与bool类型相同,但是一个无符号的char类型

class类型:

id类型:


类与对象

对于面向对象语言来说,最大的特点就是类与对象。

概念:

​ 对于类来说,就是某一批对象的抽象集合体;对象则是具体存在的实体。

​ 举个例子:鹿中有许多不同的品种梅花鹿,麋鹿等等……但是他们都可以被抽象归类为鹿。那么不同的鹿品种就相当于对象,而鹿的总称就为类。

创建第一个类

类的定义

image-20240418205605827

类的本质可以被理解为,自定义的一种数据类型,是在内存开辟空间的模版。

在OC中类的定义一共包括两部分:

  • 接口:定义该类包含的成员以及方法
  • 实现:为该类的方法提供实现

在上图中我们可以看到,@interface用于声明定义的接口部分,@end说明结束声明。

一般来说,我们会将定义类的声明放在.h文件当中,以方便程序的维护。

以下是一个简单的类的实现:

//student.h中的内容
#import <Foundation/Foundation.h>
//Student为类名, NSObject为对象名
@interface Student: NSObject {
    //成员名应被定义在大括号之中,且成员名前缀应该有_
    int _age;
    int _nums
}
- (int)age; //返回值为int的get方法
- (void)setAge:(int)newage; //set方法,一个冒号对应一个参数,没有冒号说明不用传参
- (void)setAge:(int)newage andNums:(int)newnum;//如果我们需要写一个能够获得两个变量的 get 方法
@end
  • -代表为动态方法,也称实例方法,必须对象才能够进行调用

  • +代表为静态方法,也称类方法,直接用类名就可以进行调用

类的属性不能不能在声明里赋值。

在我们创建类的时候如果包含了其他类的对象,我们其实创建的是该被包含对象的指针变量,而没有生成对象

类中方法的命名也有其相应的规则:

image-20240418210524154

该注意的是,在方法声明当中,所有的类型(包括void)都需要用圆括号扩起来。并且类的接口部分只是声明方法,并没有为类的实现提供方法体,因此在声明方法之后,应该添加一个分号,代表着声明结束。

类的实现

//student.m的内容
#import "student.h"
@implementation Student

- (int)age {
    return age;
}

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

- (void)setAge:(int)newage andNums:(int)newnum {
    _age = newage;
    _num = newnum;
}
@end

@implementation为类实现的开头,而@end同样为类实现的结尾

​ 关于类实现部分的语法说明如下:

  • 类实现部分的类名必须与类接口部分的类名相同,用于表示这是同一个类的接口部分和实现部分。类名必须大写。

  • 类实现部分也可声明自己的成员变量,但这些成员变量只能在当前类内访问。因此,在类实现部分声明成员变量相当于定义隐藏的成员变量。

  • 类实现部分必须为类声明部分的每个方法提供方法定义。方法定义由方法签名和方法体组成:实现部分除了实现类接口部分定义的方法之外,也可提供额外的方法定义——这些没有在接口部分定义,只是在实现部分定义的方法,将只能在类实现部分使用。

  • 方法体里多条可执行性语句之间有严格的执行顺序,排在方法体前面的语句总是先执行,排在方法体后面的语句总是后执行。

类加载

  1. 在创建对象的时候必须先访问类
  2. 声明一个类的指针变量也是会访问类的

当程序在运行的期间,某一个类被第一次访问到的时候,会讲这个类存储值内存中代码区,此过程就被称为类加载,当此类被加入到代码区之后,直至程序结束才会被释放。

对象的产生和使用

在.h文件中的所有方法都为公共方法

//main.m中创建变量
#import <Foundation/Foundation.h>
#import "student.m"
int main(int argc, const char* argv[]) {
    @autoreleasepool {
        Student* stu = [Student alloc];
        stu = [stu init];
        [stu release];//对象只能释放一次
    }
}

分配内存为静态方法alloc或者new,创建对象的语法格式为:[类名 + 方法名]

[Student alloc] ,对象之中还有一个指针,在创建时会指向该对象所属的类在代码段中的地址,称之为isa,相同类的对象该指针指向相同。

[Student new] (这种方法比较少用)

调用动态方法 init为对该对象进行初始化:

  • 如果属性类型是基本数据类型,那么就赋值为0;
  • 如果该属性类型是C语言的指针类型,那么就赋值为NULL;
  • 如果为OC类型的指针,那么就会返回nil
Student* stu = [Student alloc];
stu = [stu init];

两个可以写为一个

Student* stu = [[Student alloc] init];//定义变量的同时,为变量赋值
[stu release] //对象释放

allocinit方法可以被直接调用,因为其都属于父类NSObject的方法

在主函数里面调用类的方法

#import <Foundation/Foundation.h>
#import "student.m"
int main(int argc, const char* argv[]) {
    @autoreleasepool {
        Student* stu = [[Student alloc] init];
        [stu setAge : 100];
        int age = [stu age];
        [stu setAge: 10 andNums: 10];
        [stu release];//对象只能释放一次
    }
}

self语法

oc如同其他面向对象的语言一样,在类与对象之中,存在关键字self,指向该方法的调用者,当我们需要在实现过程中调用当前类中的方法时就可以使用self来给我们的程序赋值。在我们先前的实现中,我们刻意避开set方法中传入变量的名称与我们类中的名称不相同,那如果相同就需要self语法来进行set方法的操作。

//student.m的内容
#import "student.m"
@implementation Student

- (int)age {
    return age;
}

- (void)setAge:(int)_age {
    self-> _age = _qge;
}

- (void)setAge:(int)_age andNums:(int)_num {
    self-> _age = -age;
    self-> _num = _num;
}
@end

或者说如果在一个方法中需要调用到该类的另一个方法,那么也是使用self

#import "FKDog.h"
@implementation FKDog
1/ 实现一个jump 方法
- (void) jump
{
	NSLog (@"正 在 执 行 jump 方 法 " );
}			
// 实现一个run方法,run方法需要借助jump方法 
- (void) run {
	[self jump]: 
  NSLog(@"正在执行run 方法");
}
@end

注:一般来说对象的属性是不能被直接访问的,如果不使用相应方法,允许对象属性可以被外界访问,这需要在声明属性时添加@public关键字。访问的方式为:对象名->属性名 = 值;

id类型

id可以理解为任何对象,有点像c++中的auto类型,系统的在运行的时候会实行动态绑定,在运行的时候判断其对象所属于的类。

//main.m中创建变量	
#import <Foundation/Foundation.h>
#import "student.m"
int main(int argc, const char* argv[]) {
    @autoreleasepool {
        id stu = [[Student alloc] init];
    }
}

方法

Objective-C的方 法不能独立存在 ,所有的方法都必须定义在类里。方法在逻辑上要么属于类,要么属于对象。我们必须创建对象才可以调用方法。

方法的命名规则:

  1. 如果只有一个参数,那么最好为xxxWith,使得程序就像一个语句一样,拥有主谓宾,提高程序可读性。
  2. 如果具有多个参数,xxxWith:(int) and:(int)

在方法中,使用+标识符则说明该方法属于这个类,-标识符则说明这个方法是该类的实例。
类的声明和实现必须要有,就算没有方法,类的实现也是必不可少的。在特殊情况下,可以只有实现,没有声明。

当对象作为方法的参数的时候,参数类型为类指针。

形参个数可变的方法

为了在程序中获取个数可变的形参,需要使用如下关键字 。

va_list:这是一个类型,用于定义指向可变参数列表的指针变量。
va_start:这是一个函数,该函数指定开始处理可变形参的列表,并让指针变量指向可 变形参列表的第一个参数。
va_end:结束处理可变形参,释放指针变量。

va_arg : 该 函 数 返 回 获 取 指 针 当 前 指 向 的 参 数 的 值 , 并 将 指 针 移 动 到 指 向 下 一个 参 数 。

下 面 的 实 现 类 对 上 面 的 t e s t :方 法 提 供 了 实 现 。

#import "VarArgs.h"
@implementation VarArgs
- (void) test:(NSString *) name,...{
// 使用va_1ist 定义一个argList 指针变量,该指针变量指向可变参数列表
	va_list argList;
  // 如果第一个name 参数存在,才需要处理后面的参数
  if (name) {
    // 由于name参数并不在可变参数列表中,因此先处理name参数
		NSLog (@"&®" , name) ;
// 让arglist指向第一个可变参数列表的第一个参数,开始提取可变参数列表的参数 
    va_start (arglist, name) ;
    // va_arg用于提取argList指针当前指向的参数,并将指针移动到指向下一个参数 
//arg变量用于保存当前获取的参数,如果该参数不为ni1,则进入循环体 
    NSString* arg = va_arg (arglist, id) ;
    while (arg) {
      // 打 印 出 每 一个 参 数
			NSLog(@"%@" ,arg):
      arg = va_arg (argList, id) ;
      // 再次提取下一个参数,并将指针移动到指向下一个参数 
    }
  }
  // 释放argList指针,结束提取
	va_end (argList);
}

​ 当一个指针为nil的时候,通过这一个指针去调用该对象的方法,运行不会报错,只是不会运行此方法。

单例模式(Singleton)

​ 有些时候我们在程序只需要存在一个类的对象,频繁的创建只会使得系统性能下降,比如:系统只有一个系统管理器,,一个打印设备……

​ 如果一个类始终在程序中只能创建一个实例,那么我们则称这个类为单例类。
​ 单例类可以通过全局变量声明static来实现,我们在实现方法中每当程序需要获取该类的实例时,需要先判断全局变量是为nil,如果不为nil再进行变量的创建,并将变量赋值给该单例类。若不为nil则直接返回全局变量的值。

请添加图片描述

分组导航标记

方便我们查看我们声明的各类和各方法实现

  1. #prama mark 分组名 就会使得导航条对应位置显示一个标题,相当于注释,支持中文
  2. #prama mark - 会在导航条处产生一条水平分割线
  3. #prama mark - 分组名 分割线和标题同时产生

总结

这是对此篇学习笔记的总结与复习

  1. OC与C语言的区别: OC是面向对象语言,相比C语言更易于维护、复用和扩展,同时兼容C语言,并在其基础上增加了面向对象特性。
  2. 类与对象: 类是对象的抽象模板,包括接口部分(声明成员和方法)和实现部分(提供方法的具体实现),而对象则是类的具体实例。
  3. 对象的创建和使用: 对象的创建包括分配内存(alloc)和初始化(init),通常合并为[[Class alloc] init],对象的释放使用release方法。
  4. 方法: 方法是类中的行为,分为实例方法(使用-)和类方法(使用+),需要在接口部分声明并在实现部分提供具体实现。
  5. 单例模式(Singleton): 单例模式确保类在程序中只有一个实例,并提供全局访问点,可以通过静态全局变量实现,确保类的实例唯一性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/583695.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GaussDB数据库事务管理

一、引言 事务管理是数据库系统中至关重要的一部分&#xff0c;它确保了数据库的一致性和可靠性。在GaussDB数据库中&#xff0c;事务管理不仅遵循传统的ACID特性&#xff0c;还提供了一些高级功能。本文将深入探讨GaussDB数据库事务管理的各个方面。 二、事务的基本概念 2.1…

前端页面单元测试最佳策略:全面涵盖逻辑、组件、流程、UI及性能优化测试,全面保障软件应用的质量

页面级别的测试要求我们从更宏观的角度审视应用&#xff0c;不仅关注单个组件的正确性&#xff0c;还要确保组件间的协作无误&#xff0c;以及用户在应用中的完整体验。通过集成测试、E2E测试和场景测试&#xff0c;我们可以更全面地覆盖应用的各种使用情况&#xff0c;提高软件…

Educational Codeforces Round 165 (Rated for Div. 2) (C、D)

1969C - Minimizing the Sum 题意&#xff1a; 思路&#xff1a;观察到操作数很小&#xff0c;最值问题操作数很容易想到dp&#xff0c;用表示第个元素&#xff0c;操作了次的最小值总和&#xff0c;转移的时候枚举连续操作了几次即可&#xff0c;而连续操作了几次即将全部变成…

机器学习:基于Sklearn、XGBoost框架,使用逻辑回归、支持向量机和XGBClassifier来诊断并预测一个人是否患有自闭症

前言 系列专栏&#xff1a;机器学习&#xff1a;高级应用与实践【项目实战100】【2024】✨︎ 在本专栏中不仅包含一些适合初学者的最新机器学习项目&#xff0c;每个项目都处理一组不同的问题&#xff0c;包括监督和无监督学习、分类、回归和聚类&#xff0c;而且涉及创建深度学…

Linux硬盘挂载操作记录

文章目录 1.前置概念2.挂载步骤2.1查看盘信息2.2挂载整个盘到指定目录2.3将盘划分为多个分区并挂载到不同目录2.3.1创建分区2.3.2指定文件系统2.3.3挂载目录 3.删除分区 1.前置概念 分区&#xff1a;分区就是将硬盘划分为多个区域&#xff0c;每个区域都有自己的文件系统&…

AI智能名片商城小程序:引领企业迈向第三增长极

随着数字化浪潮的席卷&#xff0c;私域流量的重要性逐渐凸显&#xff0c;为企业增长提供了全新的动力。在这一背景下&#xff0c;AI智能名片商城系统崭露头角&#xff0c;以其独特的优势&#xff0c;引领企业迈向第三增长极。 私域流量的兴起&#xff0c;为企业打开了一扇新的销…

竞赛 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉

文章目录 0 简介1 二维码检测2 算法实现流程3 特征提取4 特征分类5 后处理6 代码实现5 最后 0 简介 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于机器学习的二维码识别检测 - opencv 二维码 识别检测 机器视觉 该项目较为新颖&#xff0c;适合作为竞赛课…

迅为RK3568开发板瑞芯微人工智能AI鸿蒙Linux安卓开发学习

PU&#xff1a;iTOP-3568开发板采用瑞芯微RK3568处理器&#xff0c;内部集成了四核64位Cortex-A55处理器。主频高达2.0Ghz&#xff0c;RK809动态调频。集成了双核心架构GPU&#xff0c;ARM G52 2EE、支持OpenGL ES1.1/2.0/3.2、OpenCL2.0、Vulkan1.1、内嵌高性能2D加速硬件。 内…

Windows Server 评估版转换(升级)为完整版

临时方法 获取 Windows Server 的剩余宽限期 Slmgr /dliWindows Server免费试用期可以使用以下命令合法延长5次&#xff0c;共180天&#xff1a; slmgr /rearm这意味着所评估的 Windows Server 的最长可用时间为 3 年 ( 180 days * 6)。 试用期到期后&#xff0c;Windows S…

使用opencv改变图片大小

使用opencv改变图片大小 图片的宽度和高度效果代码 图片的宽度和高度 宽度&#xff1a;图片的宽度指的是图像从左边缘到右边缘的水平跨度。在数字图像中&#xff0c;宽度通常是以像素&#xff08;pixels&#xff09;为单位来度量的。高度&#xff1a;图片的高度指的是图像从上…

在远程服务器上安装anaconda以及配置pytorch虚拟环境

目录 第一步&#xff1a;官网或者清华源下载Anaconda。 第二步&#xff1a;创建虚拟环境。 第三步&#xff1a;在服务器终端输入nvidia-smi查看服务器信息。 第四步&#xff1a;在pytorch官网找到对应版本cuda的命令。 第一步&#xff1a;官网或者清华源下载Anaconda。 官网…

Hive 表定义主键约束

文章目录 1.建表语句2.主键约束3.主键约束的意义参考文献 1.建表语句 先看一下官方给的完整的见表语句&#xff1a; CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name -- (Note: TEMPORARY available in Hive 0.14.0 and later)[(col_name data…

谷歌浏览器查看http请求的请求标头和响应标头

http://t.weather.itboy.net/api/weather/city/101010100 记得刷新&#xff0c;才算请求了一次服务器 响应标头&#xff1a; HTTP/1.1 200 OK Content-Type: application/json; 请求标头&#xff1a; GET /api/weather/city/101010100 HTTP/1.1 Host: t.weather.itboy.n…

清新优雅、功能强大的后台管理模板 | 开源日报 No.238

soybeanjs/soybean-admin Stars: 7.0k License: MIT soybean-admin 是一个基于 Vue3、Vite5、TypeScript、Pinia、NaiveUI 和 UnoCSS 的清新优雅且功能强大的后台管理模板。 使用最新流行的技术栈&#xff0c;如 Vue3、Vite5 和 TypeScript。采用清晰的项目架构&#xff0c;易…

基于Spring Boot的体质测试数据分析及可视化系统设计与实现

基于Spring Boot的体质测试数据分析及可视化系统的设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 前台首页界面图&#xff0c;体质测试…

【酱浦菌-爬虫项目】python爬取彼岸桌面壁纸

首先&#xff0c;代码导入了两个库&#xff1a;requests和parsel。这些库用于处理HTTP请求和解析HTML内容。 然后&#xff0c;它定义了一个变量url&#xff0c;指向网站’樱花2024年4月日历风景桌面壁纸_高清2024年4月日历壁纸_彼岸桌面’。 接下来&#xff0c;设置了一个HTT…

头歌:Spark的安装与使用

第1关&#xff1a;Scala语言开发环境的部署 相关知识 Scala是一种函数式面向对象语言&#xff0c;它融汇了许多前所未有的特性&#xff0c;而同时又运行于JVM之上。随着开发者对Scala的兴趣日增&#xff0c;以及越来越多的工具支持&#xff0c;无疑Scala语言将成为你手上一件…

Django框架之ORM操作

一、选择数据库 1、默认数据库 Django默认的数据库是sqlite3数据库 DATABASES {default: {ENGINE: django.db.backends.sqlite3,NAME: BASE_DIR / db.sqlite3,} }2、指定数据库 修改连接到MySQL数据库 DATABASES {default: {ENGINE: django.db.backends.mysql,# 数据库名…

微信小程序 request 配置了服务器域名后 发布体验版无法访问

问题描述 在微信小程序公众平台配置了测试服务器域名后&#xff0c;发布了体验版进行测试&#xff0c;发现网络请求不通&#xff0c;打开调试也依然无法访问。 解决步骤&#xff1a; 1.首先根据小程序文档网络模块的使用说明&#xff0c;一步步排查域名证书是否符合规范&…

我用suno做了人生中第一首歌

前几周AI已经杀入音乐制作领域&#xff0c;Suno正式发布V3音乐生成模型&#xff0c;被业界誉为AI音乐的"ChatGPT"时刻。 借此机会&#xff0c;我也生成了人生中第一首歌&#xff0c;下面是歌词和对应的音频。 歌词&#xff1a; [Verse] 烽火连天万里霜 英雄豪杰赴…