2016-05-04 4 views
-1

Как сделать так, чтобы мои данные синтаксического анализа могли быть показаны там, где я хочу?Как использовать мой обработанный разбор объект за пределами функции запроса

Я делаю приложение Tinder, где я запрашиваю массив с синтаксическим разбором и отображаю данные в колоде карт. У меня есть метод, где я запрашиваю массив, и в том же методе я использую возвращенный список. Однако я получаю сообщение об ошибке, потому что обратная карта вызывается до того, как данные будут завершены. «Неустранимая ошибка: неожиданно найден nil при развертывании необязательного значения»

Как я могу справиться с этим, чтобы код ожидал получения запроса?

import UIKit 
import MDCSwipeToChoose 

class ChoosePersonViewController: UIViewController, MDCSwipeToChooseDelegate { 

var people:[Person] = [] 
let ChoosePersonButtonHorizontalPadding:CGFloat = 80.0 
let ChoosePersonButtonVerticalPadding:CGFloat = 20.0 
var currentPerson:Person! 
var frontCardView:ChoosePersonView! 
var backCardView:ChoosePersonView! 
let nameData = "" 

required init?(coder aDecoder: NSCoder) { 
    super.init(coder: aDecoder) 
    let userObjectID = PFUser.currentUser()!.objectId! 
    let query = PFQuery(className:"Restaurants") 
    query.whereKey("Pointer", equalTo: userObjectID) 
    query.findObjectsInBackgroundWithBlock { 
     (objects: [PFObject]?, error: NSError?) -> Void in 
     if error == nil { 
      // The find succeeded. 
      print("Successfully retrieved \(objects!.count) scores.") 
      // Do something with the found objects 
      if let objects = objects { 
       for object in objects { 
        var nameData = object.objectForKey("Name") as? String 
        var imageData = object.objectForKey("Image") as? PFFile 
        imageData!.getDataInBackgroundWithBlock { (imageData, error) -> Void in 
         if error == nil { 
          if let imageData = imageData 
          { 
           let image = UIImage(data: imageData) 
           self.people.append(Person(name: nameData, image: image, age: 21, sharedFriends: 3, sharedInterest: 4, photos: 5)) 
           print(self.people) 
          } 
         } 
        } 
       } 
      } 
     } else { 
      // Log details of the failure 
      print("Error: \(error!) \(error!.userInfo)") 
     } 
    } 
    self.people = defaultPeople() 
} 
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { 
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 
    self.people = defaultPeople() 
    // Here you can init your properties 
    let imageData: PFFile 

} 

override func viewDidLoad(){ 
    super.viewDidLoad() 
    // Display the first ChoosePersonView in front. Users can swipe to indicate 
    // whether they like or dislike the person displayed. 
    self.setMyFrontCardView(self.popPersonViewWithFrame(frontCardViewFrame())!) 
    self.view.addSubview(self.frontCardView) 

    // Display the second ChoosePersonView in back. This view controller uses 
    // the MDCSwipeToChooseDelegate protocol methods to update the front and 
    // back views after each user swipe. 
    self.backCardView = self.popPersonViewWithFrame(backCardViewFrame())! 
    self.view.insertSubview(self.backCardView, belowSubview: self.frontCardView) 

    // Add buttons to programmatically swipe the view left or right. 
    // See the `nopeFrontCardView` and `likeFrontCardView` methods. 
    constructNopeButton() 
    constructLikedButton() 
} 

func suportedInterfaceOrientations() -> UIInterfaceOrientationMask{ 
    return UIInterfaceOrientationMask.Portrait 
} 

// This is called when a user didn't fully swipe left or right. 
func viewDidCancelSwipe(view: UIView) -> Void{ 

    print("You couldn't decide on \(self.currentPerson.Name)"); 
} 

// This is called then a user swipes the view fully left or right. 
func view(view: UIView, wasChosenWithDirection: MDCSwipeDirection) -> Void{ 

    // MDCSwipeToChooseView shows "NOPE" on swipes to the left, 
    // and "LIKED" on swipes to the right. 
    if(wasChosenWithDirection == MDCSwipeDirection.Left){ 
     print("You noped: \(self.currentPerson.Name)") 
    } 
    else{ 

     print("You liked: \(self.currentPerson.Name)") 
    } 

    // MDCSwipeToChooseView removes the view from the view hierarchy 
    // after it is swiped (this behavior can be customized via the 
    // MDCSwipeOptions class). Since the front card view is gone, we 
    // move the back card to the front, and create a new back card. 
    if(self.backCardView != nil){ 
     self.setMyFrontCardView(self.backCardView) 
    } 

    backCardView = self.popPersonViewWithFrame(self.backCardViewFrame()) 
    //if(true){ 
    // Fade the back card into view. 
    if(backCardView != nil){ 
     self.backCardView.alpha = 0.0 
     self.view.insertSubview(self.backCardView, belowSubview: self.frontCardView) 
     UIView.animateWithDuration(0.5, delay: 0.0, options: .CurveEaseInOut, animations: { 
      self.backCardView.alpha = 1.0 
      },completion:nil) 
    } 
} 
func setMyFrontCardView(frontCardView:ChoosePersonView) -> Void{ 

    // Keep track of the person currently being chosen. 
    // Quick and dirty, just for the purposes of this sample app. 
    self.frontCardView = frontCardView 
    self.currentPerson = frontCardView.person 
} 

func defaultPeople() -> [Person]{ 
    // It would be trivial to download these from a web service 
    // as needed, but for the purposes of this sample app we'll 
    // simply store them in memory. 
    return [Person(name: "Finn", image: UIImage(named: "finn"), age: 21, sharedFriends: 3, sharedInterest: 4, photos: 5), Person(name: "Jake", image: UIImage(named: "jake"), age: 21, sharedFriends: 3, sharedInterest: 4, photos: 5), Person(name: "Fiona", image: UIImage(named: "fiona"), age: 21, sharedFriends: 3, sharedInterest: 4, photos: 5), Person(name: "P.Gumball", image: UIImage(named: "prince"), age: 21, sharedFriends: 3, sharedInterest: 4, photos: 5)] 


} 
func popPersonViewWithFrame(frame:CGRect) -> ChoosePersonView?{ 
    if(self.people.count == 0){ 
     return nil; 
    } 

    // UIView+MDCSwipeToChoose and MDCSwipeToChooseView are heavily customizable. 
    // Each take an "options" argument. Here, we specify the view controller as 
    // a delegate, and provide a custom callback that moves the back card view 
    // based on how far the user has panned the front card view. 
    let options:MDCSwipeToChooseViewOptions = MDCSwipeToChooseViewOptions() 
    options.delegate = self 
    //options.threshold = 160.0 
    options.onPan = { state -> Void in 
     if(self.backCardView != nil){ 
      let frame:CGRect = self.frontCardViewFrame() 
      self.backCardView.frame = CGRectMake(frame.origin.x, frame.origin.y-(state.thresholdRatio * 10.0), CGRectGetWidth(frame), CGRectGetHeight(frame)) 
     } 
    } 

    // Create a personView with the top person in the people array, then pop 
    // that person off the stack. 

    let personView:ChoosePersonView = ChoosePersonView(frame: frame, person: self.people[0], options: options) 
    self.people.removeAtIndex(0) 
    return personView 

} 
func frontCardViewFrame() -> CGRect{ 
    let horizontalPadding:CGFloat = 20.0 
    let topPadding:CGFloat = 60.0 
    let bottomPadding:CGFloat = 200.0 
    return CGRectMake(horizontalPadding,topPadding,CGRectGetWidth(self.view.frame) - (horizontalPadding * 2), CGRectGetHeight(self.view.frame) - bottomPadding) 
} 
func backCardViewFrame() ->CGRect{ 
    let frontFrame:CGRect = frontCardViewFrame() 
    return CGRectMake(frontFrame.origin.x, frontFrame.origin.y + 10.0, CGRectGetWidth(frontFrame), CGRectGetHeight(frontFrame)) 
} 
func constructNopeButton() -> Void{ 
    let button:UIButton = UIButton(type: UIButtonType.System) 
    let image:UIImage = UIImage(named:"nope")! 
    button.frame = CGRectMake(ChoosePersonButtonHorizontalPadding, CGRectGetMaxY(self.frontCardView.frame) + ChoosePersonButtonVerticalPadding, image.size.width, image.size.height) 
    button.setImage(image, forState: UIControlState.Normal) 
    button.tintColor = UIColor(red: 247.0/255.0, green: 91.0/255.0, blue: 37.0/255.0, alpha: 1.0) 
    button.addTarget(self, action: "nopeFrontCardView", forControlEvents: UIControlEvents.TouchUpInside) 
    self.view.addSubview(button) 
} 

func constructLikedButton() -> Void{ 
    let button:UIButton = UIButton(type: UIButtonType.System) 
    let image:UIImage = UIImage(named:"liked")! 
    button.frame = CGRectMake(CGRectGetMaxX(self.view.frame) - image.size.width - ChoosePersonButtonHorizontalPadding, CGRectGetMaxY(self.frontCardView.frame) + ChoosePersonButtonVerticalPadding, image.size.width, image.size.height) 
    button.setImage(image, forState:UIControlState.Normal) 
    button.tintColor = UIColor(red: 29.0/255.0, green: 245.0/255.0, blue: 106.0/255.0, alpha: 1.0) 
    button.addTarget(self, action: "likeFrontCardView", forControlEvents: UIControlEvents.TouchUpInside) 
    self.view.addSubview(button) 

} 
func nopeFrontCardView() -> Void{ 
    self.frontCardView.mdc_swipe(MDCSwipeDirection.Left) 
} 
func likeFrontCardView() -> Void{ 
    self.frontCardView.mdc_swipe(MDCSwipeDirection.Right) 
} 
} 
+0

'для объекта в объектах {..' продолжайте извлекать все свойства, что вы используете, а затем создайте класс Person, добавьте его с помощью' people.append (your) 'in for loop. – tobeiosdev

ответ

1

В запросе, добавить свои объекты к своим людям:

for object in objects { 
    var nameData = object.objectForKey("Name") as! String     
    self.people.append(Person(name: nameData, image: nil, age: nil, sharedFriends: nil, sharedInterest: nil, photos: nil)) 
} 

В настоящее время я поставил все, кроме имени, nil, потому что я не уверен, какие клавиши вы используете для получения тех. Однако общая идея была бы такой же.

+0

Я получаю: Не могу вызвать 'append' с помощью списка аргументов типа '(String , UIImage, Int, Int, Int, Int) ' – Alexyesiam

+0

Отредактированный мой ответ – penatheboss

+0

В нем говорится, что отсутствуют аргументы и предлагается: «self.people.append (Person (name: lm, image: UIImage (named:« jake ») возраст: 21, sharedFriends: 5, sharedInterest: 5, photos: 5)) », который строит, однако переменные типа nameData по-прежнему пусты. Спасибо, что присоединился ко мне. – Alexyesiam

0

Ваши вар люди теперь массив «людей»

теперь вы можете, например, сказать,

print(people[index].NumberofPhotos) //will return the number of photos 
print(people[index].Name) //will print the person's name 

т.д. Это будет работать в любом месте в коде до тех пор, пока у вас есть индекс для человека в массиве, о котором вы хотите узнать.

+0

Я получаю: Не могу подстроить значение типа '[Person]' с индексом типа '(UnsafePointer , Int32) -> UnsafeMutablePointer ' – Alexyesiam

Смежные вопросы