0

我正在开发一个 TVML 应用程序。其中一个屏幕显示了供用户输入关键字的搜索表单。输入的文本将与包含现有每个项目的先前存在的 JSON 文件进行比较。在过滤可用结果后,这些用于通过使用外部 XML 文件构建 XML 节点,然后将它们导入到搜索文档中,特别是导入到 Id 为“结果”的部分。问题是,如果我直接输入搜索词,搜索就会发生。但是,如果我一个字母一个字母地输入(允许在每个字母之后进行搜索),那么应用程序就会崩溃并且我会收到以下错误:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSSingleObjectArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
terminating with uncaught exception of type NSException

(索引号和范围因结果不同而异)

以下是我目前拥有的文件:

搜索.tvml

<?xml version="1.0" encoding="UTF-8" ?>
<document>
<head>
    <style>
        .company {
            font-size: 26;
        }
    </style>
</head>
<searchTemplate>
    <searchField />
    <collectionList>
        <grid>
            <header>
                <title>Search Results</title>
            </header>
            <section id="results">
                
            </section>
        </grid>
    </collectionList>
</searchTemplate>
</document>

搜索结果.tvml

<lockup template="video.tvml" presentation="push" id="{{id}}">
    <img src="https://path_to_images/{{path}}/{{image}}.jpg" width="380" height="266" alt="{{name}}"/>
    <title>{{name}}</title>
    <subtitle class="company">{{company}}</subtitle>
</lockup>

SearchHandler.js

class SearchHandler {
    constructor(resourceLoader) {
        this._resourceLoader = resourceLoader;
        this.searchDatabase = "";
    }

    enableSearchForDoc(doc) {
        this._addSearchHandlerToDoc(doc);
    }

    _addSearchHandlerToDoc(doc) {
        var searchFields = doc.getElementsByTagName('searchField');
        for (var i = 0; i < searchFields.length; ++i) {
            var searchField = searchFields.item(i);
            var keyboard = searchField.getFeature("Keyboard");
            keyboard.onTextChange = this._handleSearch.bind(this, keyboard, doc);
        }
    }


    _handleSearch(keyboard, doc) {
    
        // Get the text entered
        var searchString = keyboard.text;
    
        // Blank results array
        var results = [];
    
        // Search only if text entered has more than one character
        if (searchString.length > 1) {
            results = this.searchVideosForString(searchString, this.searchDatabase);
        }
    
        // Get the result nodes (lockups) from the results obtained
        var resultNodes = this._renderResults(results);
    
        // Get a reference to the "results" section in search.tvml
        var resultContainer = doc.getElementById("results");
    
        // If such section exists
        if (resultContainer) {
            // remove previous results
            while (resultContainerChildren > 0 ) {
                resultContainer.removeChild(resultContainer.lastChild);
                resultContainerChildren--;
            }
        
            // Add each lockup node to the results section
            if (resultNodes.length > 0) {
                resultNodes.forEach(function(resultNode) {
                    doc.adoptNode(resultNode);
                    resultContainer.appendChild(resultNode);
                });
            }
        }
    }

    _renderResults(results) {
        var resourceLoader = this._resourceLoader;
    
        // Get an XML node (lockup) for each of the results found
        // Results will be used as data for the XML
        var rendered = results.map(function(result) {
            var doc = resourceLoader.getRenderedDocument("searchResults.tvml", result);
            return doc.documentElement;
        });
    
        // Return the array of lockup nodes
        return rendered;
    }

    searchVideosForString(searchString, data) {
        var sourceData = data;
    
        var results = []
    
        results = sourceData.filter(function(v) {
            var title = v.name;
            var show = v.showname;
            var company = v.company;
                                    
            return title.toLowerCase().includes(searchString.toLowerCase()) || show.toLowerCase().includes(searchString.toLowerCase()) || company.toLowerCase().includes(searchString.toLowerCase())
        });

        console.log("SEARCH RESULTS: ", results);

        return results;
    }
}

我一直在使用 Safari 控制台监视 searchVideosForString 方法的结果,我发现,例如,如果我尝试搜索存在于完整结果中的“Parry”,如果我输入单词“Par ",控制台为搜索结果显示一个包含 18 个对象的数组。如果我打开显示三角形,它会显示这 18 个对象中的每一个。如果我在搜索中添加一个字符来查找“Parr”,那么应用程序就会崩溃。控制台为搜索结果显示一个包含 1 个对象的数组,但如果我打开显示三角形,它是空的,我看不到实际对象是什么。

我尝试在 handleSearch 方法中删除部分代码。如果我删除下面的所有内容

var resultContainer = doc.getElementById("results");

然后我可以在搜索框中输入任何文本而不会出现任何问题,并且控制台会显示适当的搜索结果,无论它们有多少。

似乎问题发生在这一行:

doc.adoptNode(resultNode);

但我无法弄清楚索引超出范围异常的原因和来源。

4

0 回答 0