用Lua編寫iOS程式

來源:互聯網
上載者:User

原文:http://luanova.org/ioswithlua/

 

本文討論用Lua建立iOS應用的3種方法。包括用Lua建立完整的應用(Corona)一直到用Lua作為app中的指令碼元素(通過Wax或diy)。在此之前,我們需要問自己兩個問題:

1、為什麼要使用Lua。

2、蘋果允許使用Lua嗎。

這兩個問題是緊密相關的。

如果你在此之前對Lua一無所知,我會簡單介紹一下Lua。如果你熟悉Lua,則可以跳過這部分內容。

 

關於Lua

 

Lua是一個高效、輕量級、嵌入式指令碼語言。類似Javascrip、Ruby或Python。有許多和我一樣的使用者,都認為Lua是一種簡潔優雅的語言。

Lua始於1993年巴西裡約熱內盧宗鐸天主教大學的Roberto Ierusalimschy, Waldemar Celes 和Luiz Henrique de Figueiredo。它應用在Mi Casa Verde, Adobe Lightroom, Celestia, lighttpd,LuaTeX, nmap,Wireshark, 思科的Adaptive Security Appliance, pbLua,以及成千上萬的遊戲中(包括 Grim Fandango(神通鬼大),魔獸世界,Tap Tap Revenge(勁樂團)等)。Lua採用MIT協議——這意味著Lua基本無礙於商業和非商業目的。

Lua的主要資料構建機制是表——可變數組和雜湊表的結合。列表1列出了一個Lua Table,假設我們用於描述汽車和它的每加侖行駛裡程數。我們可以用字串類型的鍵來儲存車輛資訊,如license和make。而採用數字下標索引的方式儲存一系列的每加侖裡程數。

 

列表 1: 一個 Lua Table類型

 

  car_data = { license = 'XVW1942', make = 'Volvo',                model = 'XC70',30, 31.3,32.4, 34.0}

   print(car_data[1])               -- 30

 print(car_data['license'])       -- XVW1942

print(car_data.license)          -- XVW1942 (also!)

 

在Lua中,數組下標從1開始,而不是0。'--'表示注釋開始直至行末。讓你想不到的是,Lua既不是物件導向的語言,也不是函數程式設計語言。但是,它也提供了幾種機制允許你定製自己的進階特性。Lua中內包含了各種不同的對象系統如:傳統OO系統和無類化OO系統(比如Oracle的Self語言和Io語言。譯者注*  這兩種都是基於範型的語言)。Lua支援“first class 函數”(譯者注*其實是匿名函數, Lua可以在運行時隨時構造出一個函數,並把它看作一個對象),閉包以及元特性(如元表和元方法)。Lua能很好地滿足函數式編程的需要。

關於Lua 的物件導向編程的介紹,請閱讀《Lua 編程》(這本書很好地介紹了Lua的方方面面)。你也應當閱讀Luawiki上的Lua樣本。

列表2列出了鏈表類的一種實現。變數List實際上是table,用作所有鏈表對象的元表。它實現了一種向後尋找表索引的類似於類的事件處理機制。"List.__index=List"一行允許我們為List對象建立方法。方法是儲存在List元表中的函數。當我們調用list對象的這些函數時,將在List元表中尋找這些函數的定義並運行。

這段代碼顯示了Lua的一系列增強特性:多賦值(以及函數返回多個傳回值),方法調用文法糖(':' 符號的作用,類似於在函數調用中增加了一個self參數,這在許多語言,從Python到OC都能見到)。

 

列表 2: Linked List 類

List = {}

List.__index = List

 

function List:new()

  local l = { head = {},tail = {}, size = 0 }

  l.head.__next,l.tail.__prev = l.tail, l.head

  return setmetatable(l,self)

end

 

function List:first()

  if self.size > 0 then

    returnself.head.next

  else

    return nil

  end

end

 

function List:addFirst(elem)

   local node = { prev= self.head, value = elem,

                       next = self.head.next }

   node.next.prev =node

   self.head.next =node

   self.size =self.size + 1

end

 

mylist = List:new()

mylist:addFirst(12)

print(mylist:first())

 

在這裡,我忽略了一些重要的和有趣的東西(比如閉包)。但至少,你已經學到了一點Lua的皮毛。在後面我們進入iPhone編碼的時候,會看到更多的Lua代碼。更多關於Lua的介紹,請閱讀這個網站。

 

iOS支援指令碼嗎。

 

正如本文開頭列出的兩個問題,尤其是第2個問題:“iPhone允許使用Lua(或其他解釋型語言)嗎。”畢竟,早在蘋果的IDP許可協議中就已經闡明“只有蘋果官方的API和內建解譯器所支援的解釋型代碼能被下載或用於app中”。

事實上,本文的擬寫大綱時,蘋果已經改變了原來禁止開發人員在app使用除OC和Javascript(Javascript能在web app或者本地 app中使用——通過UIWebView)以外的其他語言的條款(circa2010 四月)。最近(2010 九月),蘋果再次改變了這個條款,允許使用指令碼語言。

但仍然有幾個重要的限制。更主要的是,雖然你可以使用Lua(及其它指令碼語言),但你的app不能允許使用者從web上下載外掛程式(用過應用程式購買嗎。),也不能允許使用者編寫指令碼、下載指令碼等。有大量的商店應用在使用Lua這樣的語言(比如勁樂團)。

當然,在app中包含Lua這類語言的兩個最為主要的作用,就是建立外掛程式系統,讓使用者自己能夠編寫指令碼。除此之外還有許多。

 

如何在iOS開發中使用Lua。

 

儘管你不能為終端使用者建立一個外掛程式系統,也不能讓使用者自己編寫指令碼,但你仍然能以一種外掛程式的方式開發你的系統。這可以加快原型的開發速度,同時在下個版本中有助於添加新的功能。使用Lua還有另一種好處,它允許你進行“快速原型開發”(我最喜歡抱怨的一句話:不要閉門造車式地編程),緩解甚至不需要記憶體管理,允許更多的團隊成員參與到開發中來(有許多Lua項目根本沒有程式員在編寫代碼),應用程式最佳化更加輕鬆,提供更強勁的持久化機制。

簡而言之,Lua節省了開發時間,降低了開發門檻。生活變得如此輕鬆愉快。假設你已經決定使用Lua,那麼我們該如何做起呢。

 

Corona

 

 

Ansca Mobile公司的Corona允許你完全用Lua來開發iOS應用,以及Android應用。你可以用同樣的原始碼編譯出iOS和Android程式。這正是Lua(實際上是Corona)為何如此迷人的原因:跨平台。

列表3 是一個app的全部原始碼。

 

列表3: Swirly Text 應用中的main.lua

 

local w, h = display.stageWidth, display.stageHeight

local dx, dy, dtheta = 5, 5, 5

 

 

local background = display.newRect(0, 0, w, h)

background:setFillColor(255, 255, 255)

 

 

local message = display.newText('Hello from Corona', w/2, h/2)

message:setTextColor(0, 0, 200)

 

 

local function update(event)

   local counter_spin =false

  message:translate(dx, dy)

  message:rotate(dtheta)

   if message.x > wor message.x < 0 then

      dx= -1 * dx

     counter_spin = true

   end

   if message.y > hor message.y < 0 then

      dy = -1 * dy

     counter_spin = true

   end

   if counter_spin then

     dtheta = -1 * dtheta

   end

end

 

 

Runtime:addEventListener('enterFrame', update)

 

Corona程式可以用任何文字編輯器開發——我用的是Emacs。所有Lua原始碼中用到的資源(圖片、聲音、資料)必需放在同一個目錄,Corona需要main.lua檔案來啟動app。可以在Corona模擬器中測試代碼(支援Intel cpu和Power pc的Mac)。圖1顯示了我的corona IDE: Emacs(包含Lua檔案出口和項目視窗)、Corona終端(可以從診斷中列印調試資訊),以及Corona模擬器。

 

圖 1: 我的 Corona 'IDE'

 

從左至右(反時針方向):Corona模擬器、Emacs的兩個視窗(原始碼視窗和項目目錄視窗)、Corona 終端(輸出調試資訊)。

想要在物理硬體上運行程式,使用Corona 模擬器的Openfor Build命令。要以iOS編譯,你應該提供一個Provisioning Profile(開發或部署)——沒錯,你並不需要IDP帳號——這兩個檔案隨同app代碼和資源一同上傳到Ansca公司的伺服器上,然後將編譯結果返回給你。要以Android編譯,你應當有適當的簽署憑證。然後隨著編譯過程把你的代碼傳到Ansca的伺服器上。你不必安裝AndroidSDK。我沒有太深入地研究,但編譯後的.apk檔案和.app檔案已經包含了所有你Lua代碼以某種方式處理過的東西。短暫的查看後表明,那不是標準的編譯後的Lua位元組碼,但應該是類似的格式。

Corona事件系統可以處理觸摸(包括多點觸摸),訪問GPS和加速器,處理動畫以及自訂事件。它還有一個強大的圖形系統,允許你繪製圓、矩形和文本。最近還增加了折線,允許你繪製多邊形。你可以顯示圖片。Corona允許你把這些對象組合在一起然後對他們進行變換。列表4,摘自太陽系模擬器的程式碼片段,展示了組合多個繪圖物件的簡單例子。其他Corona支援的特性還包括聲視頻播放,密碼編譯演算法庫,LuaSocket網路程式庫,SQLite存取庫LuaSQLite等。還能訪問本機群組件包括textfield、alert和activityindicator。你還可以用webview做諸如登入螢幕之類的事情,有一個樣本程式提供了一個庫,可以串連到Facebook。我最近看到有一個遊戲(很貴)使用了Box2D物理引擎、角色和一些OpenFeint的功能(類似熱門排行榜)。

 

列表 4: 太陽系應用程式碼片段

 

function new(params)

   local color =params.color or planet_colors[random(#planet_colors)]

   local radius =params.radius or planetRadius()

   local planet =display.newGroup()

 

   planet.theta = 0

   local x = params.x -ox

   local y = params.y -oy

  planet.orbital_radius = sqrt(x*x+y*y)

 

   local body =display.newCircle(x + ox, y + oy, radius, radius)

  body:setFillColor(unpack(color))

   planet:insert(body,true)

   planet.body = body

 

   planet.delta_theta =(40/planet.orbital_radius) * 0.1

 

   return planet

end

 

把table作為函數參數傳遞,可以使用具名引數並提供預設值。因此會有 local radius = params.radius orplanetRadius() 這樣的寫法。

Corona為你做了許多,但同時也有許多不足。最大的問題是對本地控制項的訪問限制。由於Corona模擬器的限制,它對本地控制項的訪問是糟糕的。在模擬器中,本地alerts和activityindicators用OSX equivalents實現而不是iOS widgets實現的。textfield、textbox以及web popups在模擬器運行時是停用。這在開發時讓人痛苦。

最後,除了ANSCA標準以外,無法訪問O-CAPI。不僅是大量的標準庫,而且第3方庫也無法使用,如Three20或 mobileads 這樣的APIs。當然,隨著Corona Android版本的發布,你可能不想訪問OC API因為它限制你的應用程式跨平台的能力(或者增加了複雜性)。最好是通過Lua的CAPI來擴充,就像是許多跨平台的項目一樣。

我在ANSCA 小組在他們論壇上的討論非常有用。隨著2.0版本(2010.9)的發布,Corona向每位開發人員每年收取249美金。對於遊戲版,收費每開發人員每年349美金。Ansca公司的網站暗示遊戲版的價格只是預覽版的。這意味著當正式版發布時價格將會更高。

 

DIY

 

很容易把Lua解譯器放到iOS app中。開啟一個Xcode項目把Lua的源檔案(除lua.c和luac.c命令列程式外)加到項目中。編譯。你就可以使用標準的LuaC API去建立一個解釋起並運行原始碼,就像 iLua所做的。你可以在http://github.com/profburke/ilua下載這個範例程式碼。iLuaShell是一個簡單的view-based application,它提供兩個文字框給使用者——一個給使用者輸入Lua代碼,另一個是不可編輯的,僅僅是顯示Lua代碼計算的結果。

 這個工作用evaluate方法完成,如列表5所示。在方法中首先擷取第1個文本域的值,把它交給Lua解譯器解析和執行,然後把Lua輸出結果放到第2個文本域中。

 

列表 5 evaluate 方法

 

-(void)evaluate {

    int err;

 

    [input resignFirstResponder];

    lua_settop(L, 0);

 

    err = luaL_loadstring(L, [input.text

                    cStringUsingEncoding:NSASCIIStringEncoding]);

    if (0 != err) {

        output.text = [NSString stringWithCString:lua_tostring(L, -1)

                            encoding:NSASCIIStringEncoding];

        lua_pop(L, 1);

        return;

    }

 

    err = lua_pcall(L, 0, LUA_MULTRET, 0);

    if (0 != err) {

        output.text = [NSString stringWithCString:lua_tostring(L, -1)

                            encoding:NSASCIIStringEncoding];

        lua_pop(L, 1);

        return;

    }

    int nresults =lua_gettop(L);

 

    if (0 == nresults) {

        output.text = @"<no results>";

    

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.