RubyMotion學(xué)習(xí)記錄

雜七雜八的先記錄一些,以后在更新;

啟動(dòng)Rubymotion

創(chuàng)建一個(gè)項(xiàng)目

$ motion create HelloMotion

啟動(dòng)

通常啟動(dòng)Simulator

rake

選擇型號(hào)啟動(dòng)Simulator

rake device_name="iPhone 4s"

配置

Motion::Project::App.setup do |app|
  app.name = 'LocationManager2'
  app.frameworks += ['CoreLocation', 'MapKit']

  app.info_plist['NSLocationAlwaysUsageDescription'] = 'Description'
  app.info_plist['NSLocationWhenInUseUsageDescription'] = 'Description'
end

Views

UIViewUIWindow的父類(lèi)

frame屬性, 它包含了視圖的x和y坐標(biāo), 以及它的height 高度和width寬度.

subviews屬性, 是包含所有子視圖的數(shù)組集合, 按照從后到前的順序依次可視.

一個(gè)視圖, 它的坐標(biāo)是(10, 10), 我想讓一個(gè)新的子視圖出現(xiàn)在屏幕(50, 50) 的位置上, 那么我必須設(shè)置新視圖的frame定位為(40, 40).

def application(application, didFinishLaunchingWithOptions:launchOptions)
   # UIScreen describes the display our app is running on
   @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
   @window.makeKeyAndVisible
   @blue_view = UIView.alloc.initWithFrame(CGRectMake(10, 10, 100, 100))
   @blue_view.backgroundColor = UIColor.blueColor
   @window.addSubview(@blue_view)
   true
end
  • 創(chuàng)建了一個(gè)UIWindow的實(shí)例@window,大小和屏幕大小一樣。
    調(diào)用方法makeKeyAndVisible以上這些告訴操作系統(tǒng)該窗口接收觸摸事件, 在屏幕上可視.
  • 創(chuàng)建@blue_view視圖,并添加為該@window的子視圖。視圖的Frame作為一個(gè)CGRect對(duì)象被存儲(chǔ),使用CGRectMake(x, y, w, h);CGRect由兩個(gè)對(duì)象組合而成:CGPointCGSize 讀取視圖的y坐標(biāo)view.frame.position.y 視圖高度view.frame.size.height

注意: 直接在UIWindow上添加UIView這種做法@window.addSubview(@blue_view)并不值得推薦, 我只是為了說(shuō)明問(wèn)題才這樣做的. 在生產(chǎn)環(huán)境中不能這樣做. [1]

UIScreen

UIScreen.mainScreen.bounds根據(jù)返回的矩形大小屏幕尺寸和器件的定位

一個(gè)UIScreen對(duì)象包含設(shè)備的整個(gè)屏幕的邊框。

label

def viewDidLoad
  super
  self.view.backgroundColor = UIColor.whiteColor
  @label = UILabel.alloc.initWithFrame(CGRectZero)
  @label.text = "Taps"
  @label.sizeToFit
  @label.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2)
  self.view.addSubview @label
end

使用CGRectZero初始化時(shí)先假設(shè)這個(gè)視圖大小為0,

label.textColor = UIColor.greenColor

label.font = UIFont.fontWithName("HelveticaNeue- CondensedBold",size:18)

Alert

UIAlertView < UIView < UIResponder < NSObject

alert = UIAlertView.alloc.initWithTitle "This is foo title",message:"Do you like this example?",
delegate: nil,
cancelButtonTitle: "cancel"
otherButtonTitles: "Yes","No",nil
alert.show

irb

> delegate = UIApplication.sharedApplication.delegate
=> #<AppDelegate>
> blue_view = delegate.instance_variable_get('@blue_view')
=> #<UIView>
> blue_view.subviews.count
> => 1
> > red_view = blue_view.subviews[0]
> => #<UIView>
> > red_view.removeFromSuperview
> => #<UIView>
  • UIApplication.sharedApplication 返回一個(gè)對(duì)象, 系統(tǒng)可以使用這個(gè)對(duì)象描述整個(gè)應(yīng)用程序, 這個(gè)對(duì)象只有一個(gè).
  • 使用.delegate來(lái)獲取配置
  • 一旦獲取到, 就可以使用instance_variable_get方法來(lái)獲取其中的視圖.

Controller

  • 視圖重用: 假設(shè)我們有一個(gè)PostView, 用來(lái)展示Post的所有信息. 我想在不同的屏幕上使用這個(gè)視圖. 為了可重用性, PostView不應(yīng)該有獲取信息的邏輯代碼, 所以處理數(shù)據(jù)的的任務(wù)就應(yīng)該由Controller來(lái)承擔(dān), 然后把處理好的數(shù)據(jù)傳遞給視圖.
  • Presentation management: 有時(shí)候我們需要讓一個(gè)視圖占據(jù)一整塊屏幕, 而有些時(shí)候需要讓這個(gè)視圖占據(jù)屏幕的一部分, 比如對(duì)于ipad和iPhone來(lái)說(shuō). 如果就因?yàn)檫@事就寫(xiě)兩個(gè)內(nèi)容完全相同的視圖class只是大小不同就沒(méi)有必要了, 所以我們使用Controller來(lái)讓視圖顯示相應(yīng)的大小.

創(chuàng)建一個(gè)./app/controllers/tap_controller.rb

class TapController < UIViewController
  def viewDidLoad
    super
    self.view.backgroundColor = UIColor.redColor
  end
end

viewDidLoad 是UIViewController生命周期方法之一.
@window.rootViewController = TapController.alloc.initWithNibName(nil, bundle: nil)

  • initWithNibName:bundle: 是用于從NIB文件中載入Controller. NIB 是使用Xcode’s Interface Builder 作為一種可視化構(gòu)建視圖的方式來(lái)創(chuàng)建的.
  • initWithNibName:bundle: 也是一種UIViewController的特點(diǎn)初始化. 只要以創(chuàng)建一個(gè)控制器, 你必須要調(diào)用這個(gè)方法.

Containers

UITabBarControllerUINavigationController這些container (容器) 是UIViewController, 同時(shí)管理其他UIViewController.

IOS SDK使用UINavigationControllersUITabBarController 來(lái)包含子視圖Controllers.

UINavigationController(需要繼續(xù)補(bǔ)充)

UINavigationController使用stack這樣的結(jié)構(gòu)管理它里面的Controllers.[2]

AppDelegate中, 把rootViewController賦值為一個(gè)UINavigationController :

controller = TapController.alloc.initWithNibName(nil, bundle:nil)
@window.rootViewController = UINavigationController.alloc.initWithRootViewController(controller)

initWithRootViewController會(huì)把controller作為stack的第一個(gè)元素.

導(dǎo)航條添加按鈕

def viewDidLoad
  ...
  self.title = "Tap (#{self.navigationController.viewControllers.count})"
  right_button = UIBarButtonItem.alloc.initWithTitle("Push", style: UIBarButtonItemStyleBordered, target:self, action:'push')
  self.navigationItem.rightBarButtonItem = right_button
end
  • 創(chuàng)建了UIBarButtonItem的實(shí)例, style 屬性決定按鈕的樣子風(fēng)格
  • 設(shè)置成了Controller的navigationItemrightBarButtonItem
  • 每一個(gè)UIViewController都有navigationItem, 我們通過(guò)這個(gè)屬性可以訪問(wèn)到導(dǎo)航條的信息.
  • 注意: UINavigationItem不是UIView, 不能隨意添加子視圖.
定義action 對(duì)于的方法push
def push
  new_controller = TapController.alloc.initWithNibName(nil, bundle: nil)
  self.navigationController.pushViewController(new_controller, animated: true)
end
  • pushViewController會(huì)把Controller推入stack中
  • 默認(rèn) navigation controller 會(huì)在左側(cè)顯示一個(gè)back的按鈕來(lái)把當(dāng)前Controller彈出棧.
  • UINavigationControllerpushViewController:animatedpopViewControllerAnimated 來(lái)控制進(jìn)棧和彈棧.

UITabBarController

TabBarControllers它只能作為windowrootViewController, 你不能把它push到NavigationController中.

UITabBarController 使用viewControllers=來(lái)控制它的子元素, 注意UITabBarController只允許被用作window的rootViewController

other_controller = UIViewController.alloc.initWithNibName(nil, bundle: nil)
other_controller.title = "Other"
other_controller.view.backgroundColor = UIColor.purpleColor
tab_controller = UITabBarController.alloc.initWithNibName(nil, bundle: nil)
tab_controller.viewControllers = [nav_controller, other_controller]
@window.rootViewController = tab_controller

創(chuàng)建了UITabBarController, 然后設(shè)置viewControllers 為一個(gè)數(shù)組. 數(shù)組的元素為所要含有的 NavigationController.

TapController重寫(xiě)initWithNibName:bundle方法

def initWithNibName(name, bundle: bundle)
  super
  self.tabBarItem = UITabBarItem.alloc.initWithTabBarSystemItem(UITabBarSystemItemFavorites, tag: 1)
  self
end
  • 使用了系統(tǒng)的圖標(biāo), 使用的方法是initWithTabBarSystemItem
  • 然后我把它放到initWithNibName:bundle, 為的是只有Controller一初始化, 就創(chuàng)建tabBarItem.
  • 使用controller(self).tabBarItem改變tab圖標(biāo)和title.

Tables

UITableView有dataSource, 用來(lái)提供數(shù)據(jù)信息; delegate 用來(lái)管理用戶的行為, 視覺(jué)體驗(yàn)

class AlphabetController < UIViewController
  def viewDidLoad
    super
    self.title = "Alphabet"
    @table = UITableView.alloc.initWithFrame(self.view.bounds)
    self.view.addSubview @table
  end
end
  • view.bounds返回的是CGRect對(duì)象, 類(lèi)似于view.frame, 但是frame只描述了大小, 沒(méi)有位置.
  • newView.initWithFrame(view.bounds)則是讓newView填充view.

在AppDelegate里添加這個(gè)新的AlphabetController:

alphabet_controller = AlphabetController.alloc.initWithNibName(nil, bundle: nil)

需要設(shè)置dataSource :

def viewDidLoad
...
@table.dataSource = self
end

data source 必須要實(shí)現(xiàn)以下方法:

  • numberOfRowsInSectioncellForRowAtIndexPath
  • cellForRowAtIndexPath應(yīng)該返回UITableViewCell的實(shí)例
def tableView(tableView, cellForRowAtIndexPath: indexPath)
  @reuseIdentifier ||= "CELL_IDENTIFIER"
  cell = tableView.dequeueReusableCellWithIdentifier(@reuseIdentifier) || begin  UITableViewCell.alloc.initWithStyle(UITableViewCellStyleDefault, reuseIdentifier:@reuseIdentifier)
  end
  # put your data in the cell
  cell
end

這里reuseIdentifier 是對(duì)這一種的cell做一個(gè)標(biāo)記, 這些cell是一個(gè)類(lèi)型的, 因?yàn)樵趇OS中管理著若干cell 池, 當(dāng)需要重新使用一個(gè)cell時(shí), 通過(guò)這個(gè)reuseIdentifier去相應(yīng)的cell池中拿出即可.

需要準(zhǔn)備數(shù)據(jù)

def viewDidLoad
  ...
  @data = ("A".."Z").to_a
  @table.dataSource = self
  @table.delegate = self
end

在numberOfRowsInSection中, 需要設(shè)置行的數(shù)量

def tableView(tableView, numberOfRowsInSection: section)
  @data.count
end

使用delegate和didSelectRowAtIndexPath方法來(lái)響應(yīng)用戶觸碰某一個(gè)行

deselectRowAtIndexPath:animated 的作用是, 點(diǎn)擊一個(gè)cell之后, 它會(huì)被高亮, 該方法就是取消高亮.

def tableView(tableView, didSelectRowAtIndexPath:indexPath)
  tableView.deselectRowAtIndexPath(indexPath, animated: true)
  alert = UIAlertView.alloc.init
  alert.message = "#{@data[indexPath.row]} tapped!"
  alert.addButtonWithTitle "OK"
  alert.show
end

Models(需要繼續(xù)補(bǔ)充)

屬性訪問(wèn)

class User
  attr_accessor :id
  attr_accessor :name
  attr_accessor :email
end

之后可以像這樣操作對(duì)象

@user = User.new
@user.name = "Clay"
@user.email = "clay@mail.com"

如果需要處理一些遠(yuǎn)程API, 就應(yīng)該技巧性的處理

class User
  PROPERTIES = [:id, :name, :email]
  PROPERTIES.each do |prop|
    attr_accessor prop
  end
  def initialize(attributes = {}) 
    attributes.each do |key, value|
      self.send("#{key}=", value) if PROPERTIES.member? key
    end
  end
end

在初始化User的時(shí)候可以這樣做

server_hash = { name: "Clay", email: "my@email.com", id: 200000 }
@user = User.new(server_hash)
@user.name
=> Clay

NSCoding

NSUserDefaults

對(duì)象可以作為持久化的K-V存儲(chǔ).一般, 我們會(huì)使用NSUserDefaults.standardUserDefaults的實(shí)例作為對(duì)象

@defaults = NSUserDefaults.standardUserDefaults
@defaults["one"] = 1
# somewhere else, next time we run the app
@defaults["one"]
=> 1
  • 只要你的app被安裝, NSUserDefaults的值就會(huì)被保存.
  • NSUserDefaults.resetStandardUserDefaults方法可以清空所有的key value.
  • 注意的是, 我們不能在NSUserDefaults 中存儲(chǔ)舊的對(duì)象[3]
  • 因?yàn)椴皇窃紨?shù)據(jù), 所以必須使用data 方法.

符合NSCoding的兩個(gè)方法是initWithCoder:(用于載入一個(gè)對(duì)象) 和 encodeWithCoder(用于保存對(duì)象).這兩個(gè)方法像鏡子一樣, encodeWithCoder可以通過(guò)key把所有對(duì)象的值進(jìn)行編碼, initWithCoder通過(guò)這些key對(duì)對(duì)象的值解碼.

class Post
  attr_accessor :message
  attr_accessor :id
  
  # called when an object is loaded from NSUserDefaults
  # this is an initializer, so should return `self`
  def initWithCoder(decoder)
    self.init
    self.message = decoder.decodeObjectForKey("message")
    self.id = decoder.decodeObjectForKey("id")
    self
  end
  # called when saving an object to NSUserDefaults
  def encodeWithCoder(encoder)
    encoder.encodeObject(self.message, forKey: "message")
    encoder.encodeObject(self.id, forKey: "id")
  end
end

這就允許我們把任意對(duì)象轉(zhuǎn)換成數(shù)據(jù), 可以保存到NSUserDefaults中:

defaults = NSUserDefaults.standardUserDefaults
post = Post.new
post.message = "hello!"
post.id = 1000
post_as_data = NSKeyedArchiver.archivedDataWithRootObject(post)
defaults["saved_post"] = post_as_data
# later on, we want to load this post:
post_as_data = defaults["saved_post"]
post = NSKeyedUnarchiver.unarchiveObjectWithData(post_as_data)

Key-Value Observing

https://danielzhangqinglong.github.io/2015/04/12/rubymotion-tut07

HTTP

https://github.com/clayallsopp/afmotion


  1. rootViewController=方法讓窗口使用給定的UIViewController所調(diào)整(產(chǎn)生)的視圖, 相對(duì)于window.addSubview這樣做更好.@window.rootViewController = TapController.alloc.initWithNibName(nil, bundle: nil) ?

  2. https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/ ?

  3. 可以存儲(chǔ)基本數(shù)據(jù)類(lèi)型( strings, integers, and hashes ), 或者使用原生的byte數(shù)據(jù). ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • iOS 實(shí)戰(zhàn)開(kāi)發(fā)課程筆記 本貼旨在作為對(duì)極客班 《iOS 開(kāi)發(fā)實(shí)戰(zhàn)》第五期期課程視頻重新學(xué)習(xí)的筆記。目標(biāo)是建立一個(gè)...
    黃穆斌閱讀 3,241評(píng)論 12 57
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,161評(píng)論 4 61
  • 醉眼朦朧看足球,驚魂動(dòng)魄酒已醒。命運(yùn)何須他人定,只要拼搏就會(huì)贏!
    葉小北閱讀 172評(píng)論 0 1
  • 1.適合你的未必是你喜歡的。你所需要的也未必會(huì)喜歡。人生而在世,總有許多身不由己。無(wú)需抱怨,接受與否,端看自己的選...
    染青綾閱讀 242評(píng)論 0 2

友情鏈接更多精彩內(nèi)容