Yalantis / Koloda

KolodaView is a class designed to simplify the implementation of Tinder like cards on iOS.
https://yalantis.com
MIT License
5.37k stars 806 forks source link

Koloda and Parse DataStore - I am fetching data but I not able to display the results #96

Closed Viorel84 closed 8 years ago

Viorel84 commented 8 years ago

Hi,

I am using Koloda to fetch an Array of Objects into the Card so every card gets a row from my database. I have seen the networking exemple with Alamofire and tried my own code that implements Parse using the same exemple. It is getting the objects from Parse but I have not been able to display them into the cards. Weird, actually I have no errors and the console display "Successfully retrieved 5 objects", but this is only the loadData() function.

What am I basically trying to achieve: I have (MyView.xib, MyView.swift) that provides the labels. (What I want, is to retrieve from the array to texts into the labels from xib)

I am retrieving the objects but I have not been successful on displaying them into the card:

Successfully retrieved 5 posts.
Optional("EvUICgRQ6E")
Optional("5kC0FLKQON")
Optional("1Uyxb2M1Et")
Optional("aeJpRCG7Qn")
Optional("GDmGh3IULm")

Some Errors: If I am returning the "numberOfCards" --- I am getting this error:

fatal error: Array index out of range
(lldb) 

If I return: "return UInt (self.data.count)" I am not getting any errors but the cards are not being displayed at all.

I am a bit of a newbie, but pointed into a good direction I will be able to get it done.

This is my ViewController.swift code:

//
//  ViewController.swift
//  TinderCardsSwift
//
//  Created by Eugene Andreyev on 4/23/15.
//  Copyright (c) 2015 Eugene Andreyev. All rights reserved.
//

import UIKit
import Koloda
import pop
import Parse
import ParseUI

private var numberOfCards: UInt = 3

class retriveData {
    var labelText = ""
    var label2Text = ""

    init(){
    }
    convenience init(_dictionary: Dictionary<String, AnyObject>){
        self.init()

        let getObjects = PFObject()
        labelText = (getObjects.objectForKey("nameEnglish") as? String)!
        label2Text = (getObjects.objectForKey("capital") as? String)!

    }

}

class ViewController: UIViewController, KolodaViewDataSource, KolodaViewDelegate {

    @IBOutlet weak var kolodaView: KolodaView!

    @IBOutlet weak var menuLeft: UIBarButtonItem!
    @IBOutlet weak var searchRight: UIBarButtonItem!

    var data = Array <retriveData>()

    //MARK: Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()

        kolodaView.dataSource = self
        kolodaView.delegate = self

        menuLeft.target = self.revealViewController()
        menuLeft.action = Selector("revealToggle:")

        searchRight.target = self.revealViewController()
        searchRight.action = Selector("rightRevealToggle:")

        self.modalTransitionStyle = UIModalTransitionStyle.FlipHorizontal

        loadData()
    }

    //MARK: Geting Data From Parse and displaying 5 posts with a print result - WORKING
    func loadData (){

        let query = PFQuery(className:"Countries")
        query.orderByAscending("nameEnglish")
        query.findObjectsInBackgroundWithBlock {
            (objects:[PFObject]?, error:NSError?) -> Void in
            if error == nil {
                // The find succeeded.
                print("Successfully retrieved \(objects!.count) posts.")
                // Do something with the found objects
                if let objects = objects {
                    for object in objects {
                        print(object.objectId)
                    }
                }
            } else {
                // Log details of the failure
                print("Error: \(error!) \(error!.userInfo)")
            }
        }
        self.kolodaView.reloadData()
    }

    @IBAction func logOut4(sender: AnyObject) {

        // Send a request to log out a user
        PFUser.logOut()

        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            let viewController:UIViewController = UIStoryboard(name: "SlideMain", bundle: nil).instantiateViewControllerWithIdentifier("Login_Platform")
            self.presentViewController(viewController, animated: true, completion: nil)

        })

    }

    override func viewWillAppear(animated: Bool) {

        if (PFUser.currentUser() == nil) {
            dispatch_async(dispatch_get_main_queue(), { () -> Void in

                let viewController:UIViewController = UIStoryboard(name: "SlideMain", bundle: nil).instantiateViewControllerWithIdentifier("Login_Platform")
                self.presentViewController(viewController, animated: true, completion: nil)

            })
        }

    }

    //MARK: IBActions
    @IBAction func leftButtonTapped() {
        kolodaView?.swipe(SwipeResultDirection.Left)
    }

    @IBAction func rightButtonTapped() {
        kolodaView?.swipe(SwipeResultDirection.Right)
    }

    @IBAction func undoButtonTapped() {
        kolodaView?.revertAction()
    }

    //MARK: KolodaViewDataSource
    func kolodaNumberOfCards(koloda: KolodaView) -> UInt {
        //return numberOfCards
        return UInt (self.data.count)
    }

    func kolodaViewForCardAtIndex(koloda: KolodaView, index: UInt) -> UIView {
        //return UIImageView(image: UIImage(named: "Card_like_\(index + 1)"))
        /*return (NSBundle.mainBundle().loadNibNamed("MyView",
            owner: self, options: nil)[0] as? UIView)!*/

        let dataView = NSBundle.mainBundle().loadNibNamed("MyView",
            owner: self, options: nil)[0] as? MyView
         let parseData = data[Int(index)]
        dataView?.label1?.text = parseData.labelText
        dataView?.label2?.text = parseData.label2Text

        return dataView!

    }
    func kolodaViewForCardOverlayAtIndex(koloda: KolodaView, index: UInt) -> OverlayView? {
        return NSBundle.mainBundle().loadNibNamed("OverlayView",
            owner: self, options: nil)[0] as? OverlayView
    }

    //MARK: KolodaViewDelegate

    func kolodaDidSwipedCardAtIndex(koloda: KolodaView, index: UInt, direction: SwipeResultDirection) {
    //Example: loading more cards
        if index >= 3 {
            numberOfCards = 6
            kolodaView.reloadData()
        }
    }

    func kolodaDidRunOutOfCards(koloda: KolodaView) {
    //Example: reloading
        //kolodaView.resetCurrentCardNumber()
        loadData()
    }

    func kolodaDidSelectCardAtIndex(koloda: KolodaView, index: UInt) {
        UIApplication.sharedApplication().openURL(NSURL(string: "http://yalantis.com/")!)
    }

    func kolodaShouldApplyAppearAnimation(koloda: KolodaView) -> Bool {
        return true
    }

    func kolodaShouldMoveBackgroundCard(koloda: KolodaView) -> Bool {
        return true
    }

    func kolodaShouldTransparentizeNextCard(koloda: KolodaView) -> Bool {
        return true
    }

    func kolodaBackgroundCardAnimation(koloda: KolodaView) -> POPPropertyAnimation? {
        return nil
    }

}

This is MyView.swift

//
//  MyView.swift
//
//
//  Created by Viorel Petrisor on 12/29/15.
//  Copyright © 2015 Viorel Petrisor. All rights reserved.
//

import UIKit

class MyView: UIView {

    @IBOutlet var label1: UILabel!
    @IBOutlet var label2: UILabel!
    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func drawRect(rect: CGRect) {
        // Drawing code
    }
    */

}

I would deeply appreciate some help!

SvshX commented 8 years ago

I'm having the same issue! Has anybody worked that out?

Viorel84 commented 8 years ago

Nope! If you are using Parse forget about it, it is closing down... And the support from Koloda, well, there is no support :)

SvshX commented 8 years ago

Any alternatives for a backend provider to fetch custom cards and connect them with swipe function?

Viorel84 commented 8 years ago

I would recommend Firebase https://www.firebase.com/ . It's google... (and it's the same thing as Parse). Or your own MySQL server and fetch data with a json file.

SvshX commented 8 years ago

Thanks! The thing is that I already built user authentication with ParseUI Login, so now I have to scrap it and start all over again. It would be nice if someone had an example for Koloda connecting with a backend provider to allow custom cards rather than just images. I think it is a common approach that many developers use in their projects.

Viorel84 commented 8 years ago

It is the only approach... Unfortunately you will have to take it from the beginning because Parse will be available only this year until it will be closed. If you will use Firebase you can find a login demo here: https://github.com/firebase/login-demo-ios for iOS. The only thing is that all the examples are for Objective C and not for Swift.

SvshX commented 8 years ago

Yeah I already noticed that. I just started with iOS (and Swift) so I'm not skilled in Objective C. But how did you solve your Koloda issue?

SvshX commented 8 years ago

An alternative is also to migrate the Parse server to Heroku and MongoDB, hence you can reuse Parse SDK and all. I really want to make Koloda linked with Parse work.

I may try both options, an own server as well as firebase.

AEugene commented 8 years ago

Hi @Viorel84 . You have some common issues: 1) You're reloading Koloda right after call of asynchronous function, so it doesn't wait for response from query. 2) You don't map your response to RetrieveData class 3) You don't save response of query.

SvshX commented 8 years ago

I worked my issue out. Had some nonsense between CustomView file and CustomView xib. Thanks for this great library!