Three20: как передать класс объектов между двумя представлениями - PullRequest
7 голосов
/ 16 октября 2010

У меня есть TTableView. Элементы в этой таблице сопоставлены с URL-адресом, поэтому при нажатии на элемент появляется другое представление с информацией об этом элементе. Все эти данные являются атрибутами класса. Итак, как я могу создать свой URL TTableTextItem для передачи класса, содержащего информацию, представлению, ответственному за отображение этой информации?

Заранее спасибо.

Ответы [ 4 ]

13 голосов
/ 17 октября 2010

Один из способов сделать это - использовать TTURLAction. Когда пользователь выбирает строку в вашей таблице, которая вызовет ваш метод didSelectObject (из TTTableViewController), извлеките объект или набор объектов, которые вы хотите передать, и создайте действие TTURLAction следующим образом:

TTURLAction *action =  [[[TTURLAction actionWithURLPath:@"tt://showUser"] 
    applyQuery:[NSDictionary dictionaryWithObject:user forKey:@"kParameterUser"]]
            applyAnimated:YES];

Затем откройте действие:

[[TTNavigator navigator] openURLAction:action];

Контроллер, который вы хотите открыть в результате этого действия, должен быть зарегистрирован в вашем TTURLMap и иметь конструктор таким образом:

- (id) initWithNavigatorURL:(NSURL*)URL query:(NSDictionary*)query {
    self = [super init];
    if (self != nil) {
        self.user = [query objectForKey:kParameterUser];
    }
    return self;
}

Я склонен создавать категории для классов, для которых я хочу иметь возможность открывать другой контроллер и отображать себя.

6 голосов
/ 24 октября 2010

Большая проблема с прямым использованием TTURLAction заключается в том, что вы не можете использовать их с TTTableViewItem.Единственный способ сделать это - переопределить -didSelectObject:atIndexPath: и создать свой собственный TTURLAction с нужным объектом в словаре query.Но это нарушает хорошее разделение между Model и View Controller и усложняется, когда вам нужно передать несколько объектов.

Вместо этого я использовал небольшую категорию, которая автоматически принимает свойство userInfoэлемент таблицы (который я установил на все, что мне нужно), и автоматически добавляет его в качестве параметра URL.

И затем вы используете это для извлечения его в вашем отображённом контроллере представления.

- (id)initWithNavigatorURL:(NSURL *)URL query:(NSDictionary *)query { 
if (self = [self initWithNibName:nil bundle:nil]) {
    id myPassedObject = [query objectForKey:@"__userInfo__"];
    // do the rest of your initlization
}
return self;

}

Вы можете скачать его как GitHub Gist здесь .Код также ниже.В какой-то момент мы планируем объединить это с основной веткой.


TTTableViewDelegate + URLAdditions.h

@interface TTTableViewDelegate(URLAdditions)

@end

TTTableViewDelegate + URLAdditions.m

#import "TTTableViewDelegate+URLAdditions.h"

@implementation TTTableViewDelegate(URLAdditions)

- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
    id<TTTableViewDataSource> dataSource = (id<TTTableViewDataSource>)tableView.dataSource;
    id object = [dataSource tableView:tableView objectForRowAtIndexPath:indexPath];

    // Added section to automatically wrap up any TTTableItem userInfo objects.  If it is a dictionary, it gets sent directly
    // If it is not, it is put in a dictionary and sent as they __userInfo__ key
    if( [object isKindOfClass:[TTTableLinkedItem class]] ) {
        TTTableLinkedItem* item = object;

        if( item.URL && [_controller shouldOpenURL:item.URL] ) {
            // If the TTTableItem has userInfo, wrap it up and send it along to the URL
            if( item.userInfo ) {
                NSDictionary *userInfoDict;

                // If userInfo is a dictionary, pass it along else create a dictionary
                if( [item.userInfo isKindOfClass:[NSDictionary class]] ) {
                    userInfoDict = item.userInfo;
                } else {
                    userInfoDict = [NSDictionary dictionaryWithObject:item.userInfo forKey:@"__userInfo__"];
                }

                [[TTNavigator navigator] openURLAction:[[[TTURLAction actionWithURLPath:item.URL]
                                                         applyQuery:userInfoDict]
                                                        applyAnimated:YES]];
            } else {
                TTOpenURL( item.URL );
            }
        }

        if( [object isKindOfClass:[TTTableButton class]] ) {
            [tableView deselectRowAtIndexPath:indexPath animated:YES];
        }
        else if( [object isKindOfClass:[TTTableMoreButton class]] ) {
            TTTableMoreButton* moreLink = (TTTableMoreButton*)object;
            moreLink.isLoading = YES;
            TTTableMoreButtonCell* cell
            = (TTTableMoreButtonCell*)[tableView cellForRowAtIndexPath:indexPath];
            cell.animating = YES;
            [tableView deselectRowAtIndexPath:indexPath animated:YES];

            if( moreLink.model )
                [moreLink.model load:TTURLRequestCachePolicyDefault more:YES];
            else
                [_controller.model load:TTURLRequestCachePolicyDefault more:YES];
        }
    }

    [_controller didSelectObject:object atIndexPath:indexPath];
}

@end
0 голосов
/ 01 февраля 2011

У меня есть немного исправить этот удивительный код :) как выложенная версия полоса обратного вызова от TTTableButton.

Исправление:

if( [object isKindOfClass:[TTTableButton class]] ) {
   if (item.delegate && item.selector) {
       [item.delegate performSelector:item.selector withObject:object];
   }
   [tableView deselectRowAtIndexPath:indexPath animated:YES];
}
0 голосов
/ 16 октября 2010

Я думаю, документация на официальном сайте очень четко описывает схему навигации для Three20. Ваш вопрос является очень распространенной задачей любого приложения, и Three20 обеспечивает мощную поддержку для этого.

...