programing

UIView 하위 클래스의 Nib을 로드하는 올바른 방법

goodsources 2023. 10. 18. 22:04
반응형

UIView 하위 클래스의 Nib을 로드하는 올바른 방법

이 질문은 이전에 질문한 적이 있는 것으로 알고 있지만 답변이 상반되고 혼란스러우니 제발 저를 화나게 하지 말아주세요.

재사용 가능한 것을 갖고 싶습니다.UIView서브클래스로 이동할 수 있습니다.nib 파일을 사용하여 인터페이스를 설명하고자 합니다.

이제 작업 지시자가 포함된 로딩 지시자 뷰라고 가정해 보겠습니다.이 보기를 인스턴스화하고 보기 컨트롤러 보기로 애니메이션화하는 이벤트를 하고 싶습니다.저는 뷰의 인터페이스를 프로그래밍 방식으로 설명할 수 있었습니다. 요소를 프로그래밍 방식으로 만들고 프레임을 init 방식으로 설정하는 등 말이죠.

근데 이거 어떻게 펜촉으로 하는 거예요?프레임을 설정할 필요 없이 인터페이스 빌더에 주어진 크기를 유지합니다.

저는 이 방법을 사용해 왔지만, 잘못된 것이라고 확신합니다. (이것은 단지 선택 도구가 있는 보기일 뿐입니다.

 - (id)initWithDataSource:(NSDictionary *)dataSource {
        self = [super init];
        if (self){
            self = [[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:@"%@", [self class]] owner:self options:nil] objectAtIndex:0];
            self.pickerViewData = dataSource;
            [self configurePickerView];
        }
        return self;
    }

하지만 저는 자기 자신을 덮어쓰고 있습니다. 그리고 그것을 인스턴스화할 때:

FSASelectView *selectView = [[FSASelectView alloc] initWithDataSource:selectViewDictionary];
    selectView.delegate = self;

    selectView.frame = CGRectMake(0, self.view.bottom + 50, [FSASelectView width], [FSASelectView height]);

IB에서 프레임을 픽업하는 것보다 수작업으로 프레임을 설정해야 합니다.

편집: 뷰 컨트롤러에 이 사용자 지정 뷰를 만들고 뷰의 요소를 제어할 수 있는 액세스 권한을 가지려고 합니다.저는 새로운 뷰 컨트롤러를 원하지 않습니다.

감사해요.

편집: 이것이 최선의 방법인지는 모르겠지만, 분명 그렇지는 않지만, 제가 이렇게 한 방법은 이렇습니다.

FSASelectView *selectView = [[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:@"%@",[FSASelectView class]] owner:self options:nil] objectAtIndex:0];
    selectView.delegate = self;
    [selectView configurePickerViewWithData:ds];
    selectView.frame = CGRectMake(0, self.view.bottom + 50, selectView.width, selectView.height);
    selectView.alpha = 0.9;
    [self.view addSubview:selectView];
    [UIView animateWithDuration: 0.25 delay: 0 options:UIViewAnimationOptionAllowUserInteraction |UIViewAnimationOptionCurveEaseInOut animations:^{
                            selectView.frame = CGRectMake(0, self.view.bottom - selectView.height, selectView.width, selectView.height);
                            selectView.alpha = 1;
                        } completion:^(BOOL finished) {
                        }];

정확한 실습이 여전히 필요함

보기 컨트롤러를 사용하여 이 작업을 수행하고 nib 이름으로 init를 수행했어야 했습니까?코드의 UIView 초기화 방법으로 nib을 설정했어야 합니까?아니면 제가 한 일이 괜찮은가요?

MyViewClass *myViewObject = [[[NSBundle mainBundle] loadNibNamed:@"MyViewClassNib" owner:self options:nil] objectAtIndex:0]

재사용 가능한 사용자 지정 보기를 초기화하는 데 사용하고 있습니다.


여기서 마지막에 "first Object"를 사용하면 좀 더 깨끗합니다.NSray와 NSMutable Array에서 편리한 방법은 "first Object"입니다.

테이블 헤더로 사용할 xib를 로드하는 전형적인 예가 있습니다.당신의 파일에 당신의 클래스.m.

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    return [[NSBundle mainBundle] loadNibNamed:@"TopArea" owner:self options:nil].firstObject;
}

에서.TopArea.xib, File Owner(파일 소유자)를 클릭하고 파일 소유자를 Your Class(유어 클래스)로 설정합니다.그러면 실제로 YourClass.h에는 IBOUTlet 속성이 있습니다.TopArea.xib, 제어 장치를 저 콘센트로 끌면 됩니다.

에서 그걸 TopArea.xib, 보기 자체를 클릭하여 필요한 경우 해당 보기를 어느 콘센트로 끌어다 놓아야 할 수도 있습니다. (매우 가치 있는 팁은 테이블 셀 행에 대해 이 작업을 수행할 때 반드시 해당 작업을 수행해야 한다는 것입니다. 즉, 보기 자체를 코드의 관련 속성에 연결해야 한다는 것입니다.

당신이 당신의 것을 유지하고 싶다면.CustomView그리고 그것의xib과는 무관하게File's Owner, 그런 다음 이 단계를 따릅니다.

  • 나가세요File's Owner필드가 비어 있습니다.
  • 실제 보기 클릭xib너의 파일CustomView그것을 설정합니다.Custom Class~하듯이CustomView(사용자 정의 보기 클래스 이름)
  • 더하다IBOutlet인에.h사용자 정의 보기의 파일입니다.
  • .xib사용자 정의 보기의 파일, 보기를 클릭하고 들어가십시오.Connection Inspector. 여기서 정의한 모든 IBOUTLET이 표시됩니다..h파일
  • 각각의 보기와 연결합니다.

인에.m너의 파일CustomView 클래스, override theinit방법은 다음과 같습니다.

-(CustomView *) init{
    CustomView *result = nil;
    NSArray* elements = [[NSBundle mainBundle] loadNibNamed: NSStringFromClass([self class]) owner:self options: nil];
    for (id anObject in elements)
    {
        if ([anObject isKindOfClass:[self class]])
        {
            result = anObject;
            break;
        }
    }
    return result;
}

이제 당신이 당신의 짐을 싣고 싶을 때.CustomView, 다음 줄의 코드를 사용합니다.[[CustomView alloc] init];

다음 단계를 따릅니다.

  1. MyView .h/.m .UIView.
  2. 같은 이름의 xib 만들기MyView.xib.
  3. 이제 파일 소유자 클래스를 다음으로 변경합니다.UIViewController부터NSObjectXIB로아래 이미지 참조enter image description here
  4. 파일 소유자 보기를 보기에 연결합니다.아래 이미지 참조enter image description here

  5. 보기 클래스를 다음으로 변경합니다.MyView랑 같아요 3과 같습니다.

  6. 컨트롤 배치는 IBOUTlet을 만듭니다.

View를 로드하는 코드는 다음과 같습니다.

UIViewController *controller=[[UIViewController alloc] initWithNibName:@"MyView" bundle:nil];
MyView* view=(MyView*)controller.view;
[self.view addSubview:myview];

도움이 되길 바랍니다.

명확화:

UIViewControllerxib 및 View를 로드하는 데 사용됩니다.UIViewController하스는 사실MyViewMyView xib에 할당한 파일입니다.

데모 여기서 데모를 해봤습니다.

2년 후에 여기서 내 질문에 답하는 건...

프로토콜 확장자를 사용하기 때문에 모든 클래스에 별도의 코드 없이 할 수 있습니다.

/*

Prerequisites
-------------
- In IB set the view's class to the type hook up any IBOutlets
- In IB ensure the file's owner is blank

*/

public protocol CreatedFromNib {
    static func createFromNib() -> Self?
    static func nibName() -> String?
}

extension UIView: CreatedFromNib { }

public extension CreatedFromNib where Self: UIView {

    public static func createFromNib() -> Self? {
        guard let nibName = nibName() else { return nil }
        guard let view = NSBundle.mainBundle().loadNibNamed(nibName, owner: nil, options: nil).last as? Self else { return nil }
        return view
    }

    public static func nibName() -> String? {
        guard let n = NSStringFromClass(Self.self).componentsSeparatedByString(".").last else { return nil }
        return n
    }
}

// Usage:
let myView = MyView().createFromNib()

스위프트에서:

예를 들어, 사용자 지정 클래스의 이름은InfoView

처음에는 파일을 만들고,InfoView.xib그리고.InfoView.swift다음과 같이:

import Foundation
import UIKit

class InfoView: UIView {
    class func instanceFromNib() -> UIView {
    return UINib(nibName: "InfoView", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! UIView
}

그다음에File's Owner.UIViewController다음과 같이:

enter image description here

이름 바꾸기View.InfoView:

enter image description here

마우스 오른쪽 단추로 클릭File's Owner그리고 당신의 것을 연결합니다.view당신의 필드를 사용합니다.InfoView:

enter image description here

클래스 이름이 다음과 같도록 합니다.InfoView:

enter image description here

그런 다음 작업을 사용자 지정 클래스의 버튼에 문제 없이 추가할 수 있습니다.

enter image description here

그리고 이 커스텀 클래스의 용도는MainViewController:

func someMethod() {
    var v = InfoView.instanceFromNib()
    v.frame = self.view.bounds
    self.view.addSubview(v)
}

뷰 컨트롤러를 사용하여 xib를 초기화하고 viewController.view를 사용하거나 사용자가 수행한 방식으로 수행할 수 있습니다.새만 .UIView하위 클래스를 컨트롤러로 지정합니다.UIView나쁜 생각입니다.

사용자 정의 보기에서 콘센트가 없는 경우 직접 A를 사용할 수 있습니다.UIViewController초기화할 클래스입니다.

업데이트: 사용자의 경우:

UIViewController *genericViewCon = [[UIViewController alloc] initWithNibName:@"CustomView"];
//Assuming you have a reference for the activity indicator in your custom view class
CustomView *myView = (CustomView *)genericViewCon.view;
[parentView addSubview:myView];
//And when necessary
[myView.activityIndicator startAnimating]; //or stop

그렇지 않으면 주문 제작을 해야 합니다.UIViewController(출구가 적절하게 연결되도록 파일의 소유자로 만듭니다.)

YourCustomController *yCustCon = [[YourCustomController alloc] initWithNibName:@"YourXibName"].

원하는 위치에 사용할 수 있는 뷰를 추가할 수 있습니다.

[parentView addSubview:yCustCon.view];

그러나 xib를 로드하는 동안 다른 뷰 컨트롤러(이미 다른 뷰에 사용 중임)를 소유자로 전달하는 것은 컨트롤러의 뷰 속성이 변경되고 원래 뷰에 액세스하려는 경우 참조가 없기 때문에 좋지 않습니다.

편집: 파일 소유자와 동일한 메인으로 새 xib을 설정한 경우 이 문제가 발생합니다.UIViewController클래스 및 뷰 속성을 새 xib 뷰에 연결했습니다.

즉,

  • MainView Controller -- manages -- mainView
  • CustomView - 필요한 경우 xibas에서 로드해야 합니다.

아래 코드는 나중에 혼동을 일으킬 것입니다. 만약 당신이 그것을 인사이드 뷰로 작성한다면 로드가 된 것입니다.YourMainViewController. 그 이유는self.view이 시점부터 사용자 정의 보기를 참조합니다.

-(void)viewDidLoad:(){
  UIView *childView= [[[NSBundle mainBundle] loadNibNamed:@"YourXibName" owner:self options:nil] objectAtIndex:0];
}

언급URL : https://stackoverflow.com/questions/15405916/correct-way-to-load-a-nib-for-a-uiview-subclass

반응형