objective-c - 차이 - 유니티 ios 구글 로그인




스토리 보드에서 여러 컨트롤러와 함께 사용할 사용자 정의 셀을 만들려면 어떻게해야합니까? (4)

BJ Homer는 무슨 일이 벌어지고 있는지에 대해 훌륭한 설명을 해주었습니다.

실용적인 견지에서 볼 때 xib로 셀을 가질 수없고 segues를 연결할 수 없다는 점을 감안할 때 선택할 수있는 가장 좋은 방법은 셀을 xib로 가져 오는 것입니다 - 전환은 여러 위치의 셀 레이아웃 및 속성보다 유지 관리가 훨씬 쉽습니다. 어쨌든 당신의 각기 다른 컨트롤러와 다를 수 있습니다. Segue를 테이블 뷰 컨트롤러에서 다음 컨트롤러로 직접 정의하고 코드로 수행 할 수 있습니다. .

추가 메모는 별도의 xib 파일로 귀하의 셀을 갖는 것은 당신이 직접 테이블 뷰 컨트롤러에 어떤 동작 등을 연결할 수 없다는 것입니다. (어쨌든이 작업을하지는 못했지만 - 파일 소유자를 의미있는 것으로 정의 할 수는 없습니다 ). 이 문제를 해결하기 위해 셀의 테이블 뷰 컨트롤러가 준수해야하는 프로토콜을 정의하고 컨트롤러를 cellForRowAtIndexPath의 대리자와 비슷한 약한 속성으로 추가합니다.

내가 작업중인 앱에서 스토리 보드를 사용하려고합니다. 앱에는 목록사용자가 있고 각각에는 다른 목록 (목록의 구성원 목록, 사용자가 소유 한 목록)이 포함되어 있습니다. 따라서 ListCellUserCell 클래스가 있습니다. 목표는 앱을 통해 다시 사용할 수 있도록하는 것입니다 (즉, 내 Tableview 컨트롤러에서).

그것이 내가 문제에 부딪히는 곳입니다.

스토리 보드에서 모든 뷰 컨트롤러에서 재사용 할 수있는 사용자 정의 테이블 뷰 셀을 만드는 방법은 무엇입니까?

지금까지 시도한 구체적인 것들이 있습니다.

  • 컨트롤러 # 1에서 프로토 타입 셀을 추가하고, 클래스를 UITableViewCell 서브 클래스로 설정하고, 재사용 ID를 설정하고, 레이블을 추가하고이를 클래스의 콘센트에 연결합니다. 컨트롤러 # 2에서 빈 프로토 타입 셀을 추가하고 같은 클래스로 설정하고 이전과 같이 ID를 다시 사용합니다. 셀이 실행되면 컨트롤러 # 2에 셀이 표시 될 때 레이블이 나타나지 않습니다. 컨트롤러 # 1에서 잘 작동합니다.

  • 다른 NIB에있는 각 세포 유형을 설계하고 적절한 세포 등급까지 배선합니다. 스토리 보드에서 비어있는 프로토 타입 셀을 추가하고 클래스를 설정하고 ID를 사용하여 셀 클래스를 참조합니다. 컨트롤러의 viewDidLoad 메서드에서 재사용 ID에 해당 NIB 파일을 등록했습니다. 그림에서 두 컨트롤러의 셀은 프로토 타입처럼 비어 있습니다.

  • 두 컨트롤러의 프로토 타입을 비워두고 클래스를 설정하고 ID를 셀 클래스에 재사용합니다. 셀의 UI를 코드로 작성했습니다. 셀은 모든 컨트롤러에서 완벽하게 작동합니다.

두 번째 경우에는 프로토 타입이 항상 NIB보다 우선시되고, 프로토 타입 셀을 죽인 경우 재사용 ID를 위해 내 NIB를 등록하면 작동 할 것으로 예상됩니다. 그렇지만 셀에서부터 다른 프레임으로 세그 (segues)를 설정할 수는 없으므로 스토리 보드 사용의 요점입니다.

하루가 끝나면 스토리 보드에서 테이블 뷰 기반 흐름을 연결하고 코드보다는 셀 레이아웃을 시각적으로 정의합니다. 나는 지금까지 그 두 가지를 모두 얻는 방법을 볼 수 없다.


BJ Homer의 위대한 대답에도 불구하고 나는 해결책이있는 것처럼 느낍니다. 나의 테스트가 진행되는 한, 그것은 효과적이다.

개념 : xib 셀에 대한 사용자 정의 클래스를 만듭니다. 여기에서 터치 이벤트를 기다리고 프로그래밍 방식으로 섹그를 수행 할 수 있습니다. 이제 Segue를 수행하는 컨트롤러에 대한 참조 만 있으면됩니다. 내 솔루션은 tableView:cellForRowAtIndexPath: 에서 설정하는 것입니다.

여러 테이블 뷰에서 사용하고자하는 테이블 셀을 포함하는 DetailedTaskCell.xib 가 있습니다.

해당 셀에 대한 TaskGuessTableCell 클래스가 있습니다.

이것은 마술이 일어나는 곳입니다.

// TaskGuessTableCell.h
#import <Foundation/Foundation.h>

@interface TaskGuessTableCell : UITableViewCell
@property (nonatomic, weak) UIViewController *controller;
@end

// TashGuessTableCell.m
#import "TaskGuessTableCell.h"

@implementation TaskGuessTableCell

@synthesize controller;

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSIndexPath *path = [controller.tableView indexPathForCell:self];
    [controller.tableView selectRowAtIndexPath:path animated:NO scrollPosition:UITableViewScrollPositionNone];
    [controller performSegueWithIdentifier:@"FinishedTask" sender:controller];
    [super touchesEnded:touches withEvent:event];
}

@end

나는 여러 개의 Segues를 가지고 있지만 모두 같은 이름을 가지고 있습니다 : "FinishedTask" . 여기서 유연해야하는 경우 다른 속성을 추가하는 것이 좋습니다.

ViewController는 다음과 같습니다.

// LogbookViewController.m
#import "LogbookViewController.h"
#import "TaskGuessTableCell.h"

@implementation LogbookViewController

- (void)viewDidLoad
{
    [super viewDidLoad]

    // register custom nib
    [self.tableView registerNib:[UINib nibWithNibName:@"DetailedTaskCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"DetailedTaskCell"];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    TaskGuessTableCell *cell;

    cell = [tableView dequeueReusableCellWithIdentifier:@"DetailedTaskCell"];
    cell.controller = self; // <-- the line that matters
    // if you added the seque property to the cell class, set that one here
    // cell.segue = @"TheSegueYouNeedToTrigger";
    cell.taskTitle.text  = [entry title];
    // set other outlet values etc. ...

    return cell;
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([[segue identifier] isEqualToString:@"FinishedTask"])
    {
        // do what you have to do, as usual
    }

}

@end

동일한 것을 달성하는 더 우아한 방법이 있을지도 모르다 - 그것은 작동한다! :)


내가 이해함에 따라, 당신은 다음과 같이하고 싶습니다.

  1. 여러 스토리 보드 장면에서 사용할 수있는 IB로 셀을 디자인하십시오.
  2. 셀이있는 장면에 따라 해당 셀에서 고유 한 스토리 보드 구성을 구성합니다.

불행히도 현재로서는이 방법이 없습니다. 이전 시도가 실패한 이유를 이해하려면 스토리 보드 및 프로토 타입 표보기 셀이 작동하는 방식에 대해 더 이해해야합니다. (이 다른 시도가 왜 효과 가 없는지 신경 쓰지 않는다면 지금 당장 떠나주세요. 버그를 제기하는 것 이외에는 마법의 해결 방법이 없습니다.)

스토리 보드는 본질적으로 .xib 파일 모음이 아닙니다. 스토리 보드에서 프로토 타입 셀을 가진 테이블 뷰 컨트롤러를로드하면 다음과 같은 결과가 발생합니다.

  • 각각의 프로토 타입 셀은 실제로 자체 임베디드 미니 펜촉입니다. 따라서 테이블 뷰 컨트롤러가로드 될 때 프로토 타입 셀의 닙과 호출을 따라 실행됩니다. -[UITableView registerNib:forCellReuseIdentifier:] .
  • 표보기는 컨트롤러에 셀을 요청합니다.
  • 아마도 -[UITableView dequeueReusableCellWithIdentifier:] 호출 할 것입니다 -[UITableView dequeueReusableCellWithIdentifier:]
  • 주어진 재사용 식별자가있는 셀을 요청하면, 등록 된 nib가 있는지 여부를 확인합니다. 이 경우 해당 셀의 인스턴스를 인스턴스화합니다. 이것은 다음 단계로 구성됩니다.

    1. 세포의 펜촉에 정의 된대로 세포의 클래스를보십시오. [[CellClass alloc] initWithCoder:] 호출하십시오.
    2. -initWithCoder: 메소드는 하위 뷰를 추가하고 펜촉에 정의 된 속성을 설정합니다. ( IBOutlet 아마도 테스트를 거치지 않았지만 아마 여기에 -awakeFromNib 수도 있으며, -awakeFromNib 에서 발생할 수 있습니다)
  • 원하는대로 셀을 구성합니다.

여기에서 주목해야 할 중요한 점은 셀 클래스 와 셀의 시각적 모양 이 구별된다는 것입니다. 동일한 클래스의 두 개의 별도 프로토 타입 셀을 만들 수 있지만 하위 뷰는 완전히 다르게 배치됩니다. 사실, 기본 UITableViewCell 스타일을 사용하는 경우 이것이 정확히 일어납니다. 예를 들어, "Default"스타일과 "Subtitle"스타일은 모두 동일한 UITableViewCell 클래스로 표현됩니다.

중요 : 셀 클래스 에는 특정 뷰 계층 구조 와 일대일 상관 관계가 없습니다. 뷰 계층 구조는이 특정 컨트롤러에 등록 된 프로토 타입 셀의 내용으로 완전히 결정됩니다.

또한 셀의 재사용 식별자가 일부 전역 셀 관리 시스템에 등록되지 않았 음을 유의하십시오. 재사용 식별자는 단일 UITableView 인스턴스의 컨텍스트 내에서만 사용됩니다.

이 정보를 바탕으로 위의 시도에서 어떤 일이 발생했는지 살펴 보겠습니다.

컨트롤러 # 1에서 프로토 타입 셀을 추가하고, 클래스를 UITableViewCell 서브 클래스로 설정하고, 재사용 ID를 설정하고, 레이블을 추가하고이를 클래스의 콘센트에 연결합니다. 컨트롤러 # 2에서 빈 프로토 타입 셀을 추가하고 같은 클래스로 설정하고 이전과 같이 ID를 다시 사용합니다. 셀이 실행되면 컨트롤러 # 2에 셀이 표시 될 때 레이블이 나타나지 않습니다. 컨트롤러 # 1에서 잘 작동합니다.

이것은 예상된다. 두 셀이 같은 클래스를 가졌지 만 컨트롤러 # 2의 셀로 전달 된 뷰 계층 구조에는 서브 뷰가 전혀 없습니다. 그래서 여러분은 빈 셀을 얻었습니다. 이것은 여러분이 프로토 타입에 넣은 것입니다.

다른 NIB에있는 각 세포 유형을 설계하고 적절한 세포 등급까지 배선합니다. 스토리 보드에서 비어있는 프로토 타입 셀을 추가하고 클래스를 설정하고 ID를 사용하여 셀 클래스를 참조합니다. 컨트롤러의 viewDidLoad 메서드에서 재사용 ID에 해당 NIB 파일을 등록했습니다. 그림에서 두 컨트롤러의 셀은 프로토 타입처럼 비어 있습니다.

다시 말하지만, 이것은 예상됩니다. 재사용 식별자는 스토리 보드 장면이나 닙에서 공유되지 않으므로 이러한 모든 별개 셀에 동일한 재사용 식별자가 있다는 사실은 의미가 없습니다. Tableview에서 가져온 셀은 스토리 보드의 장면에서 프로토 타입 셀과 일치하는 모양을 갖습니다.

이 솔루션은 거의 비슷했습니다. 언급했듯이, 당신은 방금 프로그래밍 방식으로 -[UITableView registerNib:forCellReuseIdentifier:] 호출하여 셀을 포함하는 UINib 를 전달하면 같은 셀로 되돌아 갈 수 있습니다. (이것은 프로토 타입이 펜촉을 "오버라이드"했기 때문에가 아니라 펜촉을 펜 테이블에 등록하지 않았기 때문에 여전히 스토리 보드에있는 펜촉을보고있었습니다.) 불행히도이 접근법에는 결함이 있습니다. 독립 실행 형 펜촉의 셀에 스토리 보드 단을 연결할 수있는 방법이 없습니다.

두 컨트롤러의 프로토 타입을 비워두고 클래스를 설정하고 ID를 셀 클래스에 재사용합니다. 셀의 UI를 코드로 작성했습니다. 셀은 모든 컨트롤러에서 완벽하게 작동합니다.

당연히. 바라기를, 이것은 놀랄 일이 아닙니다.

그래서 그것이 작동하지 않는 이유입니다. 독립형 펜촉으로 셀을 디자인하고 여러 스토리 보드 장면에서 사용할 수 있습니다. 현재 스토리 보드 단편을 해당 셀에 연결할 수 없습니다. 다행히도, 당신은 이것을 읽는 과정에서 뭔가를 배웠습니다.


동일한 VC에 대해 셀을로드하는 방법을 찾았습니다. 단조로 테스트하지 않았습니다. 이 방법은 별도의 펜촉으로 셀을 만드는 방법입니다.

하나의 VC와 2 개의 테이블이 있고 스토리 보드에 셀을 디자인하고 두 테이블 모두에서 사용하고자한다고 가정 해 보겠습니다.

(예 : 결과에 대한 테이블이있는 UISearchController가있는 검색 필드 및 검색 필드이며 두 셀에서 동일한 셀을 사용하려는 경우)

컨트롤러가 셀을 요구하면 다음을 수행하십시오.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString * identifier = @"CELL_ID";

    ContactsCell *cell = [self.YOURTABLEVIEW dequeueReusableCellWithIdentifier:identifier];
  // Ignore the "tableView" argument
}

스토리 보드에서 셀을 가져 왔습니다.





storyboard