2014 年 12 月 30 日
教程:使用 CoronaCards 和 Swift 实现“发送至”功能
在之前的教程中,我们向您展示了如何将 CoronaCards 与 Swift 结合使用。在本教程中,我们将在一个基于 CoronaCards 的应用中实现一个原生功能:发送至按钮,其标识如下
![]()
在许多 iOS 应用中,当您按下发送至按钮时,会弹出一个“共享面板”,让您可以通过 Twitter、Facebook 和其他服务共享您的信息,并提供打印和 AirDrop 等功能。在原生术语中,此面板被称为 UIActivityViewController。方便的是,这可以使用 CoronaCards 来实现。
在继续之前,请确保您已经安装了之前教程中的 CoronaCards 模板,并且您可以构建其中呈现的项目。
设置
首先,使用 CoronaCards “单视图”模板创建一个新的 Xcode 项目。然后,为您的项目命名并将您的 CoronaCards license.ccdata 文件复制到核心项目文件夹,其中包含 main.lua。
Corona 端
CoronaCards 模板为您提供了“HelloPhysics”示例应用作为起点,本教程将在此基础上构建。我们的“发送至”Corona 应用将提供一个按钮来调用共享,但首先我们需要一些共享内容。为此,应用将使用 display.captureScreen() 捕获屏幕,并使用 display.save() 将其保存到临时文件。然后,代码将向原生端发送一个事件,在该事件中将显示 UIActivityViewController,并且此事件将包含文本消息、捕获的图像和 URL。当控制器完成时,它将在 Corona 端触发一个事件,告诉您的应用它是否完成以及选择了什么服务。最后,将使用 display.newText() 对象来显示结果。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
--------------------------------------------------------------------------------------- -- 一个简单的物理示例,仅需 8 行! --------------------------------------------------------------------------------------- local physics = require( "physics" ) -- -- Hello Physics 示例应用 -- physics.start() local sky = display.newImage( "sky.png", 160, 195 ) local ground = display.newImage( "ground.png", 160, 445 ) local crate = display.newImage( "crate.png", 180, -50 ) crate.rotation = 5 physics.addBody( ground, "static", { friction=0.5, bounce=0.3 } ) physics.addBody( crate, { density=3.0, friction=0.5, bounce=0.3 } ) -- -- 设置共享“按钮”和结果文本对象 -- local shareText -- 前向声明按钮 local resultText = display.newText( "", display.contentCenterX, 20, "HelveticaNeue", 20 ) -- -- 设置与 Swift 的通信 -- local function handleTap( event ) -- -- 捕获屏幕 -- 此外,最初隐藏按钮 -- shareText.isVisible = false local screen = display.captureScreen( false ) -- -- 将捕获内容保存到临时目录 -- display.save( screen, { filename="screencapture.jpg", baseDir=system.TemporaryDirectory, isFullResolution=true, backgroundColor={0,0,0,0} } ) screen:removeSelf() screen = nil -- -- 显示按钮 -- shareText.isVisible = true local event = { name = "coronaView", message = "我刚刚看了Hello Physics!", image = { filename="screencapture.jpg", baseDir=system.TemporaryDirectory }, url = "" } -- 将数据分发到全局 Runtime 对象 Runtime:dispatchEvent( event ) return true end shareText = display.newText( "分享", display.contentCenterX, 200, "HelveticaNeue", 24 ) shareText:addEventListener( "tap", handleTap ) shareText.x = display.contentCenterX shareText.y = display.contentHeight - 15 -- -- 设置一个监听器来处理来自 Swift 的返回事件 -- local function sendToComplete( event ) print( "sendToComplete" ) print( event.name ) -- "sendTo" 的字符串值 print( event.complete ) -- true 或 false 的布尔值 print( event.activity ) -- 活动名称 if ( event.complete ) then resultText.text = "通过 " .. event.activity 分享" else resultText.text = "已取消" end return true end Runtime:addEventListener( "sendTo", sendToComplete ) |
让我们检查一下这段代码的关键部分。按下分享“按钮”(shareText)会触发对象的处理函数 handleTap(),在该函数中会捕获屏幕。然后将捕获的屏幕保存到 system.TemporaryDirectory 文件夹中。接下来,构建一个事件表。原生端监听一个名为 coronaView 的事件,它需要一些文本、一个 URL 和一个图像,因此我们将这些项目添加到事件表中。最后,我们将事件分发到全局 Runtime。
当 UIActivityViewController 完成时(见下文),它会将一个事件发送回 CoronaCards 端。 这需要一个 Runtime 事件监听器,我们将其称为 sendTo,它将通信信息是否已共享或是否已取消。 如果已共享,它将返回使用的方法。
Swift 端
在 Swift 端,我们需要对 ViewController.swift 文件进行一些更改。 为了参考,整个文件如下所示
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
// // ViewController.swift // ActivityController // // 创建者 Rob Miracle 于 2014/12/28. // 版权所有 (c) 2014 Corona Labs. 保留所有权利. // import UIKit class ViewController : CoronaViewController, CoronaViewDelegate { var coronaView: CoronaView! = nil override func viewDidLoad() { super.viewDidLoad() // 在 加载视图后执行任何其他设置,通常来自 a nib. coronaView = self.view as CoronaView // 强制向下转型 coronaView.coronaViewDelegate = self coronaView.run() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // 释放可以重新创建的任何资源. } func coronaView(view: CoronaView, receiveEvent event: NSDictionary) -> AnyObject? { /* event 字典包含: message = 要分享的文本 image = 包含文件名和路径的NSDictionary url = 要发布的URL */ let message: String = event["message"] as String let imageData = event["image"] as NSData let image:UIImage = UIImage(data: imageData as NSData)! let myURL:String = event["url"] as String let url = NSURL(string: myURL) shareTextImageAndURL(sharingText: message, sharingImage: image, sharingURL: url) return(true) } func shareTextImageAndURL(#sharingText: String?, sharingImage: UIImage?, sharingURL: NSURL?) { var sharingItems = [AnyObject]() var view = self.view as CoronaView if let text = sharingText { sharingItems.append(text) } if let image = sharingImage { sharingItems.append(image) } if let url = sharingURL { sharingItems.append(url) } let activityViewController = UIActivityViewController(activityItems: sharingItems, applicationActivities: nil) activityViewController.completionHandler = {(activityType, completed:Bool) in if !completed { println("已取消") let event = ["name":"sendTo", "complete":false] view.sendEvent(event) return } else { println("完成 \(activityType)") let event = ["name":"sendTo", "complete":true, "activity":activityType] view.sendEvent(event) } } self.presentViewController(activityViewController, animated: true, completion: nil) } } |
第一个更改是设置一个委托来处理事件 - 这是其他控制器如何在 CoronaCards 端“与”您的 CoronaView 通信的方式。我们还将 CoronaViewDelegate 添加到类声明的末尾。
从 CoronaCards 接收事件的事件处理程序需要被调用 coronaView。因此,我们必须将 view 重命名为 coronaView 并将其声明为 ViewController 类的一部分。此外,我们将在运行 CoronaView 之前连接委托。
接下来,我们需要设置事件处理函数,该函数将接收来自 Corona 的数据。在函数内部,我们从事件表中提取各种字段。有趣的是,图像条目不包含文件名和路径,而是包含二进制图像数据,并且以 NSData 类型到达,我们可以将其转换为 UIImage 类型。此外,我们将 URL 从字符串转换为 NSURL。
准备好数据后,我们调用函数 shareTextImageAndURL,将对象传递给该函数。shareTextImageAndURL 函数只是查找三个对象中的每一个,并将它们添加到 sharingItems 数组中。
最后,我们创建 UIActivityViewController,用我们要共享的项目初始化它,并指示它使用所有可用选项。对于 UIActivityViewController 的完成处理程序,如果控制器被取消,我们设置一个名为 sendTo 的事件表(如 CoronaCards 侧所定义),并将 complete 条目设置为 false。在 else 子句中,我们设置一个 complete 设置为 true 的事件表,并将 activity 设置为 activityType。在这两种情况下,我们都会将事件发送到 CoronaCards 视图。最后,我们指示控制器通过 presentViewController() 命令显示。
结论
正如本教程所演示的,CoronaCards 使您可以访问各种原生功能,从而扩展基于 Corona 的项目的能力。和往常一样,请在下方贡献您的问题和意见。

埃里希·格吕特纳·D.
发布于 17:45,12 月 30 日谢谢,来得正是时候!!!
新年快乐,CoronaLabs 团队!!!
JCH_APPLE
发布于 08:22,1 月 2 日如果能有一个使用 Corona Enterprise 的相同示例,来展示两种方式之间的差异会很好:使用 Corona 的原生方式和使用原生的 Corona 方式。
罗伯,感谢您提供的所有精彩教程,并祝 Corona 的人们新年快乐。
罗伯·米拉科
发布于 14:58,1 月 2 日使用 ObjC 的方法并没有太大的不同。我对 Enterprise 的理解不是很深入,但如果是我,我会回到我做的 Enterprise 教程,并把它变成一个插件。也许可以把它命名为 plugin.sendto。该教程也有原生和 Corona 之间的数据传递。
唯一的问题是,它需要使用 UIActivityViewController 的 ObjC 版本,而不是 Swift 版本。对于 CoronaCards,Lua 库(和 lua_State 结构)位于 Objective C 类后面,Swift 可以轻松桥接。然而,在 Enterprise 示例中,当前的插件代码是 C++ 与 C 库通信,ObjC 调用 C++。Swift 和 C/C++ 之间的桥接需要做更多的工作才能实现,我目前还没到那一步。
JCH_APPLE
发布于 04:01,1 月 3 日谢谢。我会尝试,如果成功,我会发布结果。打印在商业应用中非常有用。
corona273
发布于 22:30,1 月 6 日请注意,还有一个未解决的功能请求,要求将 iOS 共享表添加到 Corona SDK(这是一个简单的添加,并且已经支持 Android 共享面板)
http://forums.coronalabs.com/topic/53371-supporting-ios-modal-share-action-sheet-airdrop-print-add-to-home-screen-add-bookmark-add-to-reading-list-etc/
罗伯,对此有何想法,何时可能会实现?
穆斯塔法
发布于 00:47,1 月 7 日谢谢你,罗伯,
Pro 版本可以实现吗?
罗伯·米拉科
发布于 16:04,1 月 7 日不,Pro 版本不可用。我们需要人们投票支持它。请访问 http://feedback.coronalabs.com,查找现有功能请求或创建新请求。
罗伯