2011-12-31 25 views
6

Tôi gặp sự cố khi sử dụng chức năng Lion mới để sắp xếp lại các hàng trong ứng dụng của mình. Tôi đang sử dụng outlineView:pasteboardWriterForItem: để lưu trữ các chỉ mục hàng để tôi có thể truy cập chúng sau này khi tôi xác thực/chấp nhận thả. Tôi tạo ra một NSPasteboardItem mới quay trở lại, và đang cố gắng để lưu trữ các số liên tiếp như vậy:sắp xếp lại các hàng trong bảng bằng cách kéo trong Lion

[pbItem setData: [NSKeyedArchiver archivedDataWithRootObject: [NSNumber numberWithInteger: [fTableView rowForItem: item]]] 
                forType: TABLE_VIEW_DATA_TYPE]; 

TABLE_VIEW_DATA_TYPE là một chuỗi tùy chỉnh Tôi đang sử dụng để phân biệt dữ liệu tùy chỉnh của tôi trong tông kéo. Tôi không sử dụng nó bên ngoài kéo các hàng này.

Khi cố gắng kéo, tôi nhận được ở Console: 'TableViewDataType' is not a valid UTI string. Cannot set data for an invalid UTI.

Dĩ nhiên tôi có thể sử dụng một số được xây dựng trong UTIs cho pasteboards, nhưng không ai trong số họ được áp dụng (và sử dụng chúng làm cho kéo để chấp nhận kéo khác so với các hàng, mà nó không nên). Có một cái gì đó tôi đang thiếu, giống như một cách để xác định một UTI tùy chỉnh chỉ để kéo (mà không làm cho nó một "thực" UTI vì tôi không sử dụng nó bên ngoài kéo nội bộ, vì vậy nó không nên được công khai).

Cảm ơn bạn đã trợ giúp!

Trả lời

2

Thay vì sử dụng vanilla NSPasteboardItem, bạn nên tạo đối tượng tùy chỉnh phù hợp với giao thức NSPasteboardWriting.

Trong đối tượng tùy chỉnh của mình, bạn có thể triển khai writableTypesForPasteboard: để trả về danh sách các UTI tùy chỉnh mà mục trong bảng của bạn hỗ trợ. Sau đó, bạn triển khai pasteboardPropertyListForType: để trả về đại diện chính xác đối tượng của mình cho UTI tùy chỉnh thích hợp khi bảng yêu cầu yêu cầu.

Bạn có thể tạo một plist từ dữ liệu tùy ý bằng cách sử dụng phương thức +propertyListWithData:options:format:error: của NSPropertyListSerialization.

Sau đó, bạn sẽ ghi đè tableView:pasteboardWriterForRow: trong nguồn dữ liệu chế độ xem bảng của mình để trả về phiên bản của đối tượng tùy chỉnh của bạn.

+1

Cảm ơn, tôi đánh giá cao phản hồi. Tôi vẫn thực sự ngạc nhiên rằng nó rất phức tạp để chỉ theo dõi các hàng được sắp xếp lại. – livings124

+0

Tôi đã triển khai một đối tượng phù hợp với 'NSPasteboardWriting' trả về UTI tùy chỉnh của tôi cho' writableTypesForPasteboard: ', nhưng tôi nhận được: _'TableViewDataType 'không phải là chuỗi UTI hợp lệ. Không thể sử dụng một UTI không hợp lệ như một kiểu được trả về từ -writeableTypesForPasteboard: trong lớp TableViewDragNode._ – livings124

+0

Nếu đó là trường hợp thì tôi không nghĩ bạn có bất kỳ tùy chọn nào khác ngoài việc khai báo một UTI tùy chỉnh cho các hoạt động kéo của bạn trong Info.plist của bạn. Tôi đồng ý, điều này có vẻ là một giới hạn kỳ lạ. Tôi không tin rằng nó có thể xác định một UTI trong thời gian chạy, nó phải được mã hóa cứng trong Info.plist. –

5

Một kỹ thuật khác mà bạn có thể sử dụng là chỉ lưu trữ các chỉ mục của các đối tượng bạn đang kéo trong một biến mẫu ở bên cạnh. Đặt tất cả mọi thứ trên các tấm bảng là không cần thiết, trừ khi bạn đang chấp nhận các mục từ một ứng dụng khác hoặc ngược lại.

  1. Trong awakeFromNib, đăng ký cho NSStringPboardType.
  2. Trong… pasteboardWriterForRow, trả về [Chuỗi NSString].
  3. Trong… kéoSession: willBegin…, đặt biến mẫu của bạn thành chỉ mục bạn muốn theo dõi.
  4. Trong xác thựcDrop, trả về NSDragOperationNone nếu biến mẫu của bạn là 0 hoặc không phải của bạn.
  5. Trong… kéoSession: đã kết thúc…, không đưa ra biến mẫu của bạn.

Hy vọng rằng sẽ giúp ... Tôi đang sử dụng kỹ thuật cho chế độ xem bảng, nhưng nó sẽ hầu như giống hệt nhau cho chế độ xem phác thảo.

6

Tôi có các yêu cầu tương tự trừ khi tôi có một mạng lưới các đối tượng mà tôi muốn sắp xếp lại bằng cách kéo các đối tượng đã chọn đến vị trí mới.Có một số cách để thực hiện việc này, bao gồm tạo đối tượng tùy chỉnh và triển khai các giao thức NSPasteboardWritingNSPasteboardReading, (và NSCoding giao thức nếu bạn sẽ đọc dữ liệu dưới dạng NSPasteboardReadingAsKeyedArchive), nhưng điều này có vẻ là quá mức cần thiết cho việc kéo các đối tượng nằm bên trong ứng dụng.

Điều tôi đã làm liên quan đến việc sử dụng NSPasteboardItem làm trình bao bọc với loại UTI tùy chỉnh (nó đã triển khai các giao thức NSPasteboardWritingNSPasteboardReading). Đầu tiên khai báo một tùy chỉnh UTI loại:

#define kUTIMyCustomType @“com.mycompany.MyApp.MyCustomType”

này cần phải được xác định trong định dạng ‘com.domain.MyApp’ nếu không bạn sẽ nhận được các lỗi có dạng: “XXX không phải là một chuỗi UTI hợp lệ. Không thể đặt dữ liệu cho một UTI không hợp lệ. ”Apple đề cập đến điều này trong tài liệu của họ.

Sau đó, bạn phải đăng ký loại UTI tùy chỉnh này trong chế độ xem mà việc kéo của bạn sẽ xảy ra. Điều này có thể được thực hiện trong thời gian chạy và không yêu cầu bất kỳ bổ sung nào .plist. Trong phương pháp init xem của bạn thêm dòng sau:

[self registerForDraggedTypes:[NSArray arrayWithObjects:(NSString *)kUTIMyCustomType, nil]]; 

Bây giờ, hãy chắc chắn rằng các đại biểu được thiết lập cho quan điểm này, và các đối tượng delegate thực hiện các yêu cầu NSDraggingSourceNSDraggingDestination phương pháp giao thức. Điều này sẽ cho phép bạn tránh phá vỡ mẫu thiết kế MVC, bằng cách cho phép đối tượng điều khiển được chỉ định xử lý việc đặt dữ liệu trên bảng thông báo có khả năng liên quan đến truy vấn dữ liệu mô hình (tức là, chỉ mục).

Cụ thể, để đặt trên kéo tông các chỉ số của các đối tượng được di chuyển khi kéo bắt đầu như NSPasteboardItem giấy gói dữ liệu chỉ số của bạn:

- (void) draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint 
{ 
    NSPasteboard * pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; 
    [pboard clearContents]; 

    NSMutableArray * selectedIndexes = [NSMutableArray array]; 

    // Add NSString indexes for dragged items to pasteboard in NSPasteboardItem wrappers. 
    for (MyModel * myModel in [self selectedObjects]) 
    { 
     NSPasteboardItem * pasteboardItem = [[[NSPasteboardItem alloc] init] autorelease]; 
     [pasteboardItem setString:[NSString stringWithFormat:@"%@", [myModel index]] 
         forType:kUTIMyCustomType]; 
     [selectedIndexes addObject:pasteboardItem]; 
    } 

    [pboard writeObjects:selectedIndexes]; 
} 

Và khi thao tác kéo hoàn tất, để đọc các chỉ số kéo NSPasteboardItem dữ liệu:

- (BOOL) performDragOperation:(id <NSDraggingInfo>)sender 
{ 
    NSPasteboard * pasteboard = [sender draggingPasteboard]; 

    // Check for custom NSPasteboardItem's which wrap our custom object indexes. 
    NSArray * classArray = [NSArray arrayWithObject:[NSPasteboardItem class]]; 
    NSArray * items = [pasteboard readObjectsForClasses:classArray options:[NSDictionary dictionary]]; 

    if (items == nil) 
     return NO; 

    // Convert array of NSPasteboardItem's with NSString index reps. to array of NSNumber indexes. 
    NSMutableArray * indexes = [NSMutableArray array]; 
    for (NSPasteboardItem * item in items) 
     [indexes addObject:[NSNumber numberWithInteger:[[item stringForType:kUTIMyCustomType] integerValue]]]; 

    // 
    // Handle dragged indexes… 
    // 

    return YES; 
} 
Các vấn đề liên quan