Custom json with Juilder

Using jbuilder for customize json views is a great experience. also I have been writing the jbuilder in a long way. just today i found shortcuts way to write the same this. The length of the code dramatically reduced. Plus jbuilder support for partial is the best thing one could dream of.

previously the my code to render the array of books was  was like this.

json.data do
  json.books @books do |book|
    json.id book.id
    json.name book.name
    json.author book.author
    json.condition book.condition
    json.genere book.genere
    json.grade book.grade
    json.price book.price
    json.publication book.publication
    json.latitude book.latitude
    json.longitude  book.longitude
    json.address book.address
    json.donate book.donate
    json.exchange book.exchange

  end
end

Then I found the shortcut way for the same thing.

json.data do
  json.books @books do |book|
    json.(book, :id, :name, :author, :condition, :genere, :grade, :price, :publication, :latitude, :longitude, :address, :donate, :exchange)
  end
end

See that large chunk reduced to simple lines. Just Wow.. ūüôā

then I wrote a partial for that book Under the name _book.json.jbuilder

    json.(book, :id, :name, :author, :condition, :genere, :grade, :price, :publication, :latitude, :longitude, :address, :donate, :exchange)

and in index.jbuilder.json

  json.data do
   json.books @books do |book|
     json.partial! book
   end
  end

and thats it. The same partial can be reuse in index, create, update and delete views.

and the magic is that if we have to add or change any attribute, just do it in partial. all views will automically updated. yeeaa ūüėÄ

Advertisements

The remote end hung up unexpectedly

Sometimes, we faced an annoying problem like this one while trying to clone my BitBucket Repo.

 git clone git@bitbucket.org:veda_the_ram/veda-ios.git
  Cloning into 'veda-ios'...
  remote: Counting objects: 1688, done.
  remote: Compressing objects: 100% (1272/1272), done.
  Connection to bitbucket.org closed by remote host.00 KiB/s
  fatal: The remote end hung up unexpectedly
  fatal: early EOF
  fatal: index-pack failed

Tried increasing the postBuffer size as suggested in different stack overFlow answers. But it did not work out for me. After some research, I found the solution.

  
  git config --global core.compression 9

changing the compression quality  did the trick. Hmm.. ??

Cool Animation In UITableView

Animation in iOS are the heart of the user experience. We can add cool animation with few lines of code. I would like to share a piece of UITableViewAnimation here.

ezgif-com-video-to-gif

After all the cells are displayed normally in table view. Create a simple function called AnimateTableView.

 
func animateTableView() {
        tableview.reloadData()
        let cells = tableview.visibleCells
        let tableHeight = tableview.bounds.size.height
        
        cells.forEach({
            $0.transform = CGAffineTransform(translationX: 0, y: tableHeight)
        })
        
        var delayCounter = 0
        
        cells.forEach { (cell) in
            UIView.animate(withDuration: 1.75, delay: (Double(delayCounter) * 0.05), usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseOut, animations: {
                cell.transform = CGAffineTransform.identity
            }, completion: nil)
            delayCounter += 1
        }
    }

Just call that function in viewWillAppear or whereEver you want the show the animation.

cheers 

How to search for Crazy People…

Some times Its so much useful¬†to have a search feature in our apps. It’s so much easy to search the table view in swift.

I have a basic project already setup which  a table view as a list of names.

Screen Shot 2016-12-19 at 8.23.14 PM.png

I have defined two outlets for UITextField and UITableView in my ViewController Class.

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var txtSearch: UITextField!
    @IBOutlet weak var tableView: UITableView!
    
    let names: [String] = [
        "Ccr", "Shishir", "Da ri",
        "Bibek", "Manoj", "Amrit",
        "An Gee", "Dee J", "Ajeet",
        "Ashik", "Be Nod", "Samina",
        "guru", "aarko guru", " aani guru ko dup"
    ]
    var searchText: String = ""
    
    var filterednames: [String]  {
        let searchText = self.searchText.lowercased()
        return names.filter({
            name in
                return searchText.isEmpty || name.lowercased().contains(searchText)
        }).sorted(by: { (name, _) -> Bool in
            return name.hasPrefix(searchText) ?? false
        })
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        txtSearch.addTarget(self,
                            action: #selector(ViewController.filter(sender:)),
                            for: UIControlEvents.editingChanged
        )
    }
    
    func filter(sender: UITextField) {
        searchText = sender.text!
        tableView.reloadData()
    }
}


extension ViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView,
                   numberOfRowsInSection section: Int) -> Int {
        return filterednames.count
    }
    
    func tableView(_ tableView: UITableView,
                   cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        let name = filterednames[indexPath.row]
        cell.set(name: name)  // see extension below.
        return cell
    }
}

extension UITableViewCell {
    func set(name: String) {
        self.textLabel?.text = name
    }
}

So, That’s how we find¬†crazy people.

Choosing you default editor for git in unix system.

I used to love “nano” for a long time. But recently, I gave a try to vi and I am quite happy with it.

We can change our default editor in unix system with simple command.

git config --global core.editor "nano"   --> # if you love nano

git config --global core.editor "vim"   -->  # if you love vim

Presenting TransLucent Modal

POPUp view with a translucent background is simple way to add a cool effect on our app.

My storyBoard settings is show in this figure.

Its a simple view with little bit of opacity. Note that Alpha value is 0.8 and its backgroundColor is Black.

popUp view is simply just an another view.

screen-shot-2016-11-20-at-11-23-51-am

First grab that popUp viewController.

 let popUp = UIStoryboard.storyBoardWith(sbType: .ClubDetail).viewController() as RatingPopUp2

Then set the Modal presentation style. It defines how this modal should be presented.

 popUp.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext

Since I have  all viewControllers setup in a tabBarController, I want to present this view from the rootViewController, So that the tab bar settings remains behind this view.

So, I grab the RootViewcontroller and present this view from it.

 
let rootViewController = UIApplication.sharedApplication().keyWindow?.rootViewController
 rootViewController?.presentViewController(popUp, animated: true, completion: nil)

Result: 

A Sleek effect ūüôā

bestresult

 

Find if user is using iPAD or iPhone in swift

Many times we have to know if user is on iPad and iPhone. The most simple example is showing alerts and actionSheet. ActionSheets are cool when you have a bunch of actions. But iPad doesn’t support ActionSheets. In such case we may show alerts in iPad and actionSheet in iPhone.

 

UIAlertControllerStyle determines how the alerts are shown.

var presentationStyle: UIAlertControllerStyle = .ActionSheet
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.Pad) {
            presentationStyle = .Alert
            // Looks like user is using iPad...
        }
        // now show alerts using presentationStyle. and forget what device user is using.

Rounding a double value to x number of decimal places in swift

A little extension I wrote in Swift to round off the numbers to required number of decimal places.

 
extension Double {
    func roundOff(precision: Double) -> Double {
        let multiplier = pow(10.0, precision)
        let y = Double(round(multiplier * self) / multiplier)  // round function takes decimal value and returns double without decimals. round(123.456) --> 123
        return y
        }
}

 

Usage:

 
let x = 123.456

x.roundOff(1)  --> 123.5

x.roundOff(2) --> 123.46

x.roundOff(2) --> 123.456

Add Done Button On UIDatePicker

Default UIDatePicker View has a default Done button when it is displayed. But It does not work by default.

screen-shot-2016-09-28-at-11-30-52-am

If you are using the textField delegate, It is simple. Ios provides us a delegate function that is called when Return key is pressed.

 
func textFieldShouldReturn(textField: UITextField) -> Bool {
    // done button clicked
}

But my requirement don’t allows us to use delegate, so I need another way.

So, we need to add an button. I will be adding button pragmatically but we can also use the storyboard.

I already have textField which shows datePicker when selected.

after setting up the textField and datePicker, a function is called to add the “Done” button.

 
    func setUpDoneButton() {
        let toolBar = UIToolbar()
        toolBar.barStyle = .Default
        toolBar.translucent = true
        
        let space = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
        let doneButton = UIBarButtonItem(title: "Done", 
                                         style: .Done, 
                                         target: self, 
                                         action: #selector(doneDatePickerPressed(_:)))
        doneButton.tintColor = UIColor.blackColor()
        toolBar.setItems([space, doneButton], animated: false)
        toolBar.userInteractionEnabled = true
        toolBar.sizeToFit()
        addDoneButtonToDatePickers(toolBar)
    }

after setting up the button addDoneButtonToDatePickers function is called.

func addDoneButtonToDatePickers(doneButton: UIToolbar) {
        addDoneButtonToDatePickerView(txtStartDate, doneButton: doneButton)
        addDoneButtonToDatePickerView(txtEndDate, doneButton: doneButton)
        
    }
 
func addDoneButtonToDatePickerView(textField: UITextField, doneButton: UIToolbar) {
        textField.inputAccessoryView = doneButton
    }

When Done button is touched, doneDatePickerPressed function is called.

 
    func doneDatePickerPressed(sender: UIBarButtonItem) {
        print("done button clicked.")
        self.view.endEditing(true)
      }

Deleting Cell From UICollectionView

I have displayed images in UICollectionView. I have drag and drop feature added for the cell for this collectionView. Today, I will be adding functionality to delete the cell from the CollectionView when cross button is tapped.

Screen Shot 2016-08-24 at 10.53.25 AM

So, let’s begin.

The cell of collectionView have custom class called EnterCollectionViewCell

I will start by adding a closure variable called action.

 
   var action: (() -> ())?

Add @IBAction for the button in the EnterCollectionView

 
  class EnterCollectionViewCell: UICollectionViewCell {
    var action: (() -> ())?
    @IBOutlet weak var imgView: UIImageView!
    
    @IBAction func btnDeleteEnterImage(sender: UIButton) {
        action?()
    }
}

We will be assigning this closure to action variable in cellForItemAtIndexPath function.

 func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = self.enterImageCollectionView.dequeueReusableCellWithReuseIdentifier("EnterCollectionViewCell", forIndexPath: indexPath) as! EnterCollectionViewCell
        cell.imgView.image = enterImages[indexPath.row]
            cell.action = {
                    self.enterImages.removeAtIndex(indexPath.row)
                let indexPath = self.enterImageCollectionView.indexPathForCell(cell)
                self.enterImageCollectionView.deleteItemsAtIndexPaths([indexPath!]) 
            }
            return cell
}