associate object tutorial
"The tutorial link gave me a clear concept of object-c runtime associate object"
After reading the example code below, I have a small question.
- (void)setAssociatedObject:(id)object
{
objc_setAssociatedObject(self, #selector(associatedObject), object,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (id)associatedObject
{
return objc_getAssociatedObject(self, #selector(associatedObject));
}
If your using ARC in iOS, do we need to add memory handling by ourselves?
Thanks in advance
The call you have to objc_setAssociatedObject will cause the object to be retained — that's the OBJC_ASSOCIATION_RETAIN_NONATOMIC part. That being the specified behaviour, it'll also automatically be released when the object with which it is associated is released.
So you don't need to do any further memory handling whether you're using ARC or not (subject to the caveat that if you wanted this to act like a copy property, you'd obviously need to add copying, which would look different under ARC and non-ARC).
Related
I'm trying to get the image associated with a view but Xcode returns me an error. Here is the code:
#IBOutlet var imageView: IKImageView // Link to the image view.
func saveImage() {
var newImage: CGImageRef = imageView.image() // Line with an error.
}
I have a awakeFromNibfunction to set the image in the view. The code above returns me 'Unmanaged<CGImage>' is not convertible to 'CGImageRef'.
I know that types are optional in Swift but I don't understand why I get this error, the IKImageView Class Reference clearly said that get IKImageView's image return a CGImageRef.
This has to do with the bridging of Objective C APIs into Swift. The Swift versions of an API have been bridged (mostly automatically, I believe) by converting the original Objective C headers into a Swift version. In many cases, the conversion can work out what kind of value you're going to get back, and therefore in Swift you get a "normal" type that you can use as you'd expect.
However, the conversion is still a work in progress. In this case, what you're seeing is a type used to help you manage memory manually when the conversion process doesn't know whether you're going to get back an object that's been retained for you or not, because the API doesn't have the conventional annotation that it could use to figure it out.
The Unmanaged type effectively says "you have to tell me what to do with the contained value to get the memory management right". As soon as you get an Unmanaged value, you should call either one of its two methods:
takeUnretainedValue()
takeRetainedValue()
...depending on whether the object you get back was a "+0" or "+1". So, you're expected to do something like:
var newImage: CGImage = imageView.image().takeUnretainedValue()
And as soon as you've done that (which you should do pretty much immediately), you've given Swift enough of a hint that it can now appropriately manage the object correctly with ARC, and got yourself a valid reference of the right type.
This is touched on briefly at the end of the "Swift Interoperability in Depth" WWDC video from this year.
Look at the image() method in the new version of the IKImageView reference that shows Swift declarations and you'll see it returns an Unmanaged<CGImage>!. That means that ImageKit isn't set up such that the compiler can automatically infer CoreFoundation memory management semantics on its API. (This affects both Swift translation and ObjC implicit ARC bridging.) It should, so that'd be a good bug to file.
The Swift type Unmanaged<T> is how you interact with CF types when the compiler can't automatically infer their ARC behavior. To get at the underlying type, call either takeUnretainedValue() or takeRetainedValue() — you have to choose which depending on whether the API you're calling is known to already be retaining the value it returns. Exciting guesswork! (Again, eliminating guesswork would be a good bug to file.) You can read more about this in Using Swift with Cocoa and Objective-C.
Anyway, in this case you can probably expect that IKImageView is not incrementing the retain count of the CGImage when providing it, so you can unwrap the Unmanaged like so:
var newImage: CGImage = imageView.image().takeUnretainedValue()
Also note you don't need the Ref suffix when working with CF types in Swift. (CGImageRef is a typealias to CGImage.) Swift lets you work with CF types as if they're Swift objects (instead of as C pointers to opaque C types).
I am trying to create a Visual Studio extension which handles a multi-language content type. Much like some mvc-templates and Django or ASP.NET which a certain part of the code is in another language.
I know that I should use Projection and I already checked Django for Visual Studio extension but the solution there includes creating a Language Service and going to the trouble of creating all bits and pieces related to a code editor. Here I am trying to achieve the same goal just by using MEF.
I know that you can use IProjectionBuffer CreateProjectionBuffer() to create a projection but the question is how to replace the current TextBuffer with the created one and when is the best time to do it.
Also one may expect that if he specifies a base definition of type "projection" like this:
[Export]
[Name("Whatever")]
[BaseDefinition("code")]
[BaseDefinition("projection")]
internal static ContentTypeDefinition WhateverContentType = null;
the received TextBuffer in providers to be of type IProjectionBuffer (after all IProjectionBuffer is inherited from ITextBuffer). Which are not and it seems that a projection base definition has no effect what so ever.
So if I want to rephrase my question in a tldr version:
How and when do you apply an IProjectionBuffer to current view (using MEF and without creating an editor instance)?
So if I understand your question correctly, the answer is "you don't." A IWpfTextView is bound to a implementation of ITextBuffer (or a derived type, like IProjectionBuffer) at creation time, and can't be changed. Even if you could, many other extensions and language services would be most surprised by this and would probably crash.
To address your second question about content types: simply declaring you have a base content type of "projection" doesn't make you a projection buffer. All that really states is you might be creating projection buffers of that type, and when you do you want some extra ITagger support so taggers project through to the source buffers as you might expect them to.
I am extremely confused about resource management in C++/CLI. I thought I had a handle (no pun intended) on it, but I stumbled across the auto_gcroot<T> class while looking through header files, which led to a google search, then the better part of day reading documentation, and now confusion. So I figured I'd turn to the community.
My questions concern the difference between auto_handle/stack semantics, and auto_gcroot/gcroot.
auto_handle: My understanding is that this will clean up a managed object created in a managed function. My confusion is that isn't the garbage collector supposed to do that for us? Wasn't that the whole point of managed code? To be more specific:
//Everything that follows is managed code
void WillThisLeak(void)
{
String ^str = gcnew String ^();
//Did I just leak memory? Or will GC clean this up? what if an exception is thrown?
}
void NotGoingToLeak(void)
{
String ^str = gcnew String^();
delete str;
//Guaranteed not to leak, but is this necessary?
}
void AlsoNotGoingToLeak(void)
{
auto_handle<String ^> str = gcnew String^();
//Also Guaranteed not to leak, but is this necessary?
}
void DidntEvenKnowICouldDoThisUntilToday(void)
{
String str();
//Also Guaranteed not to leak, but is this necessary?
}
Now this would make sense to me if it was a replacement for the C# using keyword, and it was only recommended for use with resource-intensive types like Bitmap, but this isnt mentioned anywhere in the docs so im afraid ive been leaking memory this whole time now
auto_gcroot
Can I pass it as an argument to a native function? What will happen on copy?
void function(void)
{
auto_gcroot<Bitmap ^> bmp = //load bitmap from somewhere
manipulateBmp(bmp);
pictureBox.Image = bmp; //Is my Bitmap now disposed of by auto_gcroot?
}
#pragma unmanaged
void maipulateBmp(auto_gcroot<Bitmap ^> bmp)
{
//Do stuff to bmp
//destructor for bmp is now called right? does this call dispose?
}
Would this have worked if I'd used a gcroot instead?
Furthermore, what is the advantage to having auto_handle and auto_gcroot? It seems like they do similar things.
I must be misunderstanding something for this to make so little sense, so a good explanation would be great. Also any guidance regarding the proper use of these types, places where I can go to learn this stuff, and any more good practices/places I can find them would be greatly appreciated.
thanks a lot,
Max
Remember delete called on managed object is akin to calling Dispose in C#. So you are right, that auto_handle lets you do what you would do with the using statement in C#. It ensures that delete gets called at the end of the scope. So, no, you're not leaking managed memory if you don't use auto_handle (the garbage collector takes care of that), you are just failing to call Dispose. there is no need for using auto_handle if the types your dealing with do not implement IDisposable.
gcroot is used when you want to hold on to a managed type inside a native class. You can't just declare a manged type directly in a native type using the hat ^ symbol. You must use a gcroot. This is a "garbage collected root". So, while the gcroot (a native object) lives, the garbage collector cannot collect this object. When the gcroot is destroyed, it lets go of the reference, and the garbage collector is free to collect the object (assuming it has no other references). You declare a free-standing gcroot in a method like you've done above--just use the hat ^ syntax whenever you can.
So when would you use auto_gcroot? It would be used when you need to hold on to a manged type inside a native class AND that managed type happens to implement IDisposable. On destruction of the auto_gcroot, it will do 2 things: call delete on the managed type (think of this as a Dispose call--no memory is freed) and free the reference (so the type can be garbage collected).
Hope it helps!
Some references:
http://msdn.microsoft.com/en-us/library/aa730837(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/481fa11f(v=vs.80).aspx
http://www.codeproject.com/Articles/14520/C-CLI-Library-classes-for-interop-scenarios
In a Windows Phone 7 app, the PhoneApplicationService.Current.State object is declared as an IDictionary, and is implemented as a Dictionary. I was really hoping to get notified when any state changes occur. (I realise I could build my own state collection somewhere else and do whatever I want, but I'm retrofitting this into existing code.)
Is there any way to get that State object set to an ObservableDictionary instead of a Dictionary, so I can attach to it and get notified when the collection changes?
I'm guessing the answer will be 'no' but just want to check I haven't missed something :)
Thanks,
John
You can't change the existing implementation, but you could create a wrapper class which implements IObservable but uses PhoneApplicationService.Current.State internally.
This way, you wouldn't have to build a complete state persistence soution yourself and could implement the ObservableDictionary as best meets your needs.
Ok, I am creating a document-based application in Cocoa and the document's file type is actually a package. Within that package is an XML settings file, a SQLite database and a zip file which is downloaded at runtime. Now the only thing that changes, really, is the XML settings file as the other ones can be recreated at run-time.
Each one of these packages will have one and only one window, hence my desire to use document-based. These files can also be copied, renamed, moved, etc. just like any other file that is part of such an architecture.
But I am completely lost as how to implement this in the Documentation Framework! It seems everywhere I look in the docs it's always talking about in-memory representations of the files which you then write out using the path presented to you in one of the NSDocument overrides (since Cocoa may move it, etc.) But again, I'm using a SQLite database that sits on disk, not in memory.
I have looked all over for overridable methods that would still give me things like dirty-state checking of the doc, open and save file dialog support and the like, but I can't seem to find anything that just says 'Here's a file URL... Open it as you see fit' althought I did get close at the application's delegate level, at least for the opening.
So let's assume that's working as expected. How do I implement the save/save-as where I want to control everything that is written to disk or not? I don't want to (not can I) mess around with data structures or the like. I just want to be given a psth that the user selects in the 'Save As' dialog (for new) and be able to write what I need to there. Simple. But again, the 50+ page document from developer.apple.com about Document-based architecture tells me where to overload a lot of things, but every one seems to stem from some in-memory representation of the document, which again, is not what my package is. Technically, only the internal XML file is what would be tied to the document. Everything else is just support for it.
So? Anyone? Takers?
Mark
I can't seem to find anything that just says 'Here's a file URL... Open it as you see fit'
Implement the readFromURL:ofType:error: method in your document class. Alternatively, since your document type is a package type, implement the readFromFileWrapper:ofType:error: method.
You don't have to read the data into memory; you can do whatever you want in whichever method you implement, including opening the database.
How do I implement the save/save-as where I want to control everything that is written to disk or not?
Implement the writeToURL:ofType:error: method or the fileWrapperOfType:error: method.
If you had or could easily create data in memory, you would implement the readFromData:ofType:error: and dataOfType:error: methods. The URL-based and file-wrapper-based methods are for cases where data in memory is not an option. And the primary use of file wrappers is for package types like yours.
Actually, I found it. It's not the 'writeTo' methods, but rather the 'saveTo' methods you want to override. When I did that, the saving code worked as I expected, including automatic save panel support. For clarity, this is the one I chose...
saveToURL:ofType:forSaveOperation:error:
and it works like a champ! Not too confusing now, was it! Sheesh!!!
That was of course the very first thing that I tried, but if you read the developer documentation--specifically the Cocoa Document-Based Architecture--here's what it says about those very methods...
During writing, your document may be asked to write its contents to a different location or using a different file type. Again, your overridden method should be able to determine everything it needs to do the writing from the passed-in parameters.
If your override cannot determine all of the information it needs from the passed-in parameters, consider overriding another method. For example, if you see the need to invoke fileURL from within an override of readFromData:ofType:error:, perhaps you should instead override readFromURL:ofType:error:. For another example, if you see the need to invoke fileURL from within an override of writeToURL:ofType:error:, perhaps you should instead override writeToURL:ofType:forSaveOperation:originalContentsURL:error:.
In other words, it seems to say that you can't assume the URL that is passed to you is the actual place on disk where the 'something' is eventually written to, which wreaks havoc when dealing with database files that are opened by URL. Maybe I'm missing something.
But ok... forget I read that and simply even try to just override those methods. I do and return TRUE for each, (I log the URL so I can see what is being passed in), I get this error on 'Save As' after you have chosen a filename...
2009-10-28 14:31:51.548 XPanel[1001:a0f] dataOfType:error: is a subclass responsibility but has not been overridden.
...but when you look at the documentation for that it says the default implementation throws an exception because you must override one of the other implementations above... which I obviously just did! Plus, again, this can't be represented as simple data!
So grasping at straws here, I overrode that one too and just returned nil, since again, you can't represent what I'm doing with a NSData object. Then I get a 'Can't be saved' message.
WTF?! Why is it calling that thing anyway??!!
...and that's when I gave up and posted this here.
Now if YOU can give me a simple example that perhaps doesn't even actually read or write a file but instead just logs the URL, that would be perfect. Not to useful but still, it should work... I just can't seem to implement get it to.