Browse Source

oc对象的分类;对象、类、和原来的关系

huangyirong 3 years ago
parent
commit
02224ede08

+ 284 - 0
Objc4_Study/Objc4_Study.xcodeproj/project.pbxproj

@@ -0,0 +1,284 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 50;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		40F628AF2476DB0900110F74 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 40F628AE2476DB0900110F74 /* main.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		40F628A92476DB0900110F74 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		40F628AB2476DB0900110F74 /* Objc4_Study */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Objc4_Study; sourceTree = BUILT_PRODUCTS_DIR; };
+		40F628AE2476DB0900110F74 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		40F628D3247C1E4000110F74 /* main-arm64.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "main-arm64.cpp"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		40F628A82476DB0900110F74 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		40F628A22476DB0900110F74 = {
+			isa = PBXGroup;
+			children = (
+				40F628AD2476DB0900110F74 /* Objc4_Study */,
+				40F628AC2476DB0900110F74 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		40F628AC2476DB0900110F74 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				40F628AB2476DB0900110F74 /* Objc4_Study */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		40F628AD2476DB0900110F74 /* Objc4_Study */ = {
+			isa = PBXGroup;
+			children = (
+				40F628AE2476DB0900110F74 /* main.m */,
+				40F628D3247C1E4000110F74 /* main-arm64.cpp */,
+			);
+			path = Objc4_Study;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		40F628AA2476DB0900110F74 /* Objc4_Study */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 40F628B22476DB0900110F74 /* Build configuration list for PBXNativeTarget "Objc4_Study" */;
+			buildPhases = (
+				40F628A72476DB0900110F74 /* Sources */,
+				40F628A82476DB0900110F74 /* Frameworks */,
+				40F628A92476DB0900110F74 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = Objc4_Study;
+			productName = Objc4_Study;
+			productReference = 40F628AB2476DB0900110F74 /* Objc4_Study */;
+			productType = "com.apple.product-type.tool";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		40F628A32476DB0900110F74 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 1130;
+				ORGANIZATIONNAME = Sogou;
+				TargetAttributes = {
+					40F628AA2476DB0900110F74 = {
+						CreatedOnToolsVersion = 11.3.1;
+					};
+				};
+			};
+			buildConfigurationList = 40F628A62476DB0900110F74 /* Build configuration list for PBXProject "Objc4_Study" */;
+			compatibilityVersion = "Xcode 9.3";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = 40F628A22476DB0900110F74;
+			productRefGroup = 40F628AC2476DB0900110F74 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				40F628AA2476DB0900110F74 /* Objc4_Study */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		40F628A72476DB0900110F74 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				40F628AF2476DB0900110F74 /* main.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		40F628B02476DB0900110F74 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.14;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		40F628B12476DB0900110F74 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.14;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				MTL_FAST_MATH = YES;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		40F628B32476DB0900110F74 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_STYLE = Automatic;
+				DEVELOPMENT_TEAM = ZQJ4SDDLY2;
+				ENABLE_HARDENED_RUNTIME = YES;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		40F628B42476DB0900110F74 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_STYLE = Automatic;
+				DEVELOPMENT_TEAM = ZQJ4SDDLY2;
+				ENABLE_HARDENED_RUNTIME = YES;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		40F628A62476DB0900110F74 /* Build configuration list for PBXProject "Objc4_Study" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				40F628B02476DB0900110F74 /* Debug */,
+				40F628B12476DB0900110F74 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		40F628B22476DB0900110F74 /* Build configuration list for PBXNativeTarget "Objc4_Study" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				40F628B32476DB0900110F74 /* Debug */,
+				40F628B42476DB0900110F74 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 40F628A32476DB0900110F74 /* Project object */;
+}

+ 7 - 0
Objc4_Study/Objc4_Study.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:Objc4_Study.xcodeproj">
+   </FileRef>
+</Workspace>

+ 8 - 0
Objc4_Study/Objc4_Study.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>

File diff suppressed because it is too large
+ 34728 - 0
Objc4_Study/Objc4_Study/main-arm64.cpp


+ 241 - 0
Objc4_Study/Objc4_Study/main.m

@@ -0,0 +1,241 @@
+//
+//  main.m
+//  Objc4_Study
+//
+//  Created by huangyirong on 2020/5/21.
+//  Copyright © 2020 Sogou. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <objc/runtime.h>
+
+///OC对象分类
+///instance对象、class对象、meta-class对象
+///
+///
+///实例对象
+///实例对象就是通过类alloc出来的对象,每次调用alloc都会产生新的实例对象,都会分配新的存储空间
+///实例对象在内存中存储的信息包括isa和其他成员变量
+///几乎所有实例对象都有isa,因为都是继承NSObject
+///
+///2、每一个实例对象都有isa,而且在该内存地址的最前面,也就是例如Student *stu = [[Student alloc] init]; 如果isa的地址是0x30020 所以stu指针存储的地址值也就是0x30020,指向这个Student实例对象
+///实例对象没有存储方法,为什么?不可能每个alloc出来的对象都需要一份方法列表太浪费存储在对应的class中
+///
+///
+///2、通过对一个实例对象内存结构的理解,有助于研究其他问题,如分析一个对象分配多少内存
+///
+///class_getInstanceSize()
+/// 传入一个类,返回这个类最终创建出来的实例至少需要多少存储空间
+///class_getInstanceSize([Student class])
+///
+///
+///malloc_size() 传入指针,返回指针所指向内存大小,其实也是实际分配的大小,存在内存对齐问题,iOS系统中buket size,分成好多段,16、32,128字节等等 nano size什么的
+///malloc_size((__bridge const void *)(stu))
+///
+///
+///sizeof() 实际上是运算符(不是函数),传的是类型,比如int、float、struct或者指针,返回这个类型有多大,一编译就转成常数,类似宏,sizeof(double) ,转成汇编看实际上就是常数8,sizeof(stu) stu是指针变量则为8个字节,sizeof(struct)也为8
+///
+///
+///笔记-其他注意点
+///alloc 调用
+///_objc_rootAllocWithZone
+///class_createInstance
+///calloc
+///alignxxxx
+///
+///
+
+///
+///meta-class元类对象
+///meta-class可以理解成用来描述类的
+///
+
+struct NSObjct_IMPL {
+    Class isa;
+};
+
+struct Person_IMPL {
+    struct NSObjct_IMPL NSObjct_IVARS;
+    NSString *name;
+    int age;
+};
+
+struct Student_IMPL {
+    struct Person_IMPL NSObjct_IVARS;
+    NSString *name;
+    int age;
+    int number;
+};
+
+@interface Person : NSObject
+{
+    NSString *name;
+    int age;
+}
+- (void)say;
++ (void)fuxx;
+
+@end
+
+@implementation Person
+
+- (void)say
+{
+    
+}
++ (void)fuxx
+{
+    
+}
+
+@end
+
+@interface Student : Person
+{
+    int number;
+}
+- (void)study;
+@end
+
+@implementation Student
+- (void)study
+{
+    
+}
+
+@end
+
+int main(int argc, const char * argv[]) {
+    @autoreleasepool {
+        // insert code here...
+//        NSLog(@"Hello, World!");
+        
+        ///类对象示例代码
+        Student *stu = [[Student alloc] init];
+        ///类对象获取方式
+        Class objClass1 = [stu class];
+        Class objClass2 = [Student class];
+        Class objClass3 = object_getClass(stu);
+//        NSLog(@"1:%p 2:%p 3:%p",objClass1,objClass2,objClass3);
+        [stu study];
+   ///类对象 ///每个类再内存中有且只有一个class对象,因此objClass1、objClass2和objClass3指向的地址都是一样
+        ///类对象再内存中存储的信息主要包括
+        ///isa指针
+        ///superclass指针
+        ///类的属性信息(@property)、类的对象方法信息(instance method)
+        ///类的协议信息(protocl)、类的成员变量信息(ivar)
+        ///
+        ///注意,类对象包含的成员变量信息并非比如Person的成员变量name的值是多少
+      ///成员变量的值是由实例对象决定的,这里类对象的成员变量信息主要是这个变量的名称、类型等描述信息,只需要存储一份,不管对于哪个实例对象这些信息都是固定不变
+        ///
+        ///
+        ///获取元类对象
+        Class objectMetaClass = object_getClass([Student class]);
+        ///object_getClass传入的是类对象,获得元类对象
+        ///
+        Class objectMetaClass2 = [objClass2 class];
+        ///objectMetaClass2返回的也是元类对象吗?
+        ///可以通过以下runtime api判断
+        class_isMetaClass(objectMetaClass2);
+        ///不是。。试了下类对象无论调用多少次class方法始终返回类对象
+        ///
+        ///每个类在内存有且只有一个meta-class对象
+        ///meta-class对象和class对象的内存结构是一样的(类对象和元类对象指针类型都是Class,所以指向内存的结构一样),但是用途不同,
+        ///在内存中存储的主要信息包括
+        ///isa指针
+        ///superclass指针
+        ///class method类的类方法信息
+        ///
+        ///比起class对象包含的东西好像少了,内存结构还能一样?
+        ///meta-class中那些属性信息、协议信息等等都为null
+        ///两者类型一样指向的都是typedef struct objc_class *Class结构体
+        ///
+      
+        ///
+        ///思考
+        ///1、对象的isa指针指向哪里?
+        ///
+        ///instance的isa指向class
+        ///class的isa指向meta-class
+        ///meta-class的isa指向基类的meta-class
+        ///
+        ///
+        ///2、OC的类信息存在哪里?
+        ///
+        ///
+        ///
+        ///
+        ///3、object_getClass() vs objc_getClass(),内部实现
+        ///
+        ///Class objc_getClass(const char *aClassName) (源码在objc-runtime.mm里)
+        ///传入字符串类名,返回对应的类对象
+        ///
+        ///Class object_getClass(id obj) (编码在objc-class.mm里)
+        ///传入的obj可能是instance对象(返回class对象)
+        ///class对象(返回meta-class对象)
+        ///meta-class对象(返回NSObjectd meta-class对象)
+        ///
+        ///-(Class)class; 返回类对象
+        ///
+        ///
+        ///xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
+        ///-framework链接上其他框架 如 -framework UIKit
+        ///
+        ///搜 int main(int argc, const char * argv[])
+        ///
+        ///[stu study];
+        ///
+        ///objc_msgSend(stu,@selector(study))
+        ///stu对象发送一条消息@selector(study)
+        ///stu需要先找到实例方法才能调用成功,怎么找到?
+        ///通过isa找到对应类对象,再找到实例方法
+        ///同样道理,类对象调用类方法,也是类对象通过isa找到元类对象中的类方法实现
+        ///
+        ///总结下
+        ///instance的isa指向class,当调用对象方法时,通过instance的isa找到class
+        ///最后找到对象方法的实现进行调用
+        ///class的isa指向meta-class,当调用类方法时,通过class的isa找到meta-class
+        ///最后找到类方法的实现进行调用
+        ///
+        ///
+        ///
+        ///关于superclass指针
+        ///
+        ///先看class对象中的superclass指针
+        ///Student的类对象的superclass 指向 Person的类对象,后者的superclass指针指向 NSObject的类对象
+        ///也就是类对象的superclass指向它父类的类对象
+        ///
+        ///[stu say];、[stu init];调用过程?
+        ///当Student的instance对象调用Person的对象方法时,
+        ///会先通过isa找到Student的class,
+        ///然后通过superclass找到Person的class,最后找到对象方法的实现进行调用
+        ///
+        ///同理,元类对象的superclass指针指向它的父类的元类对象
+        ///[Student fuxx]; 、[Student load];
+        ///当Student的class要调用Person的类方法时,
+        ///会先通过isa找到Student的meta-class,
+        ///然后通过superclass找到Person的meta-class,
+        ///最后找到类方法的实现进行调用
+        ///
+        ///总结
+        ///class的superclass指向父类的类对象
+        ///meta-class的superclass指向父类的meta-class对象
+        ///基类的meta-class的superclass指向基类的class(特殊)
+        ///
+        ///
+        ///instance对象调用对象方法的流程
+        ///
+
+        
+
+        
+        
+        
+        
+        
+        
+        
+
+    }
+    return 0;
+}

+ 4 - 1
objc4-779.1/runtime/objc-class.mm

@@ -178,7 +178,10 @@
 **********************************************************************/
 Class object_getClass(id obj)
 {
-    if (obj) return obj->getIsa();
+    //如果obj是instance对象,返回class对象
+    //如果obj是class,返回meta-class对象
+    //如果obj是meta-class,返回NSObjct(基类)的meta-class对象
+    if (obj) return obj->getIsa();//返回isa指向的对象
     else return Nil;
 }
 

BIN
对象、类与元类之间的关系图