OC---IOS开发入门学习(一)

什么是objactive-c

​ objactice-c简称obj-c或者OC。是基于 C 语言的、面向对象的编程语言。他将C语言中复杂繁琐的语法封装的更为简单。代码源文件通常以 .m 扩展名命名(c/c++为.c/.cpp)。m为message代表OC中的消息机制

用于开发 iOS 和 macOS 应用程序。OC完全兼容C语言。

OC基础语法

从Hello World中理解最基本的语法

/*
#import预处理指令:
	1.以#开头是一个预处理指令,作用可以将文件内容在预编译时拷贝到写指令的地方。
	
	2.是#include指令的增强版。相比于#include,他在包含文件时可以判断文件是否已经包含在程序中。
	  并且同一个文件无论#import多少次都只包含一次。#includ如果想实现这个效果需要配合条件编译指令
Foundation框架:
	1.框架是一个功能集合。苹果或者第三方把一些开发时常用的一些功能提前写好。并封装在类或函数中。这
	  些类或函数的集合叫做框架。类似C的函数库
	2.Foundation框架包含了最最基础的一些功能,包括输入、输出、数据类型等等。Foundation.h文件包含
	  了Foundation框架中的其他所有的头文件。只要引入它那么框架中的所有函数和类就都可以使用
*/
#import <Foundation/Foundation.h>

//main函数仍然是程序的入口,仍然有int类型的返回值,代表程序的结束状态。
int main(int argc,const char * argv[]){//参数可以接收用户在运行程序时传递数据给程序,可以省略不写
    @autoreleasepool{
        /*
        	NSlog函数是printf函数的增强版,类似cout。作用是向控制台输出信息
        	
        	语法:NSlog(@"格式控制字符串",【变量列表】);
        	增强:
        		1.会向控制台输出一些调试内容,格式如下
        			年 月 日 时间 项目名 【进程号:线程号】 输出的内容
        		2.会自动换行。如果末尾加\n 会失效
        		3.OC中其实新增了一些数据类型,NSlog函数不仅可以输出C数据类型变
        		  量的值还可以输出OC新增数据类型变量的值
        */
        NSlog(@"hello! World");
    }
    return 0;//0代表正常结束
}

OC程序编译过程

  1. 编译

    cc -c file.m -framework Foundation
    
    • -c 表示编译
    • file.m表示目标文件,可以列举多个,也可以用通配符表示 *.m
    • -framework 之后列举所用到的标准库

    这期间编译器帮我们做了很多事情,包括预处理、检查语法、汇编

  2. 链接

    编译执行之后会在当前目录生成 file.o文件。编译只是将我们自己写的代码变成了二进制形式,它还需要和系统组件(比如标准库、动态链接库等)结合起来,这些组件都是程序运行所必须的。链接就是一个“打包”的过程,它将所有二进制形式的目标文件(.o)和系统组件组合成一个可执行文件。

    cc  file.o -framework Foundation
    

    ​ 运行以上命令,链接程序,会生成a.out可执行文件,也可以用 -o 参数指定输出文件名

  3. 运行可执行文件

    ./a.out 
    
  4. 也可以直接将编译和链接二合一,以下命令直接生成.out文件

    cc file.m -framework Foundation
    

数据类型

在 Objective-C 中,基本数据类型与 C 语言类似。以下是一些常见的 Objective-C 基本数据类型:

  1. 整数类型:
    • NSInteger:带符号的整数,根据平台的不同可能为 32 位或 64 位。
    • NSUInteger:无符号的整数,根据平台的不同可能为 32 位或 64 位。
    • int:带符号的整数,默认为 32 位。
    • unsigned int:无符号的整数,默认为 32 位。
    • short:短整数,16 位。
    • long:长整数,通常为 32 位,根据平台的不同可能为 32 位或 64 位。
    • long long:长长整数,64 位。
  2. 浮点数类型:
    • CGFloat:浮点数,根据平台的不同可能为 float 或 double 类型。
    • float:单精度浮点数,32 位。
    • double:双精度浮点数,64 位。
  3. 字符类型:
    • char:字符类型,8 位。
    • unsigned char:无符号字符类型,8 位。
    • BOOL:布尔类型,只能取 YES 或 NO,实际上是 typedef 为 signed char。
  4. 其他类型:
    • void:空类型,用于表示无返回值或不带参数的函数。
    • id:泛型指针类型,可以用于指向任意类型的对象。
    • nil: 与null差不多
    • SEL: 方法选择器
    • 自定义数据类型:
      • 自定义类:通过继承NSObject类来创建自己的类。
      • 枚举:定义一组命名的整数常量。
      • 结构体:定义包含多个变量的复合数据类型。

这些基本数据类型在 Objective-C 中被广泛使用,可以用于声明变量、方法的参数和返回值等。

typedef

在 OC 中,typedef 是一种用于创建类型别名的关键字。通过 typedef 可以为现有的数据类型定义一个新的名称,使代码更加易读和可维护。

typedef 的语法示例:

typedef 现有类型名 新的名;

其中,existingType 是已存在的数据类型,newTypeName 是为该数据类型定义的新名称。

以下是一些使用 typedef 的常见示例:

  1. 为基本数据类型定义别名:
typedef int MyInteger;
MyInteger num = 10;

在这个示例中,MyInteger 被定义为 int 的别名,所以可以使用 MyInteger 来声明变量。

  1. 为结构体定义别名:
typedef struct {
    int x;
    int y;
} Point;

Point origin;
origin.x = 0;
origin.y = 0;

在这个示例中,Point 被定义为一个结构体 struct 的别名,使用 Point 来定义结构体变量更方便。

  1. 为指针类型定义别名:
typedef NSString *MyString;
NSString *str1 = @"Hello";
MyString str2 = @"Hello"; // 不用加*了

在这个示例中,MyString 被定义为 NSString 指针类型的别名,所以可以使用 MyString 来声明指向 NSString 对象的指针变量。

通过使用 typedef,我们可以简化代码,并且使代码更具可读性。

注意,typedef 只会创建类型别名,而不会创建新的数据类型。

NSString

​ C语言的字符串存储方式是用字符数组存储,而OC设计了一个更加好用的用来存储字符串的类型——NSString。NSString类型的指针变量是专门用来存储OC字符串。

使用OC字符串使用时要加@符号作为前缀,类似:@“Yujq”

​ 用 %@ 做占位符:

#import <Foundation/Foundation.h>

int main(int argc,const char * argv[]){
    @autoreleasepool{
       	NSString *str = @"Yujq";
        NSlog(@"hello! %@",str);
    }
    return 0;
}

关于NS前缀和@符:

​ NS: NextStop —> Cocoa —> Foundation框架之中

​ @: 作用一可以把C字符串转为OC字符串,二是OC中大部分关键字都是以@开头,如 @autoreleasepool

OC多文件开发

与C++类似通常把一个类写在一个模块中,而一个模块包含两个文件分别是:

  • .h: 头文件 ,写类的声明。要引入所需框架,如Foundation框架等
  • .m: 源文件,写类的实现。要引入对应头文件
//Person.h--头文件

#import <Foundation/Foundation.h>
@inteface Person:NSObject
{
    @public
	NSString *_name;
    int _age;
}
- (void)jump;
@end
    
____________________________________________________________________________________________________
//Person.m--源文件

#import "Person.h"
@implementation 类名
- (void)jump{
    NSLog(@"%@跳了一下",this->_name);
}
@end

____________________________________________________________________________________________________
//main
    
#import <Foundation/Foundation.h>
#import "Person.h" //使用时要引入模块的头文件
int main(int argc,const char * argv[]){
    @autoreleasepool{
       	Person *p1 = [Person new];
        [p1 jump];
    }
    return 0;
}

注意:一个Target中无法访问另一个Target中的类

类与对象

类的定义

类的定义写在源文件中,主要分为两个部分

1.类的声明

@inteface 类名 :父类名 // NSObject是根类
{
    //属性写这里
}
/*方法声明写这里
    方法声明语法:
        无参数:
            - (返回值类型)方法名;
        单参数
            - (返回值名称)方法名:(参数类型)参数名;
        多参数
            - (返回值名称)方法名:(参数1类型)参数1名 :(参数2类型)参数2名 :以此类推...;
*/
@end

2.类的实现

@implementation 类名
/*方法实现写这里
    方法实现语法:
        无参数:
            - (返回值类型)方法名
            {
                这里是方法实现;
            }
        单参数:
            - (返回值名称)方法名:(参数类型)参数名
            {
                这里是方法实现;
            }
        多参数
            - (返回值名称)方法名:(参数1类型)参数1名 :(参数2类型)参数2名 :以此类推...
            {
                这里是方法实现;
            }
*/
@end

示例

@inteface Person:NSObject
{
    @public
	NSString *_name;
    int _age;
}
- (void)jump;
@end
    
@implementation Person
- (void)jump{
    NSLog(@"%@跳了一下",this->_name);
}
@end

注意:

  1. 类的声明和实现必须对应存在,方法实现中可以直接访问属性
  2. 类名为大驼峰命名
  3. 属性命名规范是以下划线开头
对象的创建和使用

对象本质是结构体

创建语法: 类名 *对象名 = [类名 new];

Person *p1 = [Person new];

对象属性的访问

1、默认情况下对象的属性是不允许外届访问的。如果允许被访问则需要在声明属性时在前面加上@public关键字

2、访问方式:

​ 访问 :对象名->属性名 || (*对象名).属性名 (会调getter/setter)

p1 -> _name;
(*p1)._name;

​ 赋值 :对象名 -> 属性名 = 值;

p1 -> _name = @"zhangsan";

方法调用

与JAVA相同根据对象进行方法调用。调用语法:

  • 无参数:[对象名 方法名];
  • 单参数:[对象名 方法名:实参]
  • 多个参数:[对象名 方法名:实参1 :实参2 :实参3 : ......]

带参数的方法命名规范:

  • 如果方法只有一个参数,方法名最好如下命名 xxxWith:

    这样写的好处是当调用时语句的可读性更高,如 [p1 eatWith:@“锅包肉”]

  • 多个参数时命名如下: 方法名:(参数1类型)参数1名 and:(参数2类型)参数2名 and:…;

    如 - (int)sumWith:(int)num1 and:(int)num2 and:(int)num3;

    调用时如下 [p1 sumWith:10 and:20 and:30]可读性更高

创建对象时内存处理过程

在创建对象时Person *p1 = [Person new];会经历如下过程

  1. 检测类是否被加载,如果是第一次访问类,会将类以Class类型对象存储到内存的代码段区。一旦被类加载就只会在程序结束时回收
  2. Person *p1会在栈内存开辟空间,存储Person类型的指针变量。
  3. [Person new]会在堆内存中申请空间,根据代码区的类模版创建对象,并为对象添加一个额外的isa属性,它是个指针,指向对象所属类在代码段中的地址,之后初始化对象属性。最终返回对象地址。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lBFoB34I-1689467494623)(7月份学习笔记.assets/image-20230708080803675.png)]

注意:堆内存中的对象没有方法只有属性,调用方法时根据ISA指针调用代码段类中的方法。

对象属性的默认值:

基本数据类型—>0 C指针类型—>NULL OC指针类型-—>nil

nil和NULL

都只能作为指针变量的值,并且都代表这一指针不指向任何一块空间。等价与0C/OC指针分别用NULL/nil

分组导航标记

作用是当单文件代码过多,函数不好查找时,通过 #pragma mark 关键字来进行函数或者类的标记。方便查找。关键字后可接 或注释

  • : 在导航栏对应位置生成分割线
  • ​ 注释 :在对应位置生成标题

示例如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-72Zv0vT4-1689467494624)(7月份学习笔记.assets/image-20230708094900479.jpg)]

访问修饰符

修饰属性(不能修饰方法),限定属性访问作用域

   @private   私有     只能在本类方法实现中访问
   @protected 受保护的  只能在本类方法,子类方法实现中访问
   @package   框架     被修饰的属性,可以在当前框架中访问
   @public    公共的   只要创建对象,可以在任意的地方访问
   不写默认: @protected

注意: 子类仍然可以继承父类的私有属性,只不过,在子类中无法直接访问从父类继承过来的私有属性,
如果父类中有一个方法为属性赋值或取值,那么子类可以调用这个方法间接的访问父类的私有属性.

访问修饰符的作用域:直接遇到另一个访问修饰符或结束大括弧为止,都是最近的修饰符. 如:

@private
	 NSString *_name;
@public
	 int _age;
	 int weight;       //也是@public

私有属性/方法

在类声明中给属性添加@private确实外界无法访问,但是xcode还是会有这个属性的提示,如果不想让外界提示这个属性。可以在声明中添加一个大括号,写在其中,如下:

@implementation 类名
{
    /*
    	写在这里的属性,访问修饰符无效、外界不会有提示。并且固定为私有属性。
    */
}
@end

同理。如果想定义私有方法,只需要不写方法声明,只写方法实现。这样外界就不会提示。

多态

左父右子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r57UAvAZ-1689467494625)(7月份学习笔记.assets/image-20230712201633139.png)]

类方法

静态方法。调用不依赖对象,使用类名即可 定义语法与对象方法相同。区别是 - 换成 +。如下:

//定义
/*
	如果这个方法不需要访问属性也不需要调用其他对象方法时,可以将这个方法声明成类方法。
*/
+ (void)sh;
//声明
+ (void)sh
{

}
//调用  只能由类(名)来调用!!
[类名 类方法名]

特点

  • 节约空间,不用创建对象

  • 高效,不用通用对象isa找到方法,直接调用

  • 类方法中不能直接访问属性或对象方法。因为属性只有在创建时创建在对象之中。但是可以在类方法中创建一个对象访问属性

    #import <Foundation/Foundation.h>
    #pragma mark - Preson class
    @interface Person : NSObject
    {
        NSString *_name;
        int _age;
    }
    + (void)run;
    - (void)jump;
    @end
    
    @implementation Person
    //类方法中创建对象访问对象方法
    + (void)run{
        Person *p1 = [Person new];
        [p1 jump];
    }
    - (void)jump
    {
        NSLog(@"fu lei lei fang fa ");
    }
    @end
    #pragma mark - main
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            [Person run];
            NSLog(@"Hello, Mac!");
        }
    }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M6W2YFnO-1689467494625)(7月份学习笔记.assets/image-20230712104402979.png)]

  • 对象方法中可以直接调用类方法

类方法规范
  1. 如果定义了一个类,就需要定义一个和类名同名的类方法。这个方法创建一个最纯洁的对象返回

    #import <Foundation/Foundation.h>
    @inteface Person:NSObject
    {
        @public
    	NSString *_name;
        int _age;
    }
    + (Person *)preson;
    
    @end
    //类方法实现
    @implementation Person
    + (Person *)preson
    {
        Person *p1 = [Preson preson];
        return p1;//最纯洁
    }
    @end 
    
  2. 如果希望创建的对象的属性由调用者指定。那么就为这个类方法带参数。类名WithXxx:

    #import <Foundation/Foundation.h>
    @inteface Person:NSObject
    {
        @public
    	NSString *_name;
        int _age;
    }
    + (Person *)preson;
    + (Preson *)presonWithName:(NSString *)name andAge:(int)age;
    @end
    //类方法实现
    @implementation Person
    + (Person *)preson
    {
        Person *p1 = [Preson preson];
        return p1;//最纯洁
    }
    + (Preson *)presonWithName:(NSString *)name andAge:(int)age
    {
        Person *p1 = [Preson preson];
        p1 ->_name = name;
        p1 ->_age = age;
        return p1;//自定义值
    }
    @end 
    
构造方法(init)

new实际上是一个类方法,返回对象地址。new内部会先调用alloc方法,在调用init方法(先创建在初始化)

​ alloc方法也是一个类方法,会创建调用他的类的对象,并经对象返回。

​ init是一个对象方法,默认作用是初始化对象,也叫构造方法

所以创建对象也可以如以下写法:

Person *p1 = [[Person alloc] init]; // 与 Person *p1 = [Person new]; 等价
description方法

类似Java中的toString()方法。description方法定义在NSObject中。所以每一个oc对象都有这个方法

它会返回一个NSStrign字符串。用于对象的描述信息。默认格式是:@“<对象所属类名:对象地址>”

当用NSLog函数使用%@打印一个对象时,NSLog底层会默认调用这个对象的description方法

封装(getter/setter)

/*
setter设置属性值:
    1、去掉@public,不让外界访问属性
    2、提供一个对象方法为属性赋值,没有返回值。名必须以set开头,后接去掉下划线首字母大写的属性名如:- (void)setXxx.
       方法参数名和去掉下划线属性名一致
getter访问属性值:
	1、提供一个对象方法访问属性值,方法返回值类型和属性类型一致,没有参数。方法名直接就是去掉下划线
       的属性名如:- (NSString *)name;
       
*/
#import <Foundation/Foundation.h>
@inteface Person:NSObject
{
	NSString *_name;
    int _age;
}
//getter/setter声明
- (void)setName:(NSString *)name;
- (NSString *)name;

@end
    
@implementation Person
//getter/setter实现
- (void)setName:(NSString *)name
{
    _name = name;
}
- (NSString *)name
{
    return _name;
}
@end 

static关键字

​ 在 Objective-C 中,静态成员变量和静态成员函数的用法与 C++ 并不相同

OC中的static关键字不能修饰成员属性和方法。主要有两种常见的用法:

  1. 静态局部变量: 在函数或方法中使用 static 关键字声明的变量称为静态局部变量。与 C 和 C++ 中的用法相同,静态局部变量在程序的生命周期内只初始化一次,并且在函数或方法调用结束后不会销毁。

    void myFunction() {
        static int count = 0;  // 静态局部变量,只初始化一次
        count++;
        NSLog(@"Count: %d", count);
    }
    
    // 调用函数多次
    myFunction();  // 输出:Count: 1
    myFunction();  // 输出:Count: 2
    
  2. 静态全局变量: 在 Objective-C 中,可以使用 static 关键字声明全局变量,将其作用域限制在当前文件中。这意味着该变量对其他文件是不可见的。

    // MyFile.m 文件
    static NSString *const kMyConstant = @"Hello";  // 静态全局变量,只在当前文件可见
    
    // AnotherFile.m 文件
    NSLog(@"%@", kMyConstant);  // 错误,kMyConstant 在当前文件不可见
    

​ 静态局部变量和静态全局变量可以在需要时保留变量的状态限制其作用域。

self关键字

​ 与this类似,是一个指针,在对象方法中指向当前对象,在类方法中指向当前类

对象方法中

​ 可以访问对象属性和方法,self -> xxxself. xxx

//访问对象的属性:
/*
	注意:在方法中调用属性,如果不存在局部变量与属性同名情况。可以不用self。默认就是访问成员属性
		 一般按照属性以下划线开头,局部变量不以下划线开头这个规范,不会重名
		 
		 对象方法中不能使用self调用类方法,因为self是指向对象,oc不能使用对象调用类方法
*/
@implementation MyClass
- (void)printName {
    NSLog(@"%@", self.name);  // 使用 self 访问对象的属性
}
@end
    
//访问对象方法:  
@interface MyClass : NSObject
- (void)myMethod;
@end

@implementation MyClass
- (void)myMethod {
    NSLog(@"Calling myMethod");
}

- (void)anotherMethod {
    [self myMethod];  // 使用 self 调用对象的方法
}
@end

点语法

在 OC 中,self.self-> 都是用于访问当前对象的成员变量或属性的方式。

  1. self.:使用点语法来访问对象的属性。点语法是 Objective-C 提供的一种简化访问属性和调用方法的语法糖。它能够让代码更加简洁易读。通过 self. 可以访问当前对象的属性,编译器会自动调用对应的 getter 或 setter 方法。

    对象名.去掉下划线的属性名
    // 访问属性
    self.name = @"John";  // 设置 name 属性的值 相当于[self setName:@"John"]
    NSString *currentName = self.name;  // 获取 name 属性的值
    
    // 调用方法
    [self doSomething];  // 调用 doSomething 方法
    
  2. self->:通过指针访问对象的实例变量(成员变量)。在 OC 中,实例变量通常被封装在属性中,外部无法直接访问。但通过使用 self->,可以直接访问实例变量。需要注意的是,这种方式绕过了属性的 getter 和 setter 方法,直接访问实例变量可能会导致细微的问题,所以在正常情况下应该使用 self. 访问属性。

    // 访问实例变量
    self->age = 25;  // 直接设置 age 实例变量的值
    int currentAge = self->age;  // 直接获取 age 实例变量的值
    

注意: 在一般情况下,推荐使用 点语法来访问对象的属性,以保持封装性和代码的可维护性。

​ 但是getter/setter中慎用点语法。容易造成递归程序崩溃

​ 点语法在编译时会转换为getter/setter方法代码。如果getter/setter方法的方法名不符合规范。那么点语法也会出问题

​ 如果属性为封装。则无法使用点语法

类方法中:

//使用self显示调用本类的其他类方法
/*
	1.虽然可以直接使用类名,但建议使用self
	
	2.类方法中不能使用self调用对象的属性和方法。只能调用类方法
	
*/

继承

子类继承父类相当于拥有父类的所有成员(属性,对象方法,类方法)

//继承语法:

@interface 类名 : 父类名
@end
    
//示例
#import <Foundation/Foundation.h>
#pragma mark - Preson class
@interface Person : NSObject
{
    NSString *_name;
    int _age;
}
+ (void)run;
- (void)jump;
@end

@implementation Person

+ (void)run{
    Person *p1 = [Person new];
    [p1 jump];
}
- (void)jump
{
    NSLog(@"fu lei lei fang fa ");
}
@end
@interface Chinese : Person
{
   
}
- (void)jump;
@end

@implementation Chinese
- (void)jump
{
    
}

OC继承特点:

  • 单根性:一个类只能有一个父类(c++支持多继承)
  • 传递性:比如a继承b、b继承c。那么a同时拥有b和c的所有成员

注意:子类中不能有跟父类同名的属性,否则冲突 (Java和C++中可以)

​ 类方法也会被子类继承

NSObject

​ 是Foundation框架中的类,它是所有OC类的基类。NSObject定义了一些基本的行为和方法,使得其他类可以继承和使用这些通用的功能。就是这个类提供new方法,还包括像 init/dealloc对象初始化和销毁、对象比较isEqual、哈希值计算hash、类信息**class**等。和JAVA中Object类似。

super关键字

在 Objective-C 中,可以通过使用 super 关键字来引用当前对象的基类。它常用于重写方法时调用级基类的实现

  • 在子类的类方法或对象方法中使用
  • 如果super处在对象方法中,那么就会调用父类的对象方法,此时不能通过super调用父类类方法,要调用父类的类方法,仍然需要使用类名来调用
  • 如果super是处在类方法中的,那么就会调用父类的类方法;此时不能通过super调用父类对象方法
    • 类方法会被继承,父类中的类方法可以使用父类名调,也可以使用字类名调
  • super只能用来调用父类的类方法或对象方法,不能调用属性
子类对象方法调用过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5WSbqoFo-1689467494626)(7月份学习笔记.assets/image-20230714081348427.png)]

Class对象

​ 在代码段存储类的那块空间是Class类型。Class是Foundation框架中的一个类,这个Class对象不仅能存储类的类名、属性、方法。还有一个isa属性。用来指向存储父类的Class对象

//如下,调用类的类方法Class就可以拿到存储类的类对象地址
Class c1 = [Person class];//typedef指针类型。不用加*。这时c1就是Person,可以使用它调用类方法

//调用对象的对象方法Class就可以得到这个对象所属类的Class对象地址
Person p1  = [Person new];
Class c2 = [p1 class];

这个特性可以用来动态创建不同的类对象。

SEL

SEL全称叫做selector选择器。SEL对象是用来存储方法的。在代码段中类是以Class对象类型存储的。而类中的方法就是以SEL对象类型存储在Class对象中。

//如下,可以拿到对应方法名的SEL对象
SEL s1 = @selector(方法名);//因为SEL是typedef类型,在自定义时已经确定为指针类型。所以这里定义就不用加*号

调用方法的本质:

  1. 在执行[p1 sayhi]时,首先底层会通过@selector(sayhi)拿到方法的SEL对象。
  2. 然后将这个对象发送给 p1 对象。
  3. p1 对象接收到SEL消息时,会根据ISA指针找到存储类的Class对象。
  4. 查找这个类是否有与传入的SEL相匹配的方法。如果有就执行。没有就找父类。直到NSObject为止

重写

oc中重写方法只要在子类实现中,将方法重新实现一次就行。

//示例
#import <Foundation/Foundation.h>
#pragma mark - Preson class
@interface Person : NSObject
+ (void)sayhi;
@end

@implementation Person
- (void)sayhi
{
    NSLog(@"hello");
}
@end
    
@interface Chinese : Person

@end

@implementation Chinese
- (void)sayhi
{
    NSLog(@"你好");
}
@end

oc多态,编译看左运行看右仍然适用

异常处理

语法:

@try
{
    
}
@catch(NSException *exc)
{
    
}
@finally
{
    //无论@try里面是否发生异常都会执行
}

oc中的try…catch不是万能的有些错误无法处理。C语言中的异常根本无法处理,如除数不为0。所以开发中很少使用,多数使用if判断

@property

用于声明类的属性。一种简化代码的方式

Xcode4.x 之前:只能生成getter/setter方法的声明,实现要靠@synthesize生成语法如下:

@interface MyClass : NSObject {
    NSString *_age; // 显式定义实例变量
}

@property NSString *age; // 使用 @property 声明属性,属性名称为 name

@end

@implementation Person
@synthesize age = _age;//表示age是存取起名称,_age是具体的私有变量,这样不会自动生成私有属性
@end

Xcode4.x 之后:@property可以同时生成setter和getter的声明和实现自动合成属性的实例变量。示例语法:

/*
	默认情况下,setter和getter方法中的实现,会去访问下划线 _ 开头的成员变量 如果没有会自动生成一个_开头的成员变量,自动生成的成员变量是私有变量, 声明在.m中,在其它文件中无法查看,只可以在本类中查看
*/

@interface MyClass : NSObject

@property (nonatomic, strong) NSString *name;

@end

​ 以上代码中,使用 @property 声明了一个名为 name 的属性。编译器会自动合成一个名为 _name 的私有属性,并生成对应的 Getter 和 Setter 方法。

合成的实例变量是根据属性的名称自动生成的,前面有一个下划线作为前缀。因此,你可以通过 _name 直接访问或修改这个合成的实例变量(self->_name),也可以使用点语法来调用自动生成的 Getter 和 Setter 方法(self.name)。

readonly和readwrite

readonly和readwrite是@property修饰符,用于指定属性的可读性。

readonly:用于声明只读属性。只读属性只生成getter方法,不生成setter方法。这意味着该属性只能被读取,不能被修改。

示例代码如下:

@property (nonatomic, readonly) NSString *name;

上述代码声明了一个名为name的只读属性。

readwrite:用于声明可读写属性。可读写属性会同时生成getter和setter方法,允许读取和修改属性的值。

示例代码如下:

@property (nonatomic, readwrite) NSInteger age;

@synthesize

Xcode4.x 之前,如果你没有手动实现 setter 方法和 getter 方法,需要使用@synthesize生成 setter 和 getter 方法。

//语法 @synthesize @property对应的属性名(会生成一个不带下划线的属性)
@implementation Person
@synthesize age = _age;//表示age是存取起名称,_age是具体的私有变量,这样不会自动生成私有属性
@end

Xcode4.x之后,@property使用“自动合成”( autosynthesis)生成ivar、getter、setter并添加到类中。

ios项目文件结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BFXr9Rs6-1689467494626)(7月份学习笔记.assets/image-20230715170444266.png)]

  1. AppDelegate.h 和 AppDelegate.m:应用程序的入口,定义应用程序的生命周期方法。
  2. Assets.xcassets:资源文件夹,用于存放应用程序所需的图片、图标等资源文件。
  3. LaunchScreen.storyboard是用于定义应用程序启动界面的布局文件。在这个文件中,你可以设置应用程序启动时显示的界面,例如加载动画、应用程序的logo等。
  4. Main.storyboard是用于定义应用程序的主界面布局的文件。在这个文件中,你可以创建应用程序的用户界面、视图控制器之间的关系以及导航流程。
  5. ViewController.h 和 ViewController.m:视图控制器文件,用于管理界面的逻辑和显示。
  6. SceneDelegate.h和SceneDelegate.m是在iOS 13及以上版本中引入的新文件,用于管理应用程序的窗口和场景生命周期。
第一个ios APP

注意,项目名不能以数字开头。不能包含中文

项目配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lhxZjAof-1689467494626)(7月份学习笔记.assets/image-20230715181812374.png)]

关联控件

在storyboard中按住ctrl点击一个控件,拖拽到辅助编辑器中的控制器类的扩展块中,可自动生成并关联此控件的监听事件或者属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qWhQw3CF-1689467494627)(7月份学习笔记.assets/image-20230715175356739.png)]

IBAction 和 IBOutlet

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lb9WmKZI-1689467494627)(7月份学习笔记.assets/image-20230715174151989.png)]

IBActionIBOutlet 是 iOS 开发中用于连接用户界面和代码的关键词。

IBAction

IBAction 是 Interface Builder Action 的缩写,是一种在 Xcode 中使用的关键字。它可用于将用户界面元素(如按钮、滑块等)的事件与代码中的方法进行绑定。

用法示例:

- (IBAction)sum:(id)sender;

上述代码表示创建了一个名为 buttonTapped: 的方法,该方法会在用户点击按钮时被调用。通过在 Interface Builder 中将按钮的 Touch Up Inside 事件与 buttonTapped: 方法进行关联,当用户点击按钮时,该方法会被触发执行。

IBOutlet

IBOutlet 是 Interface Builder Outlet 的缩写,同样是一种在 Xcode 中使用的关键字。它可用于将用户界面的组件与代码中的属性进行链接。

用法示例:

@property (nonatomic, weak) IBOutlet UILabel *textl;

上述代码表示创建了一个名为 nameLabel 的属性,它会与 Interface Builder 中的一个 UILabel 组件进行关联。通过在 Interface Builder 中选择并拖拽一个 UILabel 组件到代码中的 nameLabel 属性上,可以将该组件与属性进行绑定。

退出文本框键盘

方式一

​ 键盘是那个控件叫出来的那个控件就是第一响应者。收键盘的思路是:使当前文本框放弃第一响应者的身份

[self.tetNum1 resignFirstResponder];
[self.tetNum2 resignFirstResponder];

示例:用户按下文本框键盘上的 “Return” 或 “Done” 键可以主动退出键盘

/*
	前提是视图控制器类(YourViewController)已经遵循了 UITextFieldDelegate 协议。这意味着视图控制器类中需要实现与文本框相关 的代理方法。
	类似Android
*/
@interface YourViewController : UIViewController <UITextFieldDelegate> //前提

@property (nonatomic, weak) IBOutlet UITextField *yourTextField;

@end

@implementation YourViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.yourTextField.delegate = self;//将视图控制器设置为 yourTextField 的代理,可以在控制器里定义文本框的代理方法
}
// 实现 UITextFieldDelegate 的代理方法
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder]; // 退出键盘
    return YES;
}

@end

方式二

​ 每一个控制器都会管理一个View,self.view就表示当前控制器所管理的那个View,让控制器所管理的View停止编辑,就相当于把这个view中的所有子控件叫出的键盘都关闭。

//让控制器所管理的View停止编辑
[self.view endEditing:YES];

示例:点击屏幕其他区域,实现退出键盘的效果

/*
	在 viewDidLoad 方法中,创建了一个 UITapGestureRecognizer (手势识别器) 对象 tapGesture,
	并将其目标设置为当前视图控制器 self,动作设置为 dismissKeyboard 方法。
	然后,通过 [self.view addGestureRecognizer:tapGesture] 将手势识别器添加到视图控制器的视图上。
	当用户点击视图时,会触发 dismissKeyboard 方法,并通过 [self.view endEditing:YES] 退出键盘。
*/


@implementation YourViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建一个UITapGestureRecognizer对象并设置其目标和动作
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    
    // 将手势识别器添加到当前视图控制器的视图上
    [self.view addGestureRecognizer:tapGesture];
}

- (void)dismissKeyboard {
    [self.view endEditing:YES]; // 退出键盘
}

@end

UIKit

是 Apple 开发的用于构建 iOS 应用程序的框架。它是在 Cocoa 框架基础上针对移动设备进行优化的一部分,提供了丰富的用户界面组件和工具,用于创建直观、易用的应用程序界面。

UIKit 提供了许多预定义的视图(View)和控制器(Controller),以及处理事件、绘图、动画等方面的功能。

esponder]; // 退出键盘
return YES;
}

@end


**方式二**

​	每一个控制器都会管理一个View,self.view就表示当前控制器所管理的那个View,让控制器所管理的View停止编辑,就相当于把这个view中的所有子控件叫出的键盘都关闭。

```objective-c
//让控制器所管理的View停止编辑
[self.view endEditing:YES];

示例:点击屏幕其他区域,实现退出键盘的效果

/*
	在 viewDidLoad 方法中,创建了一个 UITapGestureRecognizer (手势识别器) 对象 tapGesture,
	并将其目标设置为当前视图控制器 self,动作设置为 dismissKeyboard 方法。
	然后,通过 [self.view addGestureRecognizer:tapGesture] 将手势识别器添加到视图控制器的视图上。
	当用户点击视图时,会触发 dismissKeyboard 方法,并通过 [self.view endEditing:YES] 退出键盘。
*/


@implementation YourViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建一个UITapGestureRecognizer对象并设置其目标和动作
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    
    // 将手势识别器添加到当前视图控制器的视图上
    [self.view addGestureRecognizer:tapGesture];
}

- (void)dismissKeyboard {
    [self.view endEditing:YES]; // 退出键盘
}

@end

UIKit

是 Apple 开发的用于构建 iOS 应用程序的框架。它是在 Cocoa 框架基础上针对移动设备进行优化的一部分,提供了丰富的用户界面组件和工具,用于创建直观、易用的应用程序界面。

UIKit 提供了许多预定义的视图(View)和控制器(Controller),以及处理事件、绘图、动画等方面的功能。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值