说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Apple TV指南:从零开始用Swift开发个tvOS应用

HTML文档下载 WORD文档下载 PDF文档下载
这篇文章主要介绍了如何在Apple TV上开发一个名为tvOS的App,以及关于tvOS的一些相关的定义,最终呈现给用户一个非常有趣的界面。

本文出自:Jameson Quave's Blog,作者:Jameson Quave,译文出自:SwiftGG,译者:ray16897188

 

教程结束时,我们会做出这样一个应用:


你更喜欢哪个艺术家?

第一部分

开始

在我们开始之前你需要安装 Xcode 7.1 beta 版,可以从这里下载:下载 Xcode 7.1 Beta。

注意:下载 Xcode 7.1 Beta需要有一个苹果开发者账号,由于目前 Xcode 是预发行版,以后正式发布的时候可能会有变化。
安装的时候要注意,如果你重命名Xcode7.1应用,会遇到一个已知Bug。一定有人会这么做,所以提前说明……别这么做,否则你的tvOS模拟器会崩溃。

同时要注意,虽然支持优胜美地 (Yosemite),但是在该操作系统上,功能会受限。推荐用 OSX 10.11 El Capitan 或更新的系统。ElCapitan beta可以在这里下载。

下面我们来介绍一些 tvOS 相关的定义。

TVMLKit

TVMLKit 是 Apple 设计的一个新框架,能在使用 Swift 或 Objective-C 实现应用逻辑的同时使用 Javascript 和 XML 开发更炫酷的用户界面。

TVML

TVML 是“TV Markup Language”(TV 标记语言)的缩写,基本上是一些 XML 语句,用于实现基于C/S(client-server,客户端-服务端)架构的 tvOS 应用布局。布局界面时,我们会用到一些 Apple 提供的 TVML 模板创建我们的 UI,然后用 TVJS 写交互脚本。

TVJS

我能告诉你的是,TVJS 就是你(可能已经)熟悉的 JavaScript。

Hello World

我们从一个基本的 hello world 程序开始。就 Apple TV 而言,我们可以只把"Hello World"输出到控制台上。这也许是个不错的开始,但更好的选择是使用 Apple TV 的一些 TVMLKit 元素在屏幕上创建一个模板。

首先,打开 Xcode 7.1 并创建一个新项目。你可以看到一个模板列表,我们在左侧选择CHANGE tvOS,然后再选Single View Application模板。

这样就会根据 tvOS 模板创建一些默认文件和一个简单的 Swift 入口点,对一会儿创建 UI 很有帮助。

建立 TVJS 主文件

在 C/S 架构的 tvOS 应用中,服务端本质上就是 TVML 和 JavaScript 文件以及和它们相关的所有数据。JavaScript 文件会装载 TVML 并把页面(page)放入视图栈中。可以从另一个角度理解:JavaScript 文件就像 TVML 文件的路由器或是控制器(controller),而 TVML 文件本质上是若干视图(views)。

拉开序幕

首先我们要修改应用的AppDelegate.swift文件。第一步是让我们的应用遵循TVApplicationControllerDelegate协议。该协议定义在 TVMLKit 框架中,所以需要导入它。更新AppDelegate.swift文件,如下所示:

import TVMLKitclass AppDelegate: UIResponder,UIApplicationDelegate,TVApplicationControllerDelegate {....
此协议包含四个 tvOS 实现AppDelegate后会调用的函数,用于给我们的应用发送 tvOS 生命周期通知。现在我们无需操心这些,但在后面的教程中我们会对它们进行深入研究。目前只要像上面的代码那样把协议加进去就够了。

下一步,我们要添加一些代码,让 JS 文件起作用。由于是 beta 版,我们还需要自己完成这些工作。我相信在 Xcode 的后续版本中这一步会变成一个模板。

在程序里didFinishLaunchingWithOptions这个函数中我们要完成一些步骤。它们对所有应用来说都是一样的,所以你可以直接复制这段代码:


// 在一个可选属性中保存对 appController 的引用var appController: TVApplicationController?func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {  self.window = UIWindow(frame:UIScreen.mainScreen().bounds)  let appControllerContext = TVApplicationControllerContext()  let jsFilePath = NSURL(string: "http://localhost:8000/main.js")  let javascriptURL = jsFilePath!  appControllerContext.javaScriptApplicationURL = javascriptURL  if let options = launchOptions  {    for (kind, value) in options    {      if let kindStr = kind as? String      {        appControllerContext.launchOptions[kindStr] = value      }    }  }  self.appController = TVApplicationController(context: appControllerContext, window: self.window, delegate: self)  return true}

简单说说这段代码干了什么:它拿到了一个TVApplicationControllerContext引用,这个Context只是为我们的AppDelegate类提供了一些启动数据,然后给了我们一个能调整和修改启动过程的接口。接着把URL 传给待会儿要运行的main.js文件,并将appController的路径设置成这个 URL。

现在就要添加我们的 JavaScript 文件了,点击 File > New,然后在 iOS tab 下面选择 Other >Empty file。将这个文件命名为main.js。

用同样方法创建一个hello.tvml文件。

在main.js文件中添加一些简单的 JavaScript 代码,用来装载hello.tvml文件:

function getDocument(url) {  var templateXHR = new XMLHttpRequest();  templateXHR.responseType = "document";  templateXHR.addEventListener("load", function() {pushDoc(templateXHR.responseXML);}, false);  templateXHR.open("GET", url, true);  templateXHR.send();  return templateXHR;}function pushDoc(document) {  navigationDocument.pushDocument(document);}App.onLaunch = function(options) {  var templateURL = 'http://localhost:8000/hello.tvml';  getDocument(templateURL);}App.onExit = function() {  console.log('App finished');}
现在在hello.tvml文件中添加:

<document>  <alertTemplate>      <title>Hello tvOS!</title>  </alertTemplate></document>

TVML 文件是 UI 的实际内容。文档(document)必须用模板编写,否则现在的代码运行时会崩溃。这个 TVML 文件只是包含了一个简单的模板和一个单元素的标题。

在编写这些代码时我发现一个问题:本地无法引用这些文件,文件必须放在一个 web 服务器上。所以最简单的解决方案是找到你刚创建 TVML 和JS 文件的位置,并在命令行中敲进如下指令:

启动服务端

python -m SimpleHTTPServer 8000

这条指令用 Mac OS 内建的 python 解释器开启了一个端口号为 8000 的 web 服务器,可以用它来托管本地文件。如果在命令行中,执行了上面给出的代码,那么现在按一下Xcode 的 play 按钮就能在 tvOS 模拟器中启动了。还有一个要注意的事情:这是一个不够安全的 HTTP 请求,在 iOS 9 中会被默认的应用传输安全机制拦截。为了能够按之前的方法来使用本地主机,我们需要在Info.plist文件中添加一个key。

允许直接加载(Allows Arbitrary Loads)

选择Info.plist文件然后按加号(+)来创建一条新记录。在列表中选择”App Transport Security Settings”并按 return 建。这将创建一个新的字典条目,展开它,在这行上按加号(+)添加一个子行。接着选中”Allows Arbitrary Loads”并将其设为true。都设好了之后我们就能用模拟器运行应用了。

添加按钮

在本例中你看到的实际上是一个被 Apple 称作alertTemplate的模板。你还能嵌入一些基本控件,比如在模板中添加文字和按钮。试着添加一些按钮吧:

<document>    <alertTemplate>        <title>Hello tvOS!</title>        <button>            <text>A Button</text>        </button>        <button>            <text>A Second Button</text>        </button>    </alertTemplate></document>

这里我们只加了子按钮(child button)元素,每个子按钮都有它自己的子文本(child text)元素。这段代码在 tvOS模拟器上全屏显示alert和两个按钮。如果你自学能力很强,苹果的官方文档中列出了你能使用的所有模板和控件。

第二部分

增加交互事件

在第一部分中我们创建了一个简单的 TVML document,里面有几个按钮。这个document看起来是这样的:

<document>	<alertTemplate>		<title>Hello tvOS!</title>		<button>			<text>A Button</text>		</button>		<button>			<text>A Second Button</text>		</button>	</alertTemplate></document>
这是一个带按钮的警告(alert)界面,目前这些按钮没有任何作用。这段代码直接硬编码了具体内容,更好的方式是使用代码生成XML,在 JS 中很容易实现。我们在main.js文件中添加一个新函数,把上面的代码封装成一个更简单的警告界面,它只包含一个 OK 按钮。

function alert(str) {	var alertXMLString = `<?xml version="1.0" encoding="UTF-8" ?>	<document>		<alertTemplate>			<title>Hey Listen!</title>			<description>${str}</description>			<button>				<text>OK</text>		</button>	</alertTemplate></document>`var parser = new DOMParser();var alertDOMElement = parser.parseFromString(alertXMLString, "application/xml");navigationDocument.presentModal(alertDOMElement);}
这里创建了一个alertXMLString字符串,它表示的是包含一个按钮的简单警告界面所对应的 TVML。description节点比较特殊,我们使用TVJS 的内嵌字符串语法${variable}来插入str的值。

接下来,创建一个新的DOMParser对象,把这个字符串转换成一个实际的 XML DOM 元素。

最后,我们用navigationDocument的presentModal方法展示一个模态框,内容就是上一步的 DOM 元素。navigationDocument是一个全局变量,它永远指向XML 文档的根节点。

现在,删除onLaunch函数中之前的代码,直接调用刚才创建的函数……

App.onLaunch = function(options) {	alert("Hello!");}


Hello警告

运行应用,你会看到一个炫酷的”Hello!” tvOS 警告。但是点击 OK 没有任何反应。我们该怎么处理像触摸之类的事件呢?

通常来说,在 JavaScript 和 TVML 的世界中,你需要给 DOM 元素添加一个事件监听器(event listener)。举个例子,我们可以给alert函数添加第二个参数,把 OK 按钮触发select事件时需要调用的函数作为参数传入。下面我们就加入这个名为doneCallback的参数:

alertDOMElement.addEventListener("select", function() { doneCallback }, false);
更新后的完整函数如下:

function alert(str, doneCallback) {	var alertXMLString = `<?xml version="1.0" encoding="UTF-8" ?>	<document>		<alertTemplate>			<title>Hey Listen!</title>			<description>${str}</description>			<button>				<text>OK</text>			</button>		</alertTemplate></document>`var parser = new DOMParser();var alertDOMElement = parser.parseFromString(alertXMLString, "application/xml");alertDOMElement.addEventListener("select", doneCallback, false);navigationDocument.presentModal(alertDOMElement);}

现在我们可以修改之前的onLaunch函数,添加一个回调函数来显示一个 TVML 页面。在此之前,我们需要再添加一个getDocumentContents函数,它会在页面加载完毕之后调用回调函数。这个回调函数只有一个参数,用来接收 XMLHttpRequest 对象的响应内容。这样我们就可以轻松地加载多种 TVML 文件。 

function getDocumentContents(url, loadCallback) {	var templateXHR = new XMLHttpRequest();	templateXHR.responseType = "document";	templateXHR.addEventListener("load", function() { loadCallback(templateXHR) }, false);	templateXHR.open("GET", url, true);	templateXHR.send();	return templateXHR;}
代码和之前定义的getDocument方法几乎一样,区别是这里是异步操作,而且不会在界面上显示任何内容。 

有个这个函数,我们就能执行下面的调用,当 OK 按钮被点击时替换屏幕上的警告内容。 

App.onLaunch = function(options) {    alert("Hello!", function() {      var helloDocument = getDocumentContents("http://localhost:8000/hello.tvml", function(xhr) {        navigationDocument.dismissModal();        navigationDocument.pushDocument(xhr.responseXML);      });    });}
我们使用stackTemplate模板来改写hello.tvml文件,这样界面会更有趣。stackTemplate非常适合用来展示一组包含标题和图片的列表内容。下面是本例用到的内容:

<document>    <stackTemplate>        <banner>            <title>Which Artist Do You Prefer?</title>        </banner>        <collectionList>            <shelf>                <section>                    <lockup>                        <img src="http://localhost:8000/nina.png" width="256" height="256" />                        <title>Nina Simone</title>                    </lockup>                    <lockup>                        <img src="http://localhost:8000/coltrane.png" width="256" height="256" />                        <title>John Coltrane</title>                    </lockup>                </section>            </shelf>        </collectionList>    </stackTemplate></document>

这基本上就是stackTemplate的布局方式,banner是顶部的横幅内容,collectionList包含许多shelf对象,而shelf对象则包含许多section对象,section对象又包含许多lockup对象,最后这个才真正包含我们的图片和标题。在本例中我向目录中添加了一些图片,它们是nina.png和coltrane.png。


预告:  2015中国移动开发者大会(MDCC 2015)将于10月14日-16日在北京新云南皇冠假日酒店召开。大会特设九大技术专场:平台与技术(iOS)、平台与技术(Android)、平台与技术(跨平台)、产品与设计、游戏开发、企业移动化、虚拟现实专场、硬件开发与技术、嵌入式开发。大会将聚集国内最具实力的产品技术团队,与开发者一道进行最前沿的探讨与交流。 

第一时间掌握最新移动开发相关信息和技术,请关注mobilehub公众微信号(ID: mobilehub)。

Firefox.html:用HTML重现Firefox UI Qt 5.4正式发布!引入WP,支持HTML5混合开发 2014智能硬件盘点第二弹!这次咱走暖心的 聚合数据资产,推动产业创新——2014中关村大数据日看大数据变现 拥抱开源:微软Windows 10宣布全面支持AllJoyn技术 改变App领域发展!友盟推“数据工场”战略,两款新品亮相 Cloudera正式登陆中国市场:与英特尔携手共助本土企业淘金大数据 Go 1.4正式发布 支持Android开发 【特别提醒】2014中国大数据技术大会门票全面告罄 不接受现场购票 累计4000万美元 Qualcomm在华投资5家公司 支持Android、WatchKit开发,全新RubyMotion 3面世! 快速开发移动医疗App!开源框架mHealhDroid 2014CVW﹒产业互联网大会解密未来20年 Nimble VR的收购与一封来自友商的感言 Google Earth API将在2015年12月彻底关闭 AR、美颜、机器人:计算机视觉库几乎无所不在 不激增,无爆收,年度最佳手游为80 Days带来了什么? 《近匠》机智云CEO黄灼:跨越智能硬件的“鸿沟” 智能手机≠智能家居!我们要的究竟是什么? 亚信大数据事业部总经理张灏:打通各行业数据壁垒 让大数据变现畅通无阻 Web App和Native App不是生死之争,而是可以和平共处! 微信之父张小龙说微信坚持“去中心化”,这样真的好吗? 亚信CFO武军谈进军海外市场成功经验 前瞻性思维是开路先峰 Swift,任重而道远! DevOps系统的变迁 玩转Docker镜像 “扫描建模”速建AR应用 Vuforia 4.0 SDK更新 硅谷里的外星人:纵观Reddit十年风雨路 不见不散 Cloud Foundry Meetup活动将首次走进杭州 独立开发者:新手做2D手游该用哪些工具? 求安全化危机!Uber研发生物识别技术、聘请前亚马逊运营 连接数据库的一个参数:Initial Catalog=Music 是什么东西,在那里设置? 在DELPHI中能用ADO连接远程有固定IP的数据库服务器上的数据库吗?怎么连接? 各位兄弟姐妹,快来看呀! 请教各位大虾:我在上网的时候为什么老是死机,鼠标键盘一动不动了!!! pb中访问数据库必须通过datawindow么? 为什么就差这么一点了~???快帮帮忙啊~! OO里面的"is a"和"has a"应该如何理解啊?举个例子看看 请问在哪可以找到可以做简历封面的图片呀?后天就是招聘会啦,快快帮忙呀~~~ javaServlet的一个问题。急! DELPHI高手!-----300分 ASP开发问题,如何在用户提交注册信息时自动分配给它一个用户ID号? 我想在 Excel 中给文件字加双下划线,可是编译时提示变量没有定义 有谁能给我一份简单的COM代码? 有关interface??? 昨晚,初恋情人不经意的出现在梦中,你到底离你的初恋情人有多远,撒分了 一个昨天没搞明白的问题! redhat 7.2中如何设置代理服务器 求教高手一个Java中一直困扰我的问题,急!急!急! 谁能够给我个例子实现 Dll向应用程序单向通信 Dll->EXE?50分? 请问.......... 在数据窗口拖动垂直滚动条死机。只能ctrl+alt+del结束任务。倾听你的声音。 请教各位大虾两个Sql语句 哪里有visual studio.net下载? 那里有sql server 2000企业版下载的 xml的学习??????双儿 怎么比较两个LPTSTR字符串啊??? 语句“rs.Open sql,conn,1,1”中后边的两个数字参数是何意思? 如何获取datawindow中文本框内容? 请教公司大院网络系统设计方案要怎写?会遇到什么问题? 关于clientdataset的返回值问题 关于报表打印的问题!火急。。 这个世界上有多少C/C++程序员? 关于ARP广播域的问题????????????????、 请问什么服务器支持global.jsa 安装oracle数据库出错!!!!!!!!!!!! 如何在对话框的OnPaint()函数中得到该对话框的窗口大小? 一个看似简单却很棘手的问题,不得不请教各位。。。 哪里有将rm文件转换成avi或者mpg格式的软件? 关于ARP广播域的问题?????????????? 请问,,怎么设定mshflexgrid的属性,使其各列的宽度与数据源字段的宽度一致 请问这几个对象是否代表同一个对象? 菜鸟问题:如何跟随鼠标拉出一虚线矩形框?回复就有分! 高分寻Authorware v6.0 注册码 在数据窗口中有“部门”和“员工”两个列,分别采用各自的下拉数据窗口显示。如何使得“部门”改变时,“员工”显示与其对应的人员而不是“员工”表中所有人员。 怎样安装UNIX? 灌水加求救…… T-SQL中SELECT句中可不可以有存储过程。。。。。。。。这样为什么不行呢?(100分酬谢) MS SQL SERVER 有谁知道型号为CDU111-NE 的SONY光驱是多少速的吗? 谁对RTTTL格式文件了解,怎么把它转换成可以发送的二进制格式? 关于ORACLE存贮过程的迷惑,请各位大侠解惑! 词组加复数名词但是谓语是单数的词组有哪些?比如:a crate of oranges was sent from Florida. A lot of 后面加名词复数还是单数还是都可以?我在美式词典中看到下面解释例子windy/windi/adjectivewind·i·er; wind·i·est1:having a lot of wind▪ It's a windy day.▪ It's windy outside.▪ a windy part of the 可数名词前用了分数谓语动词用单数还是复数? 在英语中,名词可以修饰名词吗?若能,作定语的名词是单数还是复数? a lot of 后面跟(可数)名词复数,还是(可数)名词单数? a large quantity of +复数名词(可数) 谓语动词是用单数形式还是复数形式但是很多语法书上都说跟OF后的名词....想看看跟多的答案 如何用18mol/L浓硫酸溶液配制200ml 4.5mol/L稀硫酸溶液? lots of/a lot of 后面接可数名词时谓语用复数,接不可数名词时,谓语用单数.这句话举个例子 将20毫升98%的浓硫酸(1.84克/厘米³)稀释成40%的稀硫酸,问可配制多少g的稀硫酸加水多少毫升是不是126.96g,加水90.16ml 欲用18mol/L的浓硫酸配制0.5mol/L的稀硫酸500mL. (1)量取浓硫酸的体积为 mL. (2)选用的主要仪器有:烧杯欲用18mol/L的浓硫酸配制0.5mol/L的稀硫酸500mL.(1)量取浓硫酸的体积为 mL.(2)选用的主要仪器 12墙、18墙、24墙、37墙 每平方用砖及水泥砂浆的量该如何计算啊?水泥砂浆比例是如何应用的?我要加工一个护栏(动物保护协会的),底部要砌一个12的墙,同时做好焊接预埋件.12墙是不是单薄 100立方-99立方+98立方.+2立方-1立方=?希望有人知道怎么做 先用98%的浓硫酸(1.84g·cm)配制成浓度为0.5mol·l的稀硫酸500ml他问需要多少毫升浓硫酸网上说算出来都是13.6但一开始用密度乘了1.84g每cm3这是硫酸的含量对吧!为什么最后算出13.6之后不用密度倒 水泥砂浆强度计算:在配置水泥砂浆时,每立方米砂子用了强度等级为32.5的普通水泥360kg,水320kg,则此水泥砂浆的强度等级为(),书上答案为M20,求大侠给个计算过程, 1的立方十2的立方十3的立方等于36吗? 20厚1;3水泥砂浆是什么意思 水泥砂浆施工配合比怎么计算(有外加剂的).谁能给我举个例说明一下怎么计算 1立方+2立方+3立方+4立方+...+10立方 a group of people谓语 是单数还是 复数 把19.2g铜加入到100ml一定浓度的浓硫酸中,加热,待铜完全溶解后,将溶液冷却至室温,再加水稀释到200ml,此时溶液中硫酸的物质量浓度为6mol/L试求:1.反应生成的二氧化硫气体在标准状况下的体积 观察下列各式:1的立方+2的立方十3的立方十4的立方=100 =1/4x16×25=1 /4×4的观察下列各式:1的立方+2的立方十3的立方十4的立方=100=1/4x16×25=1 /4×4的立方×5的立方.若n为正整数,试猜想1的 a group of students后的be动词是复数还是单数 网上有不同的答案,请告诉我最正确的!谢谢合作!~ 将100mL98%的浓硫酸(密度为1.84g/mL)缓缓倒入100mL水中,搅拌均匀,计算所得溶液的浓度 英语中,遇到不可数名词,谓语用单数还是复数? 'a group of sth.'前或后的动词用单数还是复数! 第三人称复数后面的like要不要加s,likes后面的动词要不要加ing? 复合名词后谓语用复数还是单数 this group of students作主语谓语用单数还是复数?主谓一致到底怎么判断? like 后什么时加名词复数 like coke与like cokes的区别 any 后面的名词究竟跟复数还是单数形式?其谓语呢?感觉有时候跟可数名词有用单数,也有用复数的.请大师详细举例区分一下! 写出用18mol/L的浓硫酸来配制200ml2mol/L稀硫酸的过程 家居装饰水泥砂浆配比要达到1;3以上是什么意思? 98%的浓硫酸密度是1.84 30%的硫酸密度是1.22 求50%的硫酸密度是 关于英语的 哪些词组可接可数名词复数 哪些接不可数名词 哪些两者都可接 家装中水泥砂浆有几种配比 1的立方+2的立方+3的立方+……至十的立方,和是多少?怎么算? 谁对英语可数名词 单数如何变复数熟悉啊,分数多多的,例如,boy的复数是boys,family 的复数就是families.可数名词单数 以辅音字母y结尾的就把Y变I加ES.谁可以告诉我什么是辅音字母Y么?boys为什么 水泥砂浆配比是否要做配比我们监理在施工要求将粉刷的1:3水泥砂浆做试验有什么要求啊?就是在哪方面有规定啊? 1立方+2立方+3立方.+10立方一步一步写下来, 英语:which后面接名词的话是接单数还是复数? the加单数可数名词后的谓语动词是用单数还是复数The teacher said that the class were,in general,very bright.The teacher said that the class was more than forty in number.为什么两个句子后面的谓语动词一个是单数一 2毫升 密度为1.84克每立方厘米 质量分数是百分之九十八的浓硫酸 将它配20毫升溶液后 硫酸的物质的量浓度是 为什么a pair of sunglasses后面的谓语动词要用复数形式?RT. 单价组成里面既有1:2水泥砂浆又有1:3水泥砂浆, 单数可数名词前加the,可以用来表示一类事物.谓语动词用单数还是复数 a pair of sth.作主语时,谓语动词的单复数,由哪个词决定? 请问主语是不可数名词,谓语动词用复数形式还是单数形式?有没有例外? a large quantity of+可数名词复数 后面的谓语动词用单数还是复数 of结构(eg:a glass of water)的名词短语作主语时谓语动词的单复数形式如何确定(是单数,还是复数)随便举个例子:a pair of glasses/two pairs of glassesa cup of tea/two cups of tea 请说一下这两队例子的 英语中分数做主语谓语动词用单数还是复数About three-fourths of the surface of the earth_____covered by the sea.这个空填什么?希望说清楚一点,为什么要填这个答案? 实验室要用质量分数为98%的浓硫酸(密度为1.84G/CM^3)配制质量分数为20%的稀硫酸250ML(密度为1.14G/CM^3)1.250ML质量分数为20%稀硫酸中硫酸的质量?2.需要质量分数为98%的浓硫酸多少毫升?需要加水 a pair / a piece of 后面跟的名词是复数形式吗?a pair of shoes a pair of trousers那 a piece of clothes 这里clothes 是衣服的意思.名词. 这里算算复数那? clothes 后面的谓语动词 应该是is / are?谢谢2.a pair of jea 可数名词和不可数名词用连词连接做主语时谓语动词用单数形式还是复数形式?不可数和不可数呢?WHEN和WHERE呢?(WHEN和WHERE做关系代词) 1.49*10的三次方在立方是多少 名词修饰名词时,修饰名词的名词使用单数还是复数.如果要是表示复数概念,那么修饰名词的名词用复数/单数 a lot of +名词单数还是复数 lots of +名词单数还是复数 已知:a²+a一1=0,求a的立方+2a²十1999 用量词修饰可数名词位于是单数还是复数,比如a box of pears后面用动词是单数还是复数, lots of 和 a lot of 后面接单数还是复数呀?还是单复数都可以呀?要举出例子的! 请问a quantity of与 quantities of修饰的名词作主语时,谓语动词单复数如何决定?请举例说明,
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn