source

iOS 앱 오류 - 자신을 하위 보기로 추가할 수 없습니다.

factcode 2023. 4. 9. 22:27
반응형

iOS 앱 오류 - 자신을 하위 보기로 추가할 수 없습니다.

크래시 보고서를 받았는데 디버깅 방법을 모르겠어요.

Fatal Exception NSInvalidArgumentException
Can't add self as subview
0 ...    CoreFoundation  __exceptionPreprocess + 130
1    libobjc.A.dylib     objc_exception_throw + 38
2    CoreFoundation  -[NSException initWithCoder:]
3    UIKit   -[UIView(Internal) _addSubview:positioned:relativeTo:] + 110
4    UIKit   -[UIView(Hierarchy) addSubview:] + 30
5    UIKit   __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke + 1196
6    UIKit   +[UIView(Animation) performWithoutAnimation:] + 72
7    UIKit   -[_UINavigationParallaxTransition animateTransition:] + 732
8    UIKit   -[UINavigationController _startCustomTransition:] + 2616
9    UIKit   -[UINavigationController _startDeferredTransitionIfNeeded:] + 418
10   UIKit   -[UINavigationController __viewWillLayoutSubviews] + 44
11   UIKit   -[UILayoutContainerView layoutSubviews] + 184
12   UIKit   -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 346
13   QuartzCore  -[CALayer layoutSublayers] + 142
14   QuartzCore  CA::Layer::layout_if_needed(CA::Transaction*) + 350
15   QuartzCore  CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 16
16   QuartzCore  CA::Context::commit_transaction(CA::Transaction*) + 228
17   QuartzCore  CA::Transaction::commit() + 314
18   QuartzCore  CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 56

iOS 버전은 7.0.3입니다.이 이상한 충돌 경험하신 분 있나요?

갱신:

이 크래시의 원인이 어디에 있는지 알 수 없기 때문에, 여기에 코드를 투고할 수 없습니다.

두 번째 업데이트

아래 답변을 참조하십시오.

최근에 디버깅한 비슷한 걸 근거로 추측하고 있는데...Animated(애니메이션)로 뷰 컨트롤러를 누르는 경우(또는 팝)네, 애니메이션이 바로 완료되지 않고 애니메이션이 완료되기 전에 다시 누르거나 팝업을 하면 좋지 않은 일이 발생합니다.푸시 및 팝 조작을 일시적으로 애니메이션으로 변경하면 실제로 이러한 상황이 발생하는지 쉽게 테스트할 수 있습니다.NO(동기적으로 완료되도록) 및 크래시가 제거되는지 확인합니다.이것이 실제로 문제이고 애니메이션을 다시 켜려면 UINavigationControllerDelegate 프로토콜을 구현하는 것이 올바른 전략입니다.여기에는 애니메이션이 완료된 후 호출되는 다음과 같은 메서드가 포함됩니다.

navigationController:didShowViewController:animated:

기본적으로 애니메이션을 완료하고 스택이 추가 변경을 수행할 준비가 될 때까지 NavigationController 스택에 변경을 일으킬 수 있는 다른 액션이 발생하지 않도록 하기 위해 필요에 따라 코드를 이 메서드로 이동해야 합니다.

우리도 이 문제가 발생하기 시작했는데, 같은 문제로 인해 발생했을 가능성이 높습니다.

이 경우 백엔드에서 데이터를 가져와야 하는 경우도 있었습니다.즉, 사용자가 무언가를 탭하면 내비게이션 푸시가 발생하기 전에 약간의 지연이 있을 수 있습니다.사용자가 빠르게 탭하는 경우 동일한 뷰 컨트롤러에서 두 번의 내비게이션 푸시가 발생할 수 있으며, 이것이 바로 이 예외를 트리거했습니다.

델의 솔루션은 UINavigation Controller의 카테고리입니다.상위 VC가 특정 시점부터 동일하지 않는 한 푸시/팝을 방지합니다.

.h 파일:

@interface UINavigationController (SafePushing)

- (id)navigationLock; ///< Obtain "lock" for pushing onto the navigation controller

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock; ///< Uses a horizontal slide transition. Has no effect if the view controller is already in the stack. Has no effect if navigationLock is not the current lock.
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock; ///< Pops view controllers until the one specified is on top. Returns the popped controllers. Has no effect if navigationLock is not the current lock.
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated navigationLock:(id)navigationLock; ///< Pops until there's only a single view controller left on the stack. Returns the popped controllers. Has no effect if navigationLock is not the current lock.

@end

.m 파일:

@implementation UINavigationController (SafePushing)

- (id)navigationLock
{
    return self.topViewController;
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock
{
    if (!navigationLock || self.topViewController == navigationLock) 
        [self pushViewController:viewController animated:animated];
}

- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated navigationLock:(id)navigationLock
{
    if (!navigationLock || self.topViewController == navigationLock)
        return [self popToRootViewControllerAnimated:animated];
    return @[];
}

- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock
{
    if (!navigationLock || self.topViewController == navigationLock)
        return [self popToViewController:viewController animated:animated];
    return @[];
}

@end

지금까지는 이것으로 문제가 해결된 것 같습니다.예:

id lock = _dataViewController.navigationController.navigationLock;
[[MyApi sharedClient] getUserProfile:_user.id success:^(MyUser *user) {
    ProfileViewController *pvc = [[ProfileViewController alloc] initWithUser:user];
    [_dataViewController.navigationController pushViewController:pvc animated:YES navigationLock:lock];
}];

기본적으로는 사용자와 관련되지 않은 지연이 발생하기 전에 해당 내비게이션컨트롤러에서 잠금을 가져와 푸시/팝 호출에 포함시키는 것이 규칙입니다.

'잠금'이라는 단어는 잠금 해제가 필요한 어떤 형태의 잠금이 있음을 암시하기 때문에 약간 부적절한 표현일 수 있지만, '잠금 해제' 방법은 어디에도 없기 때문에 괜찮을 것입니다.

(측면으로서 「비사용자 관련 지연」은, 코드로 인해 발생하는 지연, 즉 비동기적인 지연입니다.애니메이션으로 눌러진 내비게이션 컨트롤러를 탭하는 사용자는 카운트되지 않으며, 이러한 경우 navigationLock: 버전을 실행할 필요가 없습니다.)

이 코드는 문제를 해결합니다.https://gist.github.com/nonamelive/9334458

개인 API를 사용하지만 App Store가 안전한지 확인할 수 있습니다.(이 코드를 사용하는 앱 중 하나가 App Store에서 승인되었습니다.)

@interface UINavigationController (DMNavigationController)

- (void)didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;

@end

@interface DMNavigationController ()

@property (nonatomic, assign) BOOL shouldIgnorePushingViewControllers;

@end

@implementation DMNavigationViewController

#pragma mark - Push

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if (!self.shouldIgnorePushingViewControllers)
    {
        [super pushViewController:viewController animated:animated];
    }

    self.shouldIgnorePushingViewControllers = YES;
}

#pragma mark - Private API

// This is confirmed to be App Store safe.
// If you feel uncomfortable to use Private API, you could also use the delegate method navigationController:didShowViewController:animated:.
- (void)didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [super didShowViewController:viewController animated:animated];
    self.shouldIgnorePushingViewControllers = NO;
}

이 크래시에 대한 자세한 내용은 앱에서 설명하고 답변 완료로 표시합니다.

내 앱에는 UINavigationController가 있고 루트 컨트롤러는 노트 개체 목록을 포함하는 UITableViewController입니다.노트 오브젝트에는 html 콘텐츠 속성이 있습니다.상세 컨트롤러로 이동할 노트를 선택합니다.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    //get note object
    DetailViewController *controller = [[DetailViewController alloc] initWithNote:note];
    [self.navigationController pushViewController:controller animated:YES];
}

상세 컨트롤러

이 컨트롤러에는 UI WebView가 있으며 루트 컨트롤러에서 전달된 노트 내용을 표시합니다.

- (void)viewDidLoad
{
    ...
    [_webView loadHTMLString:note.content baseURL:nil];
    ...
}

이 컨트롤러는 웹 뷰 컨트롤의 위임자입니다.노트에 링크가 포함된 경우 링크를 누르면 앱 내 웹 브라우저로 이동합니다.

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    WebBrowserViewController *browserController = [[WebBrowserViewController alloc] init];
    browserController.startupURL = request.URL;
    [self.navigationController pushViewController:webViewController animated:YES];
    return NO;
}

위 크래시 리포트는 매일 받고 있습니다.내 코드의 어디에서 이 충돌이 일어났는지 모르겠어.사용자의 도움을 받아 몇 가지 조사를 한 결과, 이 크래시를 해결할 수 있었습니다.다음의 html 컨텐츠가 크래시의 원인이 됩니다.

...
<iframe src="http://google.com"></iframe>
...

Detail Controller의 viewDidLoad 메서드에서는 이 html을 webview컨트롤에 로드하고 나서 바로 위의 위임 메서드를 호출하여 요청을 받았습니다.URL은 iframe의 소스(google.com)입니다.이 위임 메서드는 viewDidLoad => crash 중에 pushViewController 메서드를 호출합니다!

나는 내비게이션을 확인해서 이 충돌을 해결했다.유형:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    if (navigationType != UIWebViewNavigationTypeOther)
    {
        //go to web browser controller
    }
}

도움이 되었으면 좋겠다

저도 같은 문제가 있었습니다만, 간단하게 효과가 있었던 것은 애니메이션을 변경하는 것이었습니다.○에서 애니메이션으로:아니요.

애니메이션이 제시간에 완료되지 않은 것이 원인으로 보입니다.

이게 도움이 됐으면 좋겠네요.

이 오류를 재현하려면 2개의 뷰 컨트롤러를 동시에 푸시해 보십시오.아니면 동시에 밀고 터지는 거.예:

여기에 이미지 설명 입력이러한 콜을 대행 수신해, 다른 푸시가 진행중에 발생하지 않게 하는 것으로써, 콜을 안전하게 하는 카테고리를 작성했습니다.프로젝트에 코드를 복사하기만 하면 메서드가 바뀌기 때문에 바로 사용할 수 있습니다.

#import "UINavigationController+Consistent.h"
#import <objc/runtime.h>
/// This char is used to add storage for the isPushingViewController property.
static char const * const ObjectTagKey = "ObjectTag";

@interface UINavigationController ()
@property (readwrite,getter = isViewTransitionInProgress) BOOL viewTransitionInProgress;

@end

@implementation UINavigationController (Consistent)

- (void)setViewTransitionInProgress:(BOOL)property {
    NSNumber *number = [NSNumber numberWithBool:property];
    objc_setAssociatedObject(self, ObjectTagKey, number , OBJC_ASSOCIATION_RETAIN);
}


- (BOOL)isViewTransitionInProgress {
    NSNumber *number = objc_getAssociatedObject(self, ObjectTagKey);

    return [number boolValue];
}


#pragma mark - Intercept Pop, Push, PopToRootVC
/// @name Intercept Pop, Push, PopToRootVC

- (NSArray *)safePopToRootViewControllerAnimated:(BOOL)animated {
    if (self.viewTransitionInProgress) return nil;
    if (animated) {
        self.viewTransitionInProgress = YES;
    }
    //-- This is not a recursion, due to method swizzling the call below calls the original  method.
    return [self safePopToRootViewControllerAnimated:animated];

}


- (NSArray *)safePopToViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (self.viewTransitionInProgress) return nil;
    if (animated) {
        self.viewTransitionInProgress = YES;
    }
    //-- This is not a recursion, due to method swizzling the call below calls the original  method.
    return [self safePopToViewController:viewController animated:animated];
}


- (UIViewController *)safePopViewControllerAnimated:(BOOL)animated {
    if (self.viewTransitionInProgress) return nil;
    if (animated) {
        self.viewTransitionInProgress = YES;
    }
    //-- This is not a recursion, due to method swizzling the call below calls the original  method.
    return [self safePopViewControllerAnimated:animated];
}



- (void)safePushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    self.delegate = self;
    //-- If we are already pushing a view controller, we dont push another one.
    if (self.isViewTransitionInProgress == NO) {
        //-- This is not a recursion, due to method swizzling the call below calls the original  method.
        [self safePushViewController:viewController animated:animated];
        if (animated) {
            self.viewTransitionInProgress = YES;
        }
    }
}


// This is confirmed to be App Store safe.
// If you feel uncomfortable to use Private API, you could also use the delegate method navigationController:didShowViewController:animated:.
- (void)safeDidShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    //-- This is not a recursion. Due to method swizzling this is calling the original method.
    [self safeDidShowViewController:viewController animated:animated];
    self.viewTransitionInProgress = NO;
}


// If the user doesnt complete the swipe-to-go-back gesture, we need to intercept it and set the flag to NO again.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    id<UIViewControllerTransitionCoordinator> tc = navigationController.topViewController.transitionCoordinator;
    [tc notifyWhenInteractionEndsUsingBlock:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        self.viewTransitionInProgress = NO;
        //--Reenable swipe back gesture.
        self.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)viewController;
        [self.interactivePopGestureRecognizer setEnabled:YES];
    }];
    //-- Method swizzling wont work in the case of a delegate so:
    //-- forward this method to the original delegate if there is one different than ourselves.
    if (navigationController.delegate != self) {
        [navigationController.delegate navigationController:navigationController
                                     willShowViewController:viewController
                                                   animated:animated];
    }
}


+ (void)load {
    //-- Exchange the original implementation with our custom one.
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(pushViewController:animated:)), class_getInstanceMethod(self, @selector(safePushViewController:animated:)));
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(didShowViewController:animated:)), class_getInstanceMethod(self, @selector(safeDidShowViewController:animated:)));
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(popViewControllerAnimated:)), class_getInstanceMethod(self, @selector(safePopViewControllerAnimated:)));
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(popToRootViewControllerAnimated:)), class_getInstanceMethod(self, @selector(safePopToRootViewControllerAnimated:)));
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(popToViewController:animated:)), class_getInstanceMethod(self, @selector(safePopToViewController:animated:)));
}

@end

저도 방금 이 문제를 경험했습니다.제 코드를 보여드리겠습니다.

override func viewDidLoad() { 
  super.viewDidLoad()

  //First, I create a UIView
  let firstFrame = CGRect(x: 50, y: 70, height: 200, width: 200)
  let firstView = UIView(frame: firstFrame)
  firstView.addBackgroundColor = UIColor.yellow
  view.addSubview(firstView) 

  //Now, I want to add a subview inside firstView
  let secondFrame = CGRect(x: 20, y:50, height: 15, width: 35)
  let secondView = UIView(frame: secondFrame)
  secondView.addBackgroundColor = UIColor.green
  firstView.addSubView(firstView)
 }

이 에러는, 다음의 행에 의해서 발생합니다.

firstView.addSubView(firstView)

서브뷰에 셀프를 추가할 수 없습니다.코드 행을 다음과 같이 변경했습니다.

firstView.addSubView(secondView)

오류가 사라져서 두 가지 뷰를 모두 볼 수 있었습니다.이게 사례를 보고 싶은 사람에게 도움이 될 것 같아서요

뷰를 뷰에 잘못 추가하려고 할 수 있습니다.

halfView.addSubview(halfView)

하위 보기로 변경합니다.

halfView.addSubview(favView)

코드를 검색하여 "add Subview"를 찾습니다.

이 메서드를 호출한 플레이스 중 하나에서 이 메서드를 사용하여 뷰를 자체 하위 뷰 배열에 추가하려고 했습니다.

예를 들어 다음과 같습니다.

[self.view addSubview:self.view];

또는 다음 중 하나를 선택합니다.

[self.myLabel addSubview:self.myLabel];

애니메이션으로 뷰 컨트롤러를 푸시/팝핑하는 것은 어느 시점에서나 문제없고 SDK는 전화 큐에 친절하게 대응해야 한다고 생각합니다.

따라서 이는 실행되지 않으며 모든 솔루션은 후속 푸시를 무시하려고 합니다. 이는 최종 내비게이션 스택이 코드가 의도한 바가 아니기 때문에 버그로 간주될 수 있습니다.

대신 푸시 콜 큐를 구현했습니다.

// SafeNavigationController.h

@interface SafeNavigationController : UINavigationController
@end

 

// SafeNavigationController.m

#define timeToWaitBetweenAnimations 0.5

@interface SafeNavigationController ()

@property (nonatomic, strong) NSMutableArray * controllersQueue;
@property (nonatomic)         BOOL animateLastQueuedController;
@property (nonatomic)         BOOL pushScheduled;
@property (nonatomic, strong) NSDate * lastAnimatedPushDate;

@end

@implementation SafeNavigationController

- (void)awakeFromNib
{
    [super awakeFromNib];

    self.controllersQueue = [NSMutableArray array];
}

- (void)pushViewController:(UIViewController *)viewController
                  animated:(BOOL)animated
{
    [self.controllersQueue addObject:viewController];
    self.animateLastQueuedController = animated;

    if (self.pushScheduled)
        return;

    // Wait for push animation to finish
    NSTimeInterval timeToWait = self.lastAnimatedPushDate ? timeToWaitBetweenAnimations + [self.lastAnimatedPushDate timeIntervalSinceNow] : 0.0;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((timeToWait > 0.0 ? timeToWait : 0.0) * NSEC_PER_SEC)),
                   dispatch_get_main_queue(), ^
                   {
                       [self pushQueuedControllers];

                       self.lastAnimatedPushDate = self.animateLastQueuedController ? [NSDate date] : nil;
                       self.pushScheduled = NO;
                   });
    self.pushScheduled = YES;
}

- (void)pushQueuedControllers
{
    for (NSInteger index = 0; index < (NSInteger)self.controllersQueue.count - 1; index++)
    {
        [super pushViewController:self.controllersQueue[index]
                         animated:NO];
    }
    [super pushViewController:self.controllersQueue.lastObject
                     animated:self.animateLastQueuedController];

    [self.controllersQueue removeAllObjects];
}

@end

푸시 큐와 팝 큐가 뒤섞인 큐를 처리하지는 않지만 대부분의 크래시를 수정하는 데 좋은 출발점이 됩니다.

개요: https://gist.github.com/rivera-ernesto/0bc628be1e24ff5704ae

츠키노최근 여러 뷰 컨트롤러를 동시에 눌러서 네비게이션 바가 파손되는 문제가 발생했습니다.이 문제는 첫 번째 뷰 컨트롤러가 아직 애니메이션 상태일 때 다른 뷰 컨트롤러가 푸시되기 때문에 발생합니다.비매력적인 대답에서 힌트를 얻어, 나는 나의 경우에 맞는 간단한 해결책을 생각해냈다..UINavigationController뷰되지 않았는지 합니다.pushViewController는 아직 종료되지 않았습니다. 수 입니다.UINavigationControllerDelegate 대리자를 '대리인'으로 설정합니다.self.

간단하게 하기 위해 여기에 요지를 올렸습니다.

스토리보드에서 이 새 클래스를 Navigation Controller로 설정하십시오.

저도 이 문제가 발생했습니다.Firebase 로그 분석을 해보니, 이 문제는 앱이 콜드 부팅되었을 때만 발생한다는 것을 알게 되었습니다.그래서 저는 이 충돌을 재현할 수 있는 데모를 만들었습니다.

.

또한 윈도우의 루트 뷰 컨트롤러가 표시될 때 여러 번 누르면 동일한 문제가 다시 발생하지 않습니다.(AppDelegate.swift에서는 testColdStartUp(rootNav)에 코멘트를 달아 ViewController.swift에서는 testColdStartUp() 코멘트를 언코멘트할 수 있습니다).

ps: 이 크래시 장면을 앱으로 분석했습니다.사용자가 앱을 콜드 스타트하기 위한 푸시 알림을 클릭해도 앱은 여전히 시작 페이지에 있고 다른 푸시 버튼을 클릭하여 점프합니다.이때 앱이 크래쉬로 나타날 수 있습니다.현재 솔루션은 푸시 또는 유니버설 링크 콜드 스타트 캐시를 통해 앱 점프 페이지를 열고 루트 뷰 컨트롤러가 표시될 때까지 기다렸다가 실행을 지연시키는 것입니다.

이러한 문제를 방지하기 위해 @RobP great hint를 기반으로 UINavigation Controller 서브클래스를 만들었습니다.푸시 및/또는 팝업을 처리하여 다음 작업을 안전하게 수행할 수 있습니다.

[self.navigationController pushViewController:vc1 animated:YES];
[self.navigationController pushViewController:vc2 animated:YES];
[self.navigationController pushViewController:vc3 animated:YES];
[self.navigationController popViewControllerAnimated:YES];

acceptConflicingCommands' 플래그가 true(기본값)이면 vc1, vc2, vc3의 애니메이션 푸시가 표시되고 vc3의 애니메이션 팝업이 표시됩니다.'acceptConflicingCommands'가 false일 경우 vc1이 완전히 푸시될 때까지 모든 푸시/팝 요청이 폐기됩니다. 따라서 나머지 3개의 콜은 폐기됩니다.

노멜라베라베라베라베라베라베라베라베라베라베라베라베라베라베라베라., API를 API를 할 수 .UINavigationControllerDelegate 애니메이션으로 .YES로로 합니다.NO뭇매를 맞다 상속할 수 있습니다.되었으면 : )

https://github.com/antrix1989/ANNavigationController

이 문제를 많이 검색했습니다.동시에 2개 이상의 VC를 푸시하면 애니메이션 푸싱 문제가 발생할 수 있습니다.Cannot Add Self as Subview " " 解解解法 i i i 。

이행의 진척을 동시에 진행하고 있는 VC가 1개 있는 것을 확인해 주세요.행운을 빕니다.

마지막 내비게이션 애니메이션을 완성하기 위해 지연 방법을 사용하여 내비게이션을 시도합니다.

[self performSelector:<#(SEL)#> withObject:<#(id)#> afterDelay:<#(NSTimeInterval)#>]

보기는 자체에서 하위 보기로 추가할 수 없습니다.

뷰는 부모-자녀 계층을 유지하므로 뷰 자체를 하위 뷰로 추가하면 예외를 통과합니다.

클래스가 UIViewController인 경우 해당 뷰를 가져오려면 self.view를 사용합니다.

클래스가 [UIView Class]인 경우, 그 뷰를 얻기 위해 당신은 자신을 사용한다.

UiViewController 클래스가 될 경우 self를 서브뷰로 추가할 수 없습니다.UiView클래스가 될 경우 self를 서브뷰로 추가할 수 있습니다.

뷰에 서브뷰를 추가하려면 다음과 같이 할 수 있습니다.

UIView *mainview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)]; //Creats the mainview
    UIView *subview = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)]; //Creates the subview, you can use any kind of Views (UIImageView, UIWebView, UIView…)

    [mainview addSubview:subview]; //Adds subview to mainview

언급URL : https://stackoverflow.com/questions/19560198/ios-app-error-cant-add-self-as-subview

반응형