Swift IOS: Save an instance of a view controller as draft with all gestures - ios

I have a custom view with UIPanGestureRecognizer, UIRotationGestureRecognizer, UIPinchGestureRecognizer
User can keep adding this views in the view controller by using add button.
Entire view controller should be saved as draft, so he can come and edit his stuff when ever he feels
I tried
Method 1 :
Saving this in var and sending back to previous Viewcontroller and getting it back. But when user restarts the app, it goes away.
Method 2 :
I tried saving in UserDefaults.
for let TxtBoxVar as UITextField in self.view.subviews
{
TxtCwtVar+=1
let TxtDataVar = NSKeyedArchiver.archivedDataWithRootObject(TxtBoxVar)
DftSdbVal.setObject(TxtDataVar, forKey: "TxtBox\(TxtCwtVar)_Key")
}
But this is ignoring all gesture of the view while saving. That means user cannot pinch or pan on the views after getting it back using beow method
let TxtCwtVal = DftSdbVal.integerForKey("TxtCwtKey")
for TxtCwtVar in 1...TxtCwtVal
{
if let VyuDtaVar = DftSdbVal.objectForKey("TxtBox\(TxtCwtVar)_Key")
{
if let VyuVar = NSKeyedUnarchiver.unarchiveObjectWithData(VyuDtaVar as! NSData) as? UITextField
{
self.view.addSubview(VyuVar)
}
}
}
Is there a better way of doing this or can we store an instance alternatively with gestures ?

Related

Xcode with swift: Is it possible to show a view controller upon another without resetting the first?

I'm creating a simple game with a pause button. I want to show another view controller with the pause screen without resetting the game view controller when i return. Every thing i have tried, has resulted in the game view controller being reset, when i press the resume button and return to the game.
Does anybody know how i can do this without resetting the game?
It's a sprite kit and swift iOS app in xcode.
You can show a pop-up based view. You can create .xib and design your pause view as you wish. Then you can resume the game without resetting anything.
Sample code:
// Set Pause Page
var pauseView = PauseView.loadFromNib() // need an extension
#IBAction func Pause(sender: UIButton) {
pauseView.btnResume.addTarget(self, action: #selector(resume(_:)), forControlEvents: .TouchUpInside)
// set place on view
view.addSubview(pauseView)
}
func resume(sender:UIButton) {
pauseView.removeFromSuperview()
}
I created a demo for you:
Full demo available on Github: Get Source Code
Create a variable in your original view controller:
var shouldReset = true
Then, when you perform a segue back, add this in your prepareForSegue:
let vc = destination as! //Your view controller
vc.shouldReset = false
In your viewDidLoad (or wherever you reset your data):
if shouldReset == true {
//Reset
}

Not allowing touch interaction on certain views?

I've got a class where I handle my touches functions on buttons, and those buttons are also a Post class.
The logic I'm going for is "If the post.user is equal to the current firebaseuser, don't allow the user to move the button"
Here's what I tried:
In my "DragButtonsClass" I've got a notification being sent to my view controller on TouchesBegan.
In the view I've got
func touchesStarted(notif : NSNotification) {
if let dict = notif.userInfo! as? [NSObject: AnyObject] {
let tag = dict["tag"]!
let tagInt = Int(String((tag))) //this is probably super sloppy, don't know how else to change an AnyObject to an Int though.
let post = postArray[tagInt! - 1]
let postbutton = self.view.viewWithTag(tagInt!)
if post.user == currentUser {
postbutton?.userInteractionEnabled = false
print("Should be working")
} else {
print("Didn't work")
}
}
}
Basically I'm assigning tags to the buttons as they're created and those tags line up with my Posts array. I'm trying to check if the Post's user is the same as the current user by sending it over and then shut off user interaction.
I'm getting "Should be working" to print out but the button is still draggable.
This seems like a super sloppy and roundabout way to do this and most importantly it isn't working. I've read that turning off userInteraction is a way to stop touches from being recognized.
Any ideas?
Ended up just setting a bool "canBeDragged" in my button's class, and when the button is created the current user's ID is compared to the information being pulled from firebase and the bool is set. Then I just checked if the button could be dragged before my touchesMoved.

Where to place code to populate a UITextfield (title field) after a segue screen returns to main screen?

I am building a Swift - Single View app. I’ve added a “segue" view to allow user to store a title line preference using NSUserDefaults. When I return to the primary view the title line isn’t filled with the new title info from NSUserDefaults. I’ve placed the code to populate the main screen title line in the viewDidLoad section noted below. Strangely enough, if I go to the “segue" screen and back to main screen again without making changes then it shows up. Where can I place code to get the title line stored in my preferences segue screen to show up when I go back to the main view? Here is my code that works, but only after going back and forth from the seague twice. Thanks for any help.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let defaults = NSUserDefaults.standardUserDefaults()
let titlePref = defaults.objectForKey("usertitleLineKey")!
titleLine.text = titlePref as! String
}
You should use viewWillAppear or viewDidAppear callback methods to refresh any content in your view when or just before it shows up. viewDidLoad will only be called once when the view is initialised on to memory.
Try this code:
override func viewWillAppear() {
let defaults = NSUserDefaults.standardUserDefaults()
let titlePref = defaults.objectForKey("usertitleLineKey")!
titleLine.text = titlePref as! String
}

Display a particular user and all their information stored on parse on a different View Controller in Swift

In my app each user sets up a profile page and all this info is stored on Parse. When the current user hits a button it segues to a tableViewController that displays in cells all the other users on the app. In each cell there is a button which the user presses to view the full profile page of the user that they have selected. I have a VC set up to hold all the info I just don't know how to display the particular user that the current user has selected into it. How do I single out the chosen users information? I have read the Parse documentation on relational queries but I can't seem to get my head around it. https://parse.com/docs/ios/guide#queries-relational-queries
So in finer detail basically all my users are displaying on a VC. It has name and profile picture, when the user clicks on the info button beside a certain user it should open a new screen and display all of this users information stored on Parse.
I have tried creating a static outside the class
struct Data { var OtherName:String! var id:String! }
And then in my ViewDidLoad:
let query = PFQuery(className: "_User")
// otherQuery.orderByDescending("createdAt")
query.whereKey("username", notEqualTo:PFUser.currentUser()!.username!)
query.findObjectsInBackgroundWithBlock { (users: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// success
print(users!.count)
for user in users! {
self.imageFiles.append(user["image"] as! PFFile)
self.instrumentText.append(user["instrument"] as! String)
self.nameText.append(user["name"] as! String)
self.ageText.append(user["age"] as! String)
// self.locationText.append(user["location"] as! PFGeoPoint)
var singleData = Data()
singleData.id = user.objectId
singleData.OtherName = user["name"] as! String
print("\(singleData)")
} // users
Then on the VC that the info button segues to I am trying to call it and upload each label with just the user that was selected.
self.userName.text = "" as String
But the "" is staying blank.
Then I was thinking maybe if I add that when the more info button is pressed that the user it was pressed on gets chosen and is added to a chosen string on Parse and then I just have to call the user from the chosen string when I am on the chosen users profile page and call the info that way and then when the user clicks the back button the user is no longer chosen. It just seems like I would be adding and taking away a lot of users to "chosen" in Parse is there a better way?
I am able to display all the users info but how do I just display a chosen user from Parse without using the objectId because at the top of each cell it will return a different user here each time depending on settings previously set on a different VC such as only show users in a certain age bracket etc. I know I must set an Id of some sort on button touched but I am at a complete loss. The only online help out there that I can find is set for other languages eg. https://parse.com/docs/js/guide#users-querying>
So I guess my question is :
1.Does anyone know a tutorial they could point me towards.
2.Does anyone know how I even get started and I can go from there myself.
3.Can anyone help?
*Swift and Parse newbie little to no experience in other languages.
New code in firstVC:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "userProfileDetailsSegue" {
if let indexPath = resultsPageTableView.indexPathForSelectedRow {
let controller = (segue.destinationViewController) as! UserProfileDetailsViewController
***error here: UserProfileDetailsViewController.userToShowDetail = indexPath.row
//line above is the one I can't get to work it needs to equal to the cell selected?
}
}
}
New Code in destinationVC:
var userToShowDetail: PFUser? {
didSet {
self.configureView()
}
}
func configureView() {
// Update the user interface for the detail item.
if let userToShowDetail: PFUser = self.userToShowDetail {
if let label = self.userName {
nameText.append(userToShowDetail["name"] as! String)
// self.nameText.append(user["name"] as! String)
}
}
}
You're going to need to do a couple of things for this to work. First, in the view controller that you're using to show another user's information, you need to set a property like var userToShowDetail: PFUser?. Then in your view with all of the users of your app, you need to create a segue to bring them from the current view to the detail view. Assuming you're using a TableView, you can connect just one prototype cell to the detail view you're trying to navigate. Then you'll need to override prepareForSegue and set the new view controller's user equal to the user at the row that was selected. I don't know how you're storing your objects of user's of your app, but you should probably be able to do something like this.
override fun prepareForSegue(segue: UIStoryboardSegue) {
if segue.identifer == "segueToShowDetailInfo" {
//get the index path for the row that was selected
let indexPath = self.tableView.indexPathForSelectedRow()
//get the PFUser object for that particular row
let userToShow = self.appUsers[indexPath.row]
//create your new view controller
let newVc = segue.destinationViewController as! DestinationVC
//assign the new vc's property to your object
newVc.userToShowDetail = userToShow
}
}
But in your query, you probably shouldn't have a separate array of the the different parts of the user's data. You should just make one array, call it var appUsers = [PFUser]() and then when you get a user back in your query, just say:
for user in users! {
self.appUsers.append(user) as! PFUser
}
There, now you have a whole array of objects that holds a reference to every user. When someone is using your app, and selects a cell, then you can perform the prepare for segue method as above.
Note that I also noticed you have a didSet on your variable in your new view controller. Calling a function to update the UI after this variable is set will not work, and may crash, because the view controller doesn't have a window yet.

UINotification selecting from handleActionWithIdentifier display specific viewController

I am new to iOS programming and I only understand swift language for now. For my app, I have set up user, local and remote notifications. The local notifications have 2 actions, 1 to dismiss and the other is to direct the user to a specific viewController.
My viewController hierarchy to the specific viewController I want to display is tabBarController -> (2nd tab) tableViewController -> (one of the many tablecells) viewController
After Richard's suggestion, I have simplified my code with the above hierarchy. I have performed a background fetch to my server in response to a remote push notification and save content locally before creating a local notification to inform the user. I have managed to set up to the point where I guide the user to the correct Tab on the tabViewController using self.window?.rootViewController.selectedIndex = 1 within application:handleActionWithIdentifier in App delegate.
How do I proceed with selecting the correct tablecell assuming that the local notification holds an index that can be used?
Edit:
After some tinkering, I managed to get the viewController I wanted to be displayed.
if var tabb = self.window?.rootViewController as? UITabBarController {
tabb.selectedIndex = 1
var controllers = tabb.childViewControllers
for controller in controllers {
if let navcon = controller as? UINavigationController {
if let tblvc = navcon.childViewControllers.first as? QuestionnaireTableViewController {
tblvc.becomeFirstResponder()
tblvc.moveUserToQuestionnaire(questionID)
}
}
}
}
func moveUserToQuestionnaire(questionID : String) {
var list = questionnaireObj.getQuestionnaireListData()
for item in list {
var selected = item["questionnaire_id"] as! NSString as String
if selected == questionID {
selectedUserID = item["study_id"] as! String
selectedReplyBatchID = item["reply_batch_id"] as! NSNumber
selectedQuestionnaireID = questionID
performSegueWithIdentifier("SelectQuestionnaire",sender:self)
break
}
}
}
If this is a correct method to use, please inform me. Thanks! Hope it also helps someone in the process. =)

Resources