Deleting the proper CCSprite from an array in a schedule - ios

Before I explain my issue, I made this very not neat illustration of how my project works -
My issue is - when the time that I want to check damage is up, I want to delete that object from the array! I have tried deleting it in the checkForDamage, but as this gets called with ccTimeit just deletes every object (when I use removeObjectAtIndex:0 to get rid of the first one). I can't put it in the stopCheckDamagebecause while the damage on the first one is being checked, the player might as well have put another bomb down.
The checkForDamageworks just fine when the user gets hit, I break; it and calls stopCheckDamage. My problem is when the user does NOT get hit, because then the nonexisting sprite stays in the array and just messes stuff up. I have been thinking about every way I know of and I can't seem to find a way to delete a specific object after three seconds delay if the player doesn't get hit.
I also made a pastebin for the relevant code, which you can find here

This is just an idea,
You have an array of all of the objects. You just need to know which one to delete.
So, why not give each object a tag that gets added into the array. When you go to delete that object test its tag and delete it.
//Say your array has 10 objects in it,
//There will be 10 objects each with a tag 1-10.
//When you want to delete an object,
EDIT
//Before you add each object to the array, use a `for` loop
for (int i = 0; i < theMaxNumberOfTagsYouWant; i++)
{
self.myObject.tag = i;
[self.myArray addObject:self.myObject];
//This will loop thru as many times as you want, specify using the
//maxNumberOfTagsYouWant variable. and it will give it a tag, which'll be the value of `i`
//which gets increased for each object you insert into the array, Then when you want to
//remove the object, use the below code to remove the object using it's tag.
}
-(void)deleteObjectFromArray{
[self.myArray removeObjectAtIndex:myObject.tag];
}
Hope this helps a bit. :)

Related

How to reactivate contact between two physicsBody's

I'm trying to get two physicsBody, that are already in contact with each other (in fact they overlap because physicBody.collisionCategory = 0; for both physicsBody's), to restart/re-register/re-trigger their contact, on command. I've been unable to do this even though I tried to get body1 to move by one pixel within body2 to re-trigger the contact. I've also deleted one of the physicsBody's & re-instantiated it several seconds after that to re-trigger the contact. But nothing works. Is there some sort of method or technique to restart the contact process while both bodies are already in contact?
So, to make things a little clearer:
1) SpriteHuman walks onto SpritePanel.
2) -(void)didBeginContact:(SKPhysicsContact *)contact registers the contact.
3) I call a method that starts step 2 again, while SpriteHuman doesn't move and is still contacting SpritePanel.
You can set a BOOL property to YES for your player object if it contacts a certain object. This will allow you to continuously run whatever code you need to run. Just remember to do also set the BOOL back to NO when contact is lost.

Creating a copy of a PFObject

I am in a situation where I allow the user to download a PFObject and modify it locally, and they can then either cancel the changes or hit Done, which will dismiss the editing interface but NOT upload the changes to Parse yet. They need to hit Save on the previous screen to write all changes to the database at once.
The problem is once the PFObject is modified, you cannot revert it to its prior state without refetching from the database. But I cannot always refetch the data from the database every time they hit Cancel because the prior state may not be uploaded to Parse yet (and that's a bad UX making them wait to discard changes that are only stored locally).
For example, imagine the user taps to edit the PFObject, they make changes then hit Done, then tap on it again and further edit the object, then hit Cancel. In this case, the object needs to be reverted to its prior state, but that state has not been uploaded to Parse yet. So I cannot refetch the data from the database to revert changes otherwise it would overwrite the changes they made the first time.
To solve this problem, I would simply fetch the PFObject and store a copy of it. I'd call that the transient object. I would have another property that stores the real object. The user would modify the transient object, and when they hit Cancel I would simply set that to nil, if they instead hit Done I would set the real object equal to the transient object, and once they finally hit Save I would save the real object to the database. That way I can be sure changes aren't being made to the real object until the user commits the changes. The problem is, PFObject does not adopt the NSCopying protocol (not sure why), therefore I cannot create a copy of the PFObject. Any change I make to it affects the real object.
How can this be resolved, without modifying the app's design that allows control over when the data is committed and later saved? Is there a way to extend PFObject and adopt NSCopying, has it been done before?
I did consider storing the attributes of the object in a dictionary and allow the user to edit that instead, then upon commit set each of those attributes on the PFObject. The problem with this solution arises with complex structures. In this app, I allow the user to modify multiple arrays that contain multiple PFObjects. It's just infeasible to try to recreate and later merge changes with complex structures like this beyond a single simple PFObject.
I ran into this same problem. I did not make any changes directly to the PFObject, but rather, saved the updates in an NSDictionary. When the user clicks the done button, I then update the PFObject and saveInBackground. I don't think there is a "discard local changes" option for PFObject. If you don't do this, the only option is to throw out the existing PFObject and fetch again.
Regarding the NSDictionary comment, perhaps NSArray would be better. The implementation really depends on your specific program, but I'll give a quick example. The NSArray we'll call instructionArray. Imagine there are 3 sections in a tableView. Also assume that the data source for each section is an NSArray of PFObjects. Now say you want to set the age property of each PFObject in Section 2 to 35.
Add an NSArray object (corresponding to an instruction to carry out) to the instructionArray. This instruction to carry out could have the form
Section to update
Property to update
Value to update to
So the object you'll add is #[#(2),#"age",#(35)];
Given that the user is probably carrying out a finite amount of instructions, it might not be that performance heavy to loop through the instructionArray in cellForRowAtIndexPath so when a cell uses its corresponding PFObject to figure out what to display, it can loop through the instructions after and change what is displayed as if the PFObject was updated.
When the save button is touched, loop through the instructions and actually edit the PFObjects themselves.
If you need the instructions to handle specific objects rather than sections, then you just have to update the structure of the instructionArray. Maybe you could include an identifier to indicate what type of instruction it is.

NSArray containsObject method inconsistent results

I have an NSMutableArray called selectedUsers to which I am adding objects using a method called addUser. The objects being added are most often of type PLManagedUser (a core data managed object) although sometimes the object could be a string. In any case, if the array already contains the object, I do not want to add it to the array. Here is the code:
- (void)addUser:(id)user withTitle:(NSString *)title {
if (![_selectedUsers containsObject:user]) {
[_selectedUsers addObject:user];
}
}
I have noticed that if I try to add the same user back to back using the above method, the containsObject catches it, and duplicates are not added. However, if I add the same user (with the same memory address) after having added other objects in between, the duplicate will be added.
I am printing the contents of the array each time I add something to confirm that the duplicate objects are in the array.
My question is, is there any obvious reason why containsObject isn't consistently working here?
You need to provide the ability for an object to identify itself as equal to another object of the same class, and to do this you implement the isEqual: and hash methods.
Having said that, the explanation in your question is the opposite of what I would have expected.

iOS how to iterate over collection and get user response for each item

This sort of thing has been asked a million times in a million different scenarios, but all of them revolve around obvious ways to break up the action and bypass the problem. This may also be the case for me, but I am not seeing it.
I have a collection of Person objects that have multiple values for various attributes. I need the user to chose which of those attributes to use for each object. So, for example, I have aliases and addresses as attributes of the Person. I need to enumerate the Persons, and ask the user which alias to use, then ask which address to use, then move on to the next Person.
I thought a UIActionSheet would handle that, but it does not block.
Currently, I am thinking I need to roll my own ActionSheet subclass, and stuff the Person object into it as a model, and then set the values in the actionSheet:clickedButtonAtIndex: method, but am hoping there is some other way to do it.
Any input greatly appreciated.
Cheers!
In pseudocode, here's what I'd try. self.persons is the array to loop over, self.cursor keeps track of where you are in that array.
- (void)actionSheet:didSelectButtonAtIndex:
{
Person *p = self.persons[self.cursor]
p.property = [self propertyForButtonIndex:]
self.cursor++
[self presentSheetForCursor]
}

Getting a key in the ActionScript Dictionary

I am using a Dictionary in ActionScript as a queue, sort of, still reading most of the time as an associative container, but I need one time to make a loop to run through the whole dictionary, such as for (var key:String in queue) . Inside this for loop I perform some actions on an element and then call delete on that key.
My issue is that I would like to wait for an Event before fetching the next element in this queue. Basically my for loop runs too fast. I would like to fetch the next key all the time, but I know there is no built in method.
A solution I thought is to add a break to the loop, as the for.. in will automatically fetch the next key, but it would be a loop which always executes one time, simply to fetch the next key. This sounds a bit counter intuitive.
I hope my problem makes sense and I really look for some better ideas than what I currently have. Thanks for your help!
Rudy
haha, that is an interesting problem indeed. there doesn't seem to be any way of retrieving a list of keys from the dictionary, short of the method you've outlined. an alternative would be caching the list of the keys on the first run, but that might get out of sync and is quite untidy anyway.
i guess my main question is why can't you do what you want to do with a list? if you need 2 values (eg strings) then just make a list of objects :)
var lInfo:Object = ObjectUtil.getClassInfo(lDict);
for each(var lProperty:String in lInfo.properties)
{
var lItem:* = lDict[lProperty];
}

Resources