iOS ViewController가 get 방법을 이용하여view를 만드는 위험
viewDidLoad
방법의 코드를 더욱 간결하고 조리가 있어 보인다.그러나 실제로 이런 방법은 위험이 존재한다. 아래의 코드 예를 보면 다음과 같다.// MyViewController.h
@interface MyViewController : UIViewController
- (void)setLabelText:(NSString *)text;
@end
// MyViewController.m
#import "MyViewController.h"
@interface MyViewController ()
@property (nonatomic, strong) UILabel *label;
@end
@implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
[self.view addSubview:self.label];
}
- (void)setLabelText:(NSString *)text {
self.label.text = text;
}
- (UILabel *)label {
if (!_label) {
_label = [[UILabel alloc] initWithFrame:self.view.bounds];
_label.backgroundColor = [UIColor redColor];
}
return _label;
}
@end
// ParentViewController.h
@interface ParentViewController : UIViewController
@end
// ParentViewController.m
#import "ParentViewController.h"
#import "MyViewController.h"
@interface ParentViewController ()
@end
@implementation ParentViewController
- (void)viewDidLoad {
[super viewDidLoad];
MyViewController *vc = [[MyViewController alloc] init];
[vc setLabelText:@"123"];
[self.view addSubview:vc.view];
[self addChildViewController:vc];
[vc didMoveToParentViewController:self];
}
위에서 보듯이 현재 2개의 controller:
ParentViewController
과 MyViewController
을 정의했다.이 중 MyViewController
은 하위 컨트롤러로 ParentViewController
에 나타났다.MyViewController
, get 방법을 다시 써서 전체 화면의 label을 만들고 문서를 표시합니다.현재
ParentViewController
을 만들고push를 표시합니다. 코드는 다음과 같습니다.- (void)gotoNext {
ParentViewController *vc = [[ParentViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
이 주요 코드가 모두 완성되었습니다. 프로그램이 실현하고자 하는 기능: 새push에 나온 페이지에 빨간색 label이 표시되며, 문안은 123입니다.
이 프로그램이 우리가 원하는 기능을 실현할 수 있는지 분석해 봅시다.만약 안 된다면, 인터페이스는 어떤 것을 보여줍니까?
답안: 기능을 실현할 수 없습니다. 인터페이스에 표시된 label의 배경색(빨간색)이 있지만 문안이 없습니다.
이유는 다음과 같습니다.
[vc setLabelText:@"123"]
을 호출하여 self.label.text = text;
을 실행하고 label 속성의 get 방법을 터치하여 label 창설의 논리에 들어가면 _label = [[UILabel alloc] initWithFrame:self.view.bounds];
이 줄 코드를 호출하는 실행 순서는 [UILabel alloc]
-> self.view.bounds
-> initWithFrame:
->label 변수에 값을 부여합니다.self.view.bounds
까지 실행되었을 때 컨트롤러의view가 만들어지지 않았기 때문에 self.view
은 컨트롤러의 loadView
과 viewDidLoad
등 관련 방법을 촉발한다.viewDidLoad
방법에서 [self.view addSubview:self.label];
에 label 속성을 다시 터치하는 get 방법을 호출합니다.이 호출 창고는self이기 때문입니다.view->viewDidLoad->get 방법, 그래서 위에서 언급한 _label = [[UILabel alloc] initWithFrame:self.view.bounds]
코드는 initWithFrame:
방법을 실행하지 않았고 완성하지 않았습니다label의 값 부여 작업이기 때문에 여기에서 호출한 get 방법은 if (!_label)
문장을 통해 label의 실례를 다시 만들고 이 실례를 되돌려줍니다. 이 실례는dd에 의해 controller에 연결됩니다.view에서 이viewDidLoad가 실행되었습니다.self로 돌아갑니다.view, self.view.bounds
계속 실행 -> initWithFrame:
->label 변수에 값을 부여합니다.여기까지 거의 분석이 끝났습니다. 위에서 언급한 바와 같이 프로그램 뒤에 또label 변수는 새로운 실례를 부여하여
self.label.text = text;
이때self로 되돌려줍니다.label은 새로운 실례, 이 실례와 controller를 가리킨다.view에 붙인 label은 다른 두 가지 실례입니다.그래서 셀프한테.label 값 부여 문자는 아무런 작용이 없습니다. 왜냐하면 이 label은 전혀 나타나지 않았기 때문입니다.다른 상관없는 label이 표시됩니다.总结
문제는 controller의 보기가 만들어지지 않았고 get 방법에서self가 사용되었습니다.view,viewDidLoad의 호출 시기가 혼란스러웠습니다.
그래서 다음과 같은 몇 가지 개법이 있다.
첫 번째 개법의 폐단: 만약 보기가self에 의존한다면.view, 사용할 수 없습니다.여기서 제2중개법을 제창한다.
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
//[self.view addSubview:self.label];
[self.view addSubview:[self setupLabel]];
}
- (void)setLabelText:(NSString *)text {
self.label.text = text;
}
//- (UILabel *)label {
- (UILabel *)setupLabel {
if (!_label) {
_label = [[UILabel alloc] initWithFrame:self.view.bounds];
_label.backgroundColor = [UIColor redColor];
}
return _label;
}
실제로는 방법명만 바꾸고 아무런 변동도 필요 없이 실현하면 된다.
마지막으로 예시 코드의 데모를 첨부합니다
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.