yes i know this question gets asked all the time, but my inexperience has prevented me from finding the answer. I'm simply trying to remove an object from the screen if a button is clicked -
public function but1click(evtObj:MouseEvent)
{
trace("button one clicked");
if (gracestate == "grace")
{
removeChild(grace);
trace("grace removed");
}
}
I traced the parent of the object (grace) and it came back as null. This is driving me nuts, and help would be much appreciated!
The question is unclear though the most likely problem seems to be you're storing a value into grace that is being garbage collected/deleted.
If you create a variable inside a function but no reference to that variable exists outside the function it will be GC'd. Basically anything that isn't referred to by something else is deleted, the only object this isn't true for is the timeline. This stops the flash player lagging and avoids errors when the RAM becomes full. Thus:
function createGrace () {
var grace = new Object();
addChild(grace);
}
trace (grace); // returns null
var grace:Object;
function createGrace () {
grace = new Object();
addChild(grace);
}
trace (grace); // returns [Object]
Related
I have a problem that I still can't solve and it just doesn't want to work. Basically I have to convert a function into a composable.
In the old function I launched a Coroutine and at the result, I changed context and then continued with my processes. In compose I don't understand how I have to "change context" in order to continue.
Old code:
fun getMyView( activity: Activity
) {
backgroundCoroutineScope.launch {
//some stuff here
withContext(coroutineContext) {
startSearchView(
activity
)
}
}
}
New not working code:
#Composable
fun getMyView( content: #Composable() () -> Unit) {
LaunchedEffect(key1 = Unit) {
//some stuff here like old funciont
//here I don't know how to change context, wait the end and go ahead. startSearchViewis a composable function too
// i want to use it to populate my screen
startSearchView(
content
)
}
}
How can I solve it? Thanks
Seems like you are trying to asynchronously "create" composable function, but UI emitting doesn't work this way. Like #PylypDukhov suggested, you should keep a mutable state holding nullable result of your async action. After loading the data set this state. Then in composable just do something like:
if (data != null) {
SearchComposable(data)
}
This way the composable will be emitted after the data is loaded
I am new to Reactive programming, and I'm trying to observe a boolean value from my ViewModel in order to let my ViewController know when to start/stop the app's loader screen.
It's fairly simple and I want to use this method to avoid unnecessary delegates, since my ViewModel holds the business logic and my ViewController handles the UI.
My problem is this compiler error: Ambiguous reference to member 'subscribe'.
It also adds the two possible candidates, as you can see in the image below:
In my ViewModel, I've declared the observable as PublishSubject:
let done = PublishSubject<Bool>()
And I use it while observing another stream:
func subscribe() {
done.onNext(false)
anotherObservable.subscribe(
// other events observed here but not relevant to this matter
onCompleted: {
self.done.onNext(true)
}).addDisposableTo(rx_disposeBag)
}
And, finally, this is how I'm trying to handle it in the ViewController:
self.model.done.subscribe(
.onNext { isDone in
if isDone {
self.removeLoader()
}
}).addDisposableTo(rx_disposeBag)
I believe there is something simple I'm probably missing, so any help is appreciated.
In your second subscribe should be:
self.model.done.subscribe(onNext: { isDone in
if isDone {
self.removeLoader()
}
}).addDisposableTo(rx_disposeBag)
(I'm sorry if this question is kind of confusing/imprecise. I'm just learning advanced CoreData usage and I don't know the terminology and stuff very well).
I have a singleton Game that holds certain data you need during the game. For example, you can access currentSite (Site is a CoreData Entity) from there to get the Site the user is currently at:
// I created the Site in a background queue (when the game started), then saved the objectID and here I load the objectID
public var currentSiteObjectID: NSManagedObjectID {
let objectIDuri = UserDefaults.standard.url(forKey: Keys.forGameObject.currentSiteObjectIDURI)!
return appDelegate.persistentContainer.persistentStoreCoordinator.managedObjectID(forURIRepresentation: objectIDuri)!
}
// managedObjectContext is the one running on the main queue
public var currentSite: Site! {
return managedObjectContext.object(with: currentSiteObjectID) as! Site
}
You see, I retrieve the currentSite by using the managedObjectContext.object(with:) method.
The documentation of this method says:
Returns the object for a specified ID.
If the object is not registered
in the context, it may be fetched or returned as a fault. (...)
I'm not quite sure about the following:
// Each Site has resources that you can access like this
print(Game.shared.currentSite!.resourceSet!.iron)
appDelegate.persistentContainer.performBackgroundTask { (context) in
let currentSite = context.object(with: Game.shared.currentSiteObjectID) as! Site
// Here I increase the iron resource
currentSite.resourceSet!.iron += 42
do {
try context.save()
} catch let error as NSError {
fatalError("\(error.debugDescription)")
}
DispatchQueue.main.async {
print(Game.shared.currentSite!.resourceSet!.iron)
}
}
The second print function is using the managedObjectContext of the main queue (which is different to the private one used inside performBackgroundTask {...}).
It actually does print:
50 // the start value
92
My question: Is it guaranteed that managedObjectContext.object(with:) returns the current object (that is up-to-date), even if it has been changed in another context? The documentation says that it will be fetched if it's a new object that's not known to the context.
But what if an object changes?
I'm not sure if it's just a coincidence that the example code from above is working like expected.
Thanks for any help/explanation! I'm eager to learn about this kind of stuff.
No it is not guaranteed. If managed object is already registered in context then it will return this object. What's more, if object with given id (NSManagedObjectId) doesn't exist in persistent store then your app will crash as soon as you try to use any of its properties.
I get the above message in XCode 4.6. I've done a pretty thorough search and but nothing seems to match the exact circumstances surrounding my issue. Admittedly, I'm relatively new to iOS dev, and memory-management has never been my strong suit, but this just has me completely miffed.
I have an instance variable theLink which is defined in the class Game as follows:
#interface Game : NSObject
// Class objects
#property(nonatomic,retain) NSMutableArray *queryItems;
#property(nonatomic,retain) NSMutableArray *theArray;
#property(nonatomic,retain) NSString *theLink;
#property(nonatomic,retain) NSString *thePath;
theLink is set in the makeGame method which is called in the method initialiseGame in my view controller:
- (void) initialiseGame
{
bool gameCreated = FALSE;
while (!gameCreated)
{
gameCreated = [theGame makeGame:#"ptl"];
}
[loadingIndicator stopAnimating];
[loading setText:#"Tap to Start"];
[self performSelector:#selector(setLabels) withObject:nil afterDelay:0.0];
}
(Note: the performSelector afterDelay is used to allow the view to update before continuing. Bit of a hack but I couldn't work out a better way!)
The app then loads the game, and when the user taps the screen to start, the next method which is called from the view controller is:
- (void) setupLink
{
...
for(int i=0; i<[theGame.theLink length]; i++) {
...
}
}
It is on this reference to theGame.theLink where I'm am getting the crash.
What has me most confused is that if I call theGame.theLink from inside the initialiseGame method, it is displays correctly, and also calling any other variable from the Game class (such as thePath or theArray works perfectly, so theGame object has not been deallocated in it's entirety, only the variable theLink.
It seems to me that the variable is being deallocated somewhere as the view controller is being updated. I haven't released the variable, and can't work out why only this variable is being deallocated. As I said at the start, memory-management is not my strength!
Any help/ideas would be hugely appreciated. Let me know if you require any more details.
Thanks heaps,
Andrew
EDIT: Setting of theLink within makeGame
- (bool) makeGame:(NSString*)gameType
{
...
[self getLink];
}
- (void) getLink
{
...
if (... && ((arc4random() % 10) > 8))
{
theLink = #"Animals";
}
}
There are many different ways theLink may be set, depending on random numbers and other factors. This is the most basic form which simply sets it to a static string. It doesn't matter how theLink is set or what it is set to, the program always crashes at the same point.
If theLink is being set to the parameter being passed to it ,#"ptl" or some similar temporary string, it will give you a problem, because it is just a pointer pointing at the current location that is holding #"ptl". After the makeGame method is completed, your system will assume that it is all done with #"ptl" and just free it up.
When you make an #"stringwhatever" in your code, it is supposed to be the equivalent of making an NSObject that is an immutable literal instance of #"stringwhataver". It should, in theory handle all the reference counting in a nice way, but when you are doing your own memory management, there are so many ways to lose count of your references.
There's a pretty simple rule to follow. If you've declared properties, access them via the property. To do otherwise (as you are doing above, with theLink = ...) bypasses all of the memory management built into the property accessors.
self.theLink = ...
Would have solved this problem under MRC. Switching to ARC has "solved" your problem without you understanding the root cause.
Iv been trying to pass arguments through an addEventListener event in actionscript such as...
target.addEventListener("pComp", rakeSoil(target));
but i get errors.
Iv tried to google but no luck :/
Thanks for replying if you do :)
The target is already passed as part of the event, either event.currentTarget or event.target will be what you want.
If you want something else passed, create a custom event. Add the property to the custom event.
Try adding an additional method as your event listener:
target.addEventListener ("pComp", targetListener);
...
private function targetListener (event:Event):void {
rakeSoil (event.currentTarget);
}
How this is what you want:
{
var target:EventDispatcher = ...;
Function rakeSoil = function (e:Event):void
{
// handle target
}
target.addEventListener("pComp", rakeSoil);
}
rakeSoil is a first class function(or closure), when event is dispatched, it will be invoked, and you can access 'target' in it.
EDIT:
Have a look at Closure (computer science)
I have always found anonymous functions to be more trouble than they are worth. I would simply follow the standard event handler code layout. It's more formal and takes a little more effort up front, but there is no ambiguity and it is far more readable when you return to it a year from now (reduces head-scratching duration):
// Target extends EventDispatcher
private var target:Target;
public function listenToTarget();
{
target = new Target();
target.addEventListener("pComp", pCompHandler);
}
private function pCompHandler(event:Event):void
{
target.rakeSoil();
}
Although, now that I look at it more closely, why are you having this object do something that Target should be capable of handling internally on its own?