Rubymotion – new bug found

I’m using this motion-addressbook in my project. Reported http://hipbyte.myjetbrains.com/youtrack/issue/RM-630

fixed in 2.37


= RubyMotion 2.37 =

* Fixed a regression where Dispatch.once did not work correctly when it was
invoked in some points.
* Fixed a bug where the compiler would crash with an assertion message
`[BUG] Object: SubtypeUntil ...' when compiling certain Ruby files.
* Fixed a bug in the compiler when compiling for ARM64 where certain types
would still be emitted with a 32-bit architecture in mind.
* Fixed a bug in the compiler when compiling for ARM64 where certain structs
would not be properly available (such as NSDecimal).

Change image in UIImageView – RubyMotion

I needed to change image in my UIImageView, but simply setting new image using myImageView.setImage didn’t work. There’s simple workaround

@button = UIView.alloc.initWithFrame(frame)
buttonImage = UIImageView.alloc.initWithFrame(@button.bounds)
buttonImage.setTag(1) # set any number you want
buttonImage.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight
@button.addSubview buttonImage

and now set the image

self.button.viewWithTag(1).setImage(UIImage.imageNamed('answer_bar_white.png').resizableImageWithCapInsets(UIEdgeInsetsMake(18, 18, 18, 18)))

you can remove resizableImageWithCapInsets – I’m using square images to make UIImageView of any size.

Download file using AFNetwork

set your Rakefile

  app.pods do
    pod 'AFNetworking'
    ...
  end
  def downloadFile(url, file, filesize)
    url = NSURL.URLWithString(url)
    request = NSURLRequest.requestWithURL(url)
    operation = AFHTTPRequestOperation.alloc.initWithRequest(request)
    operation.outputStream = NSOutputStream.outputStreamToFileAtPath(file, append: false)

    unless filesize.nil?
      SVProgressHUD.showProgress(0, status: "Downloading file")
      operation.setDownloadProgressBlock(lambda{|bytesRead, totalBytesRead, totalBytesExpected|
        SVProgressHUD.showProgress((((totalBytesRead/filesize.to_f)*100.0).round)/100.0, status: "Downloading file")
      })
    end

    operation.setCompletionBlockWithSuccess(lambda{|request, response|
      SVProgressHUD.dismiss unless filesize.nil?
    }, failure: lambda{|request, err|
      SVProgressHUD.dismiss unless filesize.nil?

      @alert = UIAlertView.alloc.initWithTitle('Error',
          message: 'Error when downloading data.', delegate: nil, cancelButtonTitle: 'OK',
          otherButtonTitles: nil)
      @alert.show
    })
    operation.start
  end

when downloading multiple files, use NSOperationQueue

# change donwloadFile

def downloadFile..
 ...
 operation # was operation.start
end
@queue = NSOperationQueue.alloc.init
@queue.name = "FileDownload"
@queue.maxConcurrentOperationCount = 1   # number of concurrent downloads

@queue.addOperation(downloadFile(url, file, filesize))

MD5/SHA1 gem for RubyMotion

I’ve released gem for making MD5/SHA1 hashes in RubyMotion. It’s handled by small ObjC code in vendor directory. You can get this gem from my github.

Add gem ‘rm-digest’  into your Gemfile , run bundle install  and you can generate MD5/SHA1 in your application.

digestSHA1String = RmDigest::SHA1.hexdigest('some string')

digestMD5String = RmDigest::MD5.hexdigest('some string')

 

Dismissing popup view tapping outside

class MyView < UIVIewController

  ...

  # set gesture to close
  def viewDidAppear(animated)
    recognizer = UITapGestureRecognizer.alloc.initWithTarget(self, action: 'handleTapBehind:')

    recognizer.setNumberOfTapsRequired(1)
    recognizer.cancelsTouchesInView = false
    self.view.window.addGestureRecognizer(recognizer)
  end

  # handle tap  
  def handleTapBehind(sender)
    if sender.state == UIGestureRecognizerStateEnded
      location = sender.locationInView(nil)
      unless self.view.pointInside(self.view.convertPoint(location, fromView: self.view.window), withEvent: nil)
        self.view.window.removeGestureRecognizer(sender)
        self.dismissViewControllerAnimated(true, completion: lambda{})
      end
    end
  end

end

 

PSTCollectionView in rubymotion

I need use UICollectionView, but target my app for iOS < 6.0. So I’ve found PSTCollectionView library and using it with my rubymotion project. You can find whole source code in my github repo.

You need to download and link PSTCollectionView directory into vendor/PSTCollectionView .

Then update yourRakefile :

app.vendor_project('vendor/PSTCollectionView', :static)
app.frameworks += %w(QuartzCore UIKit)
app.deployment_target = "5.0"
app.device_family = [:ipad]

create app/controllers  and add two files – cell.rb  and view_controller.rb

cell.rb

class Cell < PSTCollectionViewCell #PSUICollectionViewCell

  attr_accessor :label

  def initWithFrame(frame)
    if super
      @label = UILabel.alloc.initWithFrame(CGRectMake(0.0, 0.0, frame.size.width, frame.size.height))

      @label.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth
      @label.textAlignment = UITextAlignmentCenter
      @label.font = UIFont.boldSystemFontOfSize(50.0)
      @label.backgroundColor = UIColor.underPageBackgroundColor
      @label.textColor = UIColor.whiteColor
      self.contentView.addSubview(@label)
    end
    self
  end

end

and view_controller.rb

class ViewController < PSTCollectionViewController #PSUICollectionViewController

  def viewDidLoad
    super
    pinchRecognizer = UIPinchGestureRecognizer.alloc.initWithTarget(self, action:'handlePinchGesture')
    self.collectionView.addGestureRecognizer(pinchRecognizer)
    self.collectionView.registerClass(Cell, forCellWithReuseIdentifier: "MY_CELL")
  end

  def collectionView(view, numberOfItemsInSection: section)
    63
  end

  def collectionView(collectionView, cellForItemAtIndexPath: indexPath)
    cell = collectionView.dequeueReusableCellWithReuseIdentifier("MY_CELL", forIndexPath:indexPath)
    cell.label.text = 'test'
    cell
  end

  def collectionView(collectionView, layout: collectionViewLayout, sizeForItemAtIndexPath:indexPath)
    CGSizeMake(120, 120)
  end

  def collectionView(collectionView, layout: collectionViewLayout, minimumInteritemSpacingForSectionAtIndex: section)
    30
  end

  def collectionView(collectionView, layout:collectionViewLayout, minimumLineSpacingForSectionAtIndex: section)
    30
  end

end

Finally, change app_delegate.rb

class AppDelegate
  def application(application, didFinishLaunchingWithOptions:launchOptions)
    @window = UIWindow.alloc.initWithFrame UIScreen.mainScreen.bounds
    view_controller = ViewController.alloc.initWithCollectionViewLayout(PSTCollectionViewFlowLayout.new)
    @window.rootViewController = view_controller
    @window.makeKeyAndVisible
    true
  end
end

runrake  and voila! :)

Screen Shot 2013-02-20 at 21.56.21

PSPDFKit gem for rubymotion

I’ve just released simple gem to include PSPDFKit into rubymotion project – see https://rubygems.org/gems/pspdfkit.

Installation is pretty straightforward

add to your Rakefile :

require 'rubygems'
require 'bundler'
Bundler.require

Create Gemfile file and add:

source :rubygems

gem 'pspdfkit'

and execute bundle install .

Then you need to copy/link framework and bundle files:

mkdir vendor
cd vendor
ln -s ../../pdf/Products/PSPDFKit.embeddedframework/PSPDFKit.framework ./
cd ../resources
ln -s ../../pdf/Products/PSPDFKit.embeddedframework/Resources/PSPDFKit.bundle ./

That’s it. Run rake and test your installation.

PSPDFKit in rubymotion

Update

If you’re using Bundler, you can simply add gem ‘pspdfkit’ to your Gemfile. See more on https://github.com/tmeinlschmidt/rm-pspdfkit


As I’ve started using this famous framework, I’d like to use it in my rubymotion application. So, there’s my setup to include this fmw in rubymotion project

  • extract PSPDFKit anywhere
  • create directory vendor  in your RM project
  • create symbolic link from your unzipped PSPDFKit to vendor/PSPDFKit.framework
cd vendor
ln -s ../../pdf/Products/PSPDFKit.embeddedframework/PSPDFKit.framework ./
cd ../resources
ln -s ../../pdf/Products/PSPDFKit.embeddedframework/Resources/PSPDFKit.bundle ./

and modify Rakefile accordingly

app.vendor_project('vendor/PSPDFKit.framework', :static, products: ['PSPDFKit'], headers_dir: 'Headers')

app.libs << '/usr/lib/libz.1.1.3.dylib'

app.frameworks += %w(MessageUI AssetsLibrary MediaPlayer PSPDFKit)

try rake , it should link and start simulator.

Next step

Add some PDF file into your app resources  folder.

And then you can try to modify app/app_delegate.rb  with simple example:

class AppDelegate
  def application(application, didFinishLaunchingWithOptions:launchOptions)

    documentURL = NSBundle.mainBundle.resourceURL.URLByAppendingPathComponent "DevelopersGuide.pdf"
    @document = PSPDFDocument.PDFDocumentWithURL documentURL

    pdfController = PSPDFViewController.alloc.initWithDocument @document
    navController = UINavigationController.alloc.initWithRootViewController pdfController

    @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
    @window.makeKeyAndVisible

    @window.rootViewController = navController
  end
end