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

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

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

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

第一种关系:继承。

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

@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;

}


目录
相关文章
|
6月前
|
C++
C++程序中的继承与组合
C++程序中的继承与组合
67 1
|
3月前
|
Java
继承与组合的区别
【8月更文挑战第22天】
35 0
|
6月前
|
C++
4. C++类的组合
4. C++类的组合
57 0
|
6月前
|
C++
52继承与组合
52继承与组合
27 0
|
算法 C语言 C++
C++类的组合练习
C++类的组合练习
|
算法 C++ 容器
关系类算法函数
关系类算法函数
|
编译器 C语言 C++
C++ 之什么是类 & 对象的关系?
C++ 之什么是类 & 对象的关系?
接口vs抽象类、继承vs组合,他们之间有啥关系
接口vs抽象类、继承vs组合,他们之间有啥关系
|
程序员
组合、继承、内部类什么时候用,该怎么设计?
组合、继承、内部类什么时候用,该怎么设计?
140 0
组合、继承、内部类什么时候用,该怎么设计?