Search code examples
iosuser-interfaceaudiocarplay

Adding UI for CarPlay audio app


I am adding a list (tableview) in my CarPlay audio app. In AppDelegate.m, I have

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ..........

    [MPPlayableContentManager sharedContentManager].dataSource = self;
    [MPPlayableContentManager sharedContentManager].delegate = self;

    return YES;
}

I also implemented MPPlayableContentDataSource methods in AppDelegate.m:

- (NSInteger)numberOfChildItemsAtIndexPath:(NSIndexPath *)indexPath
{
    switch (indexPath.row)
    {
        case 0:
            return 3;

        case 1: 
            return 2;

        default:
            return 4;
    }
}

- (MPContentItem *)contentItemAtIndexPath:(NSIndexPath *)indexPath
{
    MPContentItem *contentItem = [[MPContentItem alloc] initWithIdentifier:@"container"];
    .................

    return contentItem;
}

However, the app crashes at switch (indexPath.row) and says 'Invalid index path for use with UITableView. Index paths passed to table view must contain exactly two indices specifying the section and row. Please use the category on NSIndexPath in UITableView.h if possible.' Did I do anything wrong here? Thanks in advance.


Solution

  • MPPlayableContentDataSource uses NSIndexPath differently than UITableView. For indexPath.row to work indexPath has to contain exactly 2 elements but numberOfChildItemsAtIndexPath: can be called with indexPath consisting of 0 to 5 elements - that's why your code crashes

    numberOfChildItemsAtIndexPath: in general should describe your navigation tree - provided indexPath to a specific node in your navigation it should return number of nodes to which you can navigate from this node

    Some way to fix your code would be:

    - (NSInteger)numberOfChildItemsAtIndexPath:(NSIndexPath *)indexPath {
        if (indexPath.length == 0) {
            // In a root of our navigation we have 3 elements
            return 3;
        }
        if (indexPath.length == 1) {
            switch ([indexPath indexAtPosition:0]) {
                case 0:
                    // After tapping first item on our root list we see list with 3 elements
                    return 3;
                case 1:
                    // for second one we get list with 2 elements
                    return 2;
                default:
                    return 4;
            }
        }
        return 0;
    }
    

    I recommend watching WWDC video "Enabling Your App for CarPlay", especially from 6:00 where they show nice example.