我如何制作它,以便我的解析数据可以显示在我想要的位置?
我正在制作一个类似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)
}
}
在查询中,将对象添加到人员中:
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
,因为我不确定你正在使用哪些密钥来检索这些密钥。然而,总的想法是一样的。
您的var人员现在是一个"人员"数组
例如,你现在可以说
print(people[index].NumberofPhotos) //will return the number of photos
print(people[index].Name) //will print the person's name
等等。只要您有数组中要了解的人的索引,这将在代码中的任何地方都有效。