类间两种关系:继承、 组合

简介: 类间两种关系:继承、 组合

类间两种关系:继承、 组合。类间非继承关系,而调用了其它类的对象方法或访问了其它类的成员变量,那么他们间的关系统称组合关系。

广义上讲,组合也包含另两个特别的情况:单例访问、 通过根控制器或导航控制器找到对应页面控制器进行操作。

第一种关系:继承。

大家都知道通过父子类的继承关系,子类对象可以访问父类对象的公有成员变量和公有成员函数,这个就不多说了。

@interface SettingProfileHeadCell : SettingProfileCell

@property UIImageView *headImageView;

@property UILabel *describeLabel;

@end

第二种关系:普通组合关系。

类间的组合关系大家也经常用,一个类的成员对象是另一个类的对象。这个也不难了解。

它又包含两种情况:

1.生成的另一个类的对象是本类的一个成员对象。

2.生成的另一个类的对象是本类的成员函数的一个临时对象,随着本类的成员函数的调用结束,系统就销毁了该临时对象。

第一种情况:

生成的另一个类的对象是本类的一个成员对象的声明部分

@interface DrawMoneyViewController ()

{

}

@property CustomCommonNavigationBar *customCommonNavigationBar;

@end

@implementation DrawMoneyViewController

生成对象的部分:

- (void)setupSubViews {

self.view.backgroundColor = BACKGROUND_COLOR;

_customCommonNavigationBar = [[CustomCommonNavigationBar alloc] initWithLeftBtnImageName:@”NavBar_icon_Back_dark” LeftBtnShift:19 RightBtnTitle:@”” title:@”提现” titleIsBold:NO];

[self.view addSubview:_customCommonNavigationBar];

_customCommonNavigationBar.sd_layout

.leftSpaceToView(self.view, 0)

.rightSpaceToView(self.view, 0)

.topSpaceToView(self.view, 0)

.heightIs(64 + LINE_THICK); // 设置高度约束

[self loadButtonAction];

}

使用页面控制器包含的控件block:

-(void)loadButtonAction

{

[_customCommonNavigationBar backResult:^(BOOL iSuccess) {

[self.navigationController popViewControllerAnimated:YES];

}];

}

第二种情况:成员函数临时变量的数据序列化例子:

- (void)storageDataModelWithFileName:(NSString *)fileName
dataArr:(NSMutableArray *)dataArr;
{
if(![fileName isKindOfClass:[NSString class]] || ![dataArr isKindOfClass:[NSMutableArray class]] || (dataArr.count == 0))
{
return;
}
NSString *plistFileName = [fileName stringByReplacingOccurrencesOfString:@” ” withString:@”“];
if(plistFileName.length == 0)
{
return;
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSFileManager* fm = [NSFileManager defaultManager];
NSString *path=[paths objectAtIndex:0];
path = [path stringByAppendingPathComponent:LOCATION_DATA];
if (![fm fileExistsAtPath:path])
{
[fm createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
}
NSString *filePath = [path stringByAppendingPathComponent:plistFileName]; //获取路径
if([plistFileName isEqualToString:ORDER_CENTER_PLIST_FILE_NAME])
{
OrderOperateModel *orderOperateModel = nil;
NSMutableArray *arr = [NSMutableArray array];
for(NSUInteger i = 0; i < dataArr.count; i++)
{
OrderCellModel *model = dataArr[i];
if(![model isKindOfClass:[OrderCellModel class]])
{
return;
}
orderOperateModel = [[OrderOperateModel alloc] initWithDictionary:model];
[arr addObject:orderOperateModel];
}
if(arr.count > 0)
{
NSData * tempArchive = [NSKeyedArchiver archivedDataWithRootObject:arr];
[tempArchive writeToFile:filePath atomically:YES];
}
}
}
第二种情况:成员函数临时变量的页面跳转例子:
-(void)openOnlineServiceViewController : (NSMutableDictionary *)orderInfo
{
OnlineServiceViewController *onlineServiceViewController = [OnlineServiceViewController new];
[onlineServiceViewController displayOrderInfo : orderInfo];
[self.navigationController pushViewController:onlineServiceViewController animated:YES];
}

特殊的组合关系:单例访问。
一个类的对象中的函数可以访问全局的单例。
使用系统的单例的block:
__weak typeof(self) weakSelf = self;
AppDelegate app = (AppDelegate )[UIApplication sharedApplication].delegate;
[app regisiterXYContinueListenOrderCallback:^{
[weakSelf continueListenOrder];
}];
使用单例的变量:
[SingleObject sharedInstance].keyboardWasShownFlag = NO;
使用单例的函数:

[[SingleObject sharedInstance] initData];

使用单例的block:

[[SocketManager shareInstance] regisiterOnlineServiceCallBackMessageCallBack:^(NSMutableDictionary *message) {
    [weakSelf handleMessageWithMessage:message];
}];

特殊的组合关系:通过根控制器或导航控制器找到对应页面控制器进行操作。

它和第二种关系的主要区别是它不是直接在本类生成该对象,而是找到已经存在的对象,并进行操作。

它和第三种关系的主要区别是它不是直接找到该对象,而是通过根控制器(也可能是导航控制器)找到,甚至根控制器(也可能是导航控制器)也是被间接找到的。

在一个页面控制器里可以通过导航控制器找到其它页面控制器,对它的公有成员数据进行赋值,也可以对它的公有函数进行调用,一般近接着就要跳到找到的这个页面控制器。

-(void)openOnlineServiceViewController : (NSMutableDictionary *)orderInfo

{

for (UIViewController *viewController in self.navigationController.viewControllers) {

if ([viewController isKindOfClass:[OnlineServiceViewController class]]) {

OnlineServiceViewController onlineServiceViewController = (OnlineServiceViewController )viewController;

[self.navigationController popToViewController:onlineServiceViewController animated:YES];

return;

}

}

OnlineServiceViewController *onlineServiceViewController = [OnlineServiceViewController new];

[onlineServiceViewController displayOrderInfo : orderInfo];

[self.navigationController pushViewController:onlineServiceViewController animated:YES];

}

在一个页面控制器里或非页面控制器里可以通过keyWindow找到rootViewController,然后通过它可以找到本导航控制器,然后通过本导航控制器找到指定的页面控制器,对它的公有成员数据进行赋值,也可以对它的公有函数进行调用,一般近接着就要跳到找到的这个页面控制器。

所以这种情况算着上一种情况的一种特殊情况。

使用这种方式找页面控制器时要注意一下三种情况:

1.当你在高德导航地图页面,你找到的就不是rootViewController了,是导航地图图层。

2.若你的页面出现了循环跳转,当使用该方法循环跳转了多次,你再用该种方法找页面可能出现异常情况(我的首页使用了两个子试图,一个做侧边栏,一个作普通的首页,在两个子试图间产生页面循环,使用该方法多次循环跳转后崩溃。估计普通的循环页面跳转使用该方法不会产生崩溃)。

3.当你的页面有多于一个导航控制器时(如:有侧边栏的应用),要注意导航控制器的层级。

-(void)goToLoginViewControlNotification

{

NSArray *cv = [[self getCurrentVC] childViewControllers];

NSLog(@”%@”,cv);

if(cv.count == 0)

{

return;

}

[[GlobalShare getGlobalShare] clearUserInfo];

UIViewController viewCtrl = (UIViewController )(cv[0]);

if([viewCtrl isKindOfClass:[LoginViewController class]])
{
    return;
}
for (UIViewController *viewController in self.navigationController.viewControllers) {
    if ([viewController isKindOfClass:[LoginViewController class]]) {
        [self.navigationController popToViewController:viewController animated:YES];
    }
}

}


(UIViewController *)getCurrentVC

{

UIViewController *result = nil;


UIWindow * window = [[UIApplication sharedApplication] keyWindow];

if (window.windowLevel != UIWindowLevelNormal)

{

NSArray *windows = [[UIApplication sharedApplication] windows];

for(UIWindow * tmpWin in windows)

{

if (tmpWin.windowLevel == UIWindowLevelNormal)

{

window = tmpWin;

break;

}

}

}

UIView *frontView = [[window subviews] objectAtIndex:0];

id nextResponder = [frontView nextResponder];


if ([nextResponder isKindOfClass:[UIViewController class]])

result = nextResponder;

else

result = window.rootViewController;


return result;

}


目录
相关文章
|
存储 项目管理 Python
数据导入与预处理-第4章-数据获取python读取docx文档(上)
数据导入与预处理-第4章-pandas数据获取docx文档 1.python读取docx文档概述 1.1 从Word文件获取数据 1.2 python-docx库介绍 1. Paragraph类 2. Table类
数据导入与预处理-第4章-数据获取python读取docx文档(上)
|
机器学习/深度学习 Go 计算机视觉
YOLOv8改进 | Neck篇 | 利用ASF-YOLO改进特征融合层(适用于分割和目标检测)
YOLOv8改进 | Neck篇 | 利用ASF-YOLO改进特征融合层(适用于分割和目标检测)
744 1
|
3月前
|
IDE JavaScript 程序员
HarmonyOS Next 如何优雅的编写注释
本文介绍了如何在 HarmonyOS NEXT 中优雅地编写注释,提升代码可读性和维护性。通过使用 jsDoc 或 TypeDoc 规范,开发者可以为项目生成清晰的说明文档。文章详细解析了常见修饰符(如 @param、@returns、@async 等)的用法,并展示了 DevEco Studio 自动生成 ArkTSDoc 文档的功能。遵循这些规范,团队能够更高效协作,同时 IDE 也能提供更好的语法提示支持。
93 20
HarmonyOS Next 如何优雅的编写注释
|
6月前
|
图形学 异构计算
Siemens NX何时支持GPU光线追踪与图形加速?
NX的Ray Tracing Studio在NX 1847及更早版本中不支持NVIDIA RTX板的GPU加速,仅依赖CPU,性能较慢。从NX 1872起支持GPU加速。自2023年6月版起,若无GPU,NX将显示图形配置错误并记录到syslog文件,建议使用支持的GPU以避免未定义行为。更多支持的硬件和图形信息,请参阅鼎森电脑整理的文件“NX-Graphics-Certification-Table_20241207.xlsx”。链接:https://pan.baidu.com/s/1_FpOoJU_IrExnhVXyzB4cw?pwd=676s 提取码: 676s
168 1
|
10月前
|
网络协议
TCP 三次握手:工作原理及重要性
【8月更文挑战第25天】
360 0
|
6月前
|
消息中间件 安全 Java
vulhub部分复现记录(后面大概都是原文档了,也比较难复现就不继续了)
本文介绍了多个软件的安全漏洞及其复现过程,涉及的软件包括Vulhub、Flask、ActiveMQ、Adminer、Airflow、Apache Druid、Apereo CAS、APISIX、AppWeb、Aria2、Bash、Cacti、Celery、CGI、ColdFusion和Confluence。每个部分详细描述了漏洞的背景、环境搭建步骤、漏洞复现的具体操作和验证方法。例如,Flask的SSTI漏洞通过构造特定的模板参数实现命令执行;ActiveMQ的反序列化漏洞利用特制的序列化对象触发;这些示例不仅展示了漏洞的危害性,还提供了实际的复现步骤,帮助读者深入理解这些安全问题。
942 3
vulhub部分复现记录(后面大概都是原文档了,也比较难复现就不继续了)
|
存储 JSON Kubernetes
基于 cri-dockerd 二进制部署 kubernetest-v1.26.3 2
基于 cri-dockerd 二进制部署 kubernetest-v1.26.3
165 0
|
Web App开发 移动开发 iOS开发
input输入框的23中类型
input输入框的23中类型
204 1
QString字符串的查找与截取实例
QString字符串的查找与截取实例
362 1
|
10月前
|
Python
Python常用工具类
Python常用工具类
72 0