How exactly is NSPrintInfo's sharedPrintInfo shared? - objective-c

Apple's documentation for NSPrintInfo states in part:
A shared NSPrintInfo object is automatically created for an application and is used by default for all printing jobs for that application.
The method sharedPrintInfo returns the shared NSPrintInfo. What's not explicitly stated is if you alter that object (e.g., by using setOrientation), do said alterations "stick" with the shared object? I.e., is the object you get back a singleton or a fresh copy of the shared object?
One reason I ask is because I've seen in some of Apple's sample code where they explicitly call setSharedPrintInfo at the end of a print job. Why do they do that if the shared object is a singleton?
Update
It seems I have to be clearer in my question. From Apple's documentation, there exists an instance of NSPrintInfo that is the "shared" one. This "shared" instance is used by default when no NSPrintInfo object is used explicitly in method calls. The method sharedPrintInfo returns a pointer to this "shared" instance.
What's not clear is whether sharedPrintInfo clones the "shared" instance and returns a pointer to that, or simply returns a pointer to the existing instance.
If cloned, then any call such as one to setOrientation will affect the clone only. If I wanted to alter the orientation of the "shared" instance also, I would have to call setSharedPrintInfo supplying the altered clone as an argument.
If not cloned, then it's not clear why Apple's sample code explicitly calls setSharedPrintInfo because all method calls altering the state of the NSPrintInfoObject returned by sharedPrintInfo already affected the "shared" instance.

What's not explicitly stated is if you alter that object (e.g., by using setOrientation), do said alterations "stick" with the shared object? I.e., is the object you get back a singleton or a fresh copy of the shared object?
Setters ordinarily return void; they don't return the object whose property you set. NSPrintInfo's setOrientation: method is one example.
Methods that return a copy of the receiver with the change applied say so explicitly in their name—for example, stringByAppendingString: (returns a modified copy), as opposed to appendString: (modifies the receiver).
So NSPrintInfo's setters only affect the object you send those messages to. If you send setOrientation: to the shared print info, you modify that object; you aren't creating a new print info.
OK, now for your actual question.
If you look at NSDocument, you'll see that each document can have its own print info. When the user enters Page Setup, they do so in a sheet on the document window, and their changes only affect that document—which is only possible by giving each document its own print info. If your app isn't document-based, it's probably a single-window app, and one print info for the whole process will do just fine.
The documentation for NSDocument calls out one specific case: You can override its printInfo method in your NSDocument subclass to always use the shared print info object. I can't imagine why you would do that, but in that case, the shared print info object is literally shared between all your open documents.

What's not clear is whether sharedPrintInfo clones the "shared" instance and returns a pointer to that, or simply returns a pointer to the existing instance.
In Cocoa, a sharedFoo method returns the shared foo object. It doesn't make a copy of it—that would defeat its purpose, which is to access the shared object.
This rule is also true of defaultFoo methods (e.g., [NSFileManager defaultManager]). Don't ask me why they call some of these methods defaultFoo and others sharedFoo. ☺
If you ever do want your own copy, many classes will let you make one; NSPrintInfo is one example that explicitly does allow this. Other classes (the shared panels in particular, such as NSColorPanel) exist in one and only one instance.

I don't know the answer to your question, but here's a simple test to find out: call sharedPrintInfo twice and compare the pointers. If they're the same, then no, you get the same NSPrintInfo object back each time. If they're different, then you get a different object back each time. You could do this in the debugger and have your answer in sixty seconds.

The NSPrintInfo documentation states the following, which seems pretty clear:
A shared NSPrintInfo object is automatically created for an application
and is used by default for all printing jobs for that application.
You can also initialize an instance of this class using the initWithDictionary: method.
You can use this dictionary to store custom information associated with a print job.
This would indicate that you can either use the shared object OR create your own.
Now to the second part of your question, why do the Apple examples call setSharedPrintInfo: ?
If you create your own using initWithDictionary: you CAN then store it to be the new shared one. But you don't have to.
source: Mac Dev Center, NSPrintInfo Class Reference

It's not a singleton. There's a shared NSPrintInfo object, because most apps only need one. You can also create additional NSPrintInfo instances if that's appropriate to your situation.

Related

Do Objective-C objects get their own copies of instance methods?

I'm new to Objective-C and was wondering if anyone could provide any information to clarify this for me. My (possibly wrong) understanding of object instantiation in other languages is that the object will get it's own copies of instance variables as well as instance methods, but I'm noticing that all the literature I've read thus far about Objective-C seems to indicate that the object only gets copies of instance variables, and that even when calling an instance method, program control reverts back to the original method defined inside the class itself. For example, this page from Apple's developer site shows program flow diagrams that suggest this:
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW1
Also in Kochan's "Programming in Objective-C", 6th ed., pg. 41, referring to an example fraction class and object, the author states that:
"The first message sends the setNumerator: message to myFraction...control is then sent to the setNumerator: method you defined for your Fraction class...Objective-C...knows that it's the method from this class to use because it knows that myFraction is an object from the Fraction class"
On pg. 42, he continues:
"When you allocate a new object...enough space is reserved in memory to store the object's data, which includes space for its instance variables, plus a little more..."
All of this would seem to indicate to me that there is only ever one copy of any method, the original method defined within the class, and when calling an instance method, Objective-C simply passes control to that original copy and temporarily "wires it" to the called object's instance variables. I know I may not be using the right terminology, but is this correct? It seems logical as creating multiple copies of the same methods would be a waste of memory, but this is causing me to rethink my entire understanding of object instantiation. Any input would be greatly appreciated! Thank you.
Your reasoning is correct. The instance methods are shared by all instances of a class. The reason is, as you suspect, that doing it the other way would be a massive waste of memory.
The temporary wiring you speak of is that each method has an additional hidden parameter passed to it: a pointer to the calling object. Since that gives the method access to the calling object, then it can easily access all of the necessary instance variables and all is well. Note that any static variable exists in only a single instance as well and if you are not aware of that, unexpected things can happen. However, regular local variables are not shared and are recreated for each call of a method.
Apple's documention on the topic is very good so have a look for more info.
Just think of a method as a set of instructions. There is no reason to have a copy of the same method for each object. I think you may be mistaken about other languages as well. Methods are associated with the class, not individual objects.
Yes, your thinking is more or less right (although it's simpler than that: behind the scenes in most such languages methods don't need to be "wired" to anything, they just take an extra parameter for self and insert struct lookups before references to instance variables).
What might be confusing you is that not all languages work this way, in their implementations and semantically. Object-oriented languages are (very roughly) divided into two camps: class-based, like Objective-C; and prototype-based, like Javascript. In the second camp of languages, a method or procedure really is an object in its own right and can often be assigned directly to an object's instance variables as well - there are no classes to lookup methods from, only objects and other objects, all with the same first-class status (this is an oversimplification, good languages still allow for sharing and efficiency).

How to set a breakpoint on "objectAtIndex:" method of a specific property in a specific class in XCode 4?

I would like to set a symbolic breakpoint on "objectAtIndex:" method of a specific property in a specific class.
See the following code :
#interface Foo
...
#property (strong,nonatomic) NSMutableArray *fooArray;
...
#end
I 've tried the following things:
-[[Foo fooArray] objectAtIndex:]
-[Foo::fooArray objectAtIndex:]
-[Foo::fooArray objectAtIndex]
Foo::fooArray::objectAtIndex:
Foo::fooArray::objectAtIndex
Foo::fooArray::objectAtIndex()
None of theses solutions work.
Any ideas to do the trick ?
Unfortunately, while this would be useful, it cannot work, for multiple reasons.
The first involves how methods are specified. A method signature for identifying a method in a breakpoint has three parts:
-¹[NSDictionary² objectForKey:³]
+¹[NSString² stringWithContentsOfURL:encoding:error:³]
Is this an instance method (-) or a class method (+)?
Which class's implementation of this method?
What's the selector of this method?
So your first problem is that what you have written for #2 is not a class.
What you do have is a class, followed in some fashion by a property name. This cannot work, because the debugger has no way to know whether that is a pure accessor—it cannot be sure that you, or whoever implemented that property, didn't write a custom accessor that does something else. This means that the debugger has no good, reliable way to obtain that value, or to know when that value changes, without potentially incurring side effects.
Moreover, the role of a class in a method signature is to identify which class provides the implementation you're setting a breakpoint on. That goes out the window as soon as you start trying to refer to a property that holds an object instead, because the debugger needs a class, and will have to get it from the object—and see the previous paragraph for some of the difficulties of knowing which object that is at all times.
(To be fair, it would indeed be possible for the debugger to watch the value of an instance variable—IIRC, both debuggers can already do this in a watchpoint, though reliability of watchpoints was flaky the last time I tried one. If the debugger could translate the property into its backing ivar, if it has one, and watch that, it would be a decent 90% solution for the majority of properties, which aren't backed by imaginative storage implementations and custom accessors. But the debuggers cannot do this today.)
The second reason is that NSArray is a class cluster.
You probably already know the first part of this (I suspect it's why you're trying to specify a single object by a property of another):
NSArray and NSMutableArray are both abstract classes, which in turn means that neither one implements the business of being an array; each one implements a bunch of convenience methods, while leaving a select set of core methods unimplemented, for subclasses to implement.
So, when you create an NSArray, you do not create an NSArray. The object you get back will be an instance of some private subclass of NSArray, with its own implementation of all of the details of how it manages an ordered list of objects.
So you could set a breakpoint on, say, -[NSArray objectAtIndex:], but it would never get hit, because nothing uses NSArray's implementation of objectAtIndex:—it would not make sense to use that implementation, because that implementation raises an exception (intended to catch subclasses that forget to implement it).
The part that breaks your question is:
While NSArray's implementations of various non-essential methods are defined ultimately in terms of the core methods, such as objectAtIndex:, that does not mean that subclasses are bound to use those implementations. A subclass could very well have its own implementations that don't use objectAtIndex:, if objectAtIndex: is not the most efficient way to do what they do (e.g., if the array is backed by a linked list rather than a C array).
So, to summarize this long answer:
It is not possible for the debugger to reliably watch the value of a property.
As such, it is not possible for the debugger to break when a method in the class of the object that is the value of that property is called, because the correct method to set the breakpoint on may change at any time, and the debugger cannot know when that happens.
Even if you could break on objectAtIndex: of some object identified by property, the array may validly never use objectAtIndex:, in which case your breakpoint would never get hit anyway.
You probably should ask another question about whatever you're trying to do by breaking on objectAtIndex:. I assume you're trying to investigate a bug in your app; that bug is probably another interesting question.
After some digging, I found a way to work this out. That's kinda ugly.
It involves creating a conditional breakpoint dynamically, in a command triggered by a first breakpoint.
First, break whenever your fooArray is ready. I settled on the fooArray accessor, but it could be done earlier :
breakpoint set --name "-[Foo fooArray]"
Then, what you want is break when objectAtIndex: is called on this specific array object. First let's put its pointer in a variable :
expr id $watch = self->_fooArray
and then create a new breakpoint, using this variable in the condition :
breakpoint set --name "-[__NSArrayI objectAtIndex:]" --condition "$rdi == $watch"
$rdi contains self, at least on x86_64. Use $r0 on ARM. (See Clark Cox's great post on the topic.)
-[NSArray objectAtIndex:] is never called. As Peter mentioned, NSArray is a class cluster, and your array is actually an __NSArrayI.
Or, in Xcode :
(Don't forget to check the "continue" box.)
It's not really beautiful, but it seems to work !
I am not at my Mac, so I cannot try this myself, but how about:
breakpoint set -n "-[[Foo fooArray] objectAtIndex:]"

iOS singleton with static data

I'm working with game center and wanted to have a singleton class for accessing the GK functionality which I've setup, but I then introduced a couple of methods which needed a delegate. Obviously delegates can't really work properly with a singleton, but I want/need the data loaded in this class to be loaded once and be there all the time.
Is there a nice way that I'm missing of keeping the data there all the time, but having the class instantiated as and when it's needed?
Yoy say "singleton class", and by that I assume you mean that this class only has class methods. That's fine, you can still use it, since class objects are still objects. That said, you will probably need to maintain state. Each delegate call will include some parameter that allows the object to identify the sender.
What I would probably do myself is create a NSMutableDictionary in an "initialize" method, then have objects register themselves before sending delegate methods, and when they register create another mutableDictionary, and save that in the first one with the sending object as the key (or some other unique identifier).
Every delegate call has to include the sender, and with that you can retrieve the dictionary associated with that object.

Conflict between memory management descriptions in ObjC book and official docs

I'm trying to learn/understand what happens and why when working with or creating various objects. (Hopefully to LEARN from the docs.)
I'm reading "Programming in Objective-C 2.0" (2nd edition, by Steven Kochan). On page 408, in the first paragraph is a discussion of retain counts:
Note that its reference count then goes to 2. The addObject: method does this automatically; if you check your documentation for the addObject: method, you will see this fact described there.
So I read the addObject: docs:
Inserts a given object at the end of the array.
There, the description is missing, while other items, like arrayByAddingObject:, state it:
Returns a new array that is a copy of the receiving array with a given object added to the end.
Where in the reference does it indicate that addObject: increases the retain count? Given the presence of ARC, I should still understand what these methods are doing to avoid bugs and issues. What does ARC bring to this? (Going to read that again...)
Great question, I'm glad to see someone actually reading the docs and trying to understand them!
Since you are looking for how to research answers using Apple's documentation more so than the actual answer itself, here is how I found the answer:
First I look at the class reference for addObject: which is a method of NSMutableArray and there is no mention of memory management.
Then I look at the Overview section at the top... Hmmm, still no luck.
Since the behavior might be inherited from a parent class, I look at the Inherits from section at the top of the class reference and see that NSArray is the most immediate parent. Let's check there:
Under the Overview There is one small section about retain's:
Special Considerations
In most cases your custom NSArray class should conform to Cocoa’s
object-ownership conventions. Thus you must send retain to each object
that you add to your collection and release to each object that you
remove from the collection. Of course, if the reason for subclassing
NSArray is to implement object-retention behavior different from the
norm (for example, a non-retaining array), then you can ignore this
requirement.
Okay, I'm still not happy... Where next? The parent class of NSArray is NSObject and I know that it won't be covered there in this case (from experience) so I won't bother checking that. (If the parent was another class or something that might be covered by NSObject, I would keep moving up the tree until I found something.)
The Companion Guides usually contains a lot of good information for these types of classes. Let's try the first one, Collections Programming Topics.
The first section (after Overview) is Accessing Indexes and Easily Enumerating Elements: Arrays. Sounds promising! Click on Relevant Chapters: “Arrays: Ordered Collections”
There it is under Array Fundamentals along with a link to even more information:
And when you add an object to an NSMutableArray object, the object
isn’t copied, (unless you pass YES as the argument to
initWithArray:copyItems:). Rather, an object is added directly to an
array. In a managed memory environment, an object receives a retain
message when it’s added; in a garbage collected environment, it is
strongly referenced. When an array is deallocated in a managed memory
environment, each element is sent a release message. For more
information on copying and memory management, see “Copying
Collections.”
The book must be referring to out of date documentation because you are correct it doesn't mention anything about the retain count. It does in fact retain the object though. The way you need to think of it is not in terms of retain counts (which are useless) but rather ownership. Especially so when using ARC.
When you add an object to an NSMutableArray, it is taking ownership of that object (in ARC terminology it has a strong reference to it).
"What does ARC bring to this?"
ARC does nothing different. All ARC does (besides some optimization) is add the same release, retain, and autorelease statements that you would add yourself without using ARC. All you need to care about is that once you add an object to the array, it will live at least as long as the array.
And the arrayByAddingObject: method creates a new NSArray (or NSMutableArray) containing the object you're passing, and keeps a strong reference to the passed object. The actual array object that it creates has no references yet unless you assign it to either an ivar, property, or local variable. What you assign it to determines it's lifespan.
Basically even without ARC, it's best to think of object life-cycles in terms of ownership, ARC just formalizes that. So because of that, when using the frameworks, it doesn't matter when retains happen or don't happen, you are only responsible for your objects until you pass ownership to another object and you can trust that the framework will keep the object alive as long as it needs it.
Now of course you have to intuit what constitutes ownership. For instance delegate properties are often assign, or in ARC unsafe_unretained or weak, to prevent circular retains cycles (where two objects each retain each other), though are sometimes retained/strong so you need to look into those on a case by case basis.
And also in cases like key value observing and NSNotification observing the object you are observing does not retain the observer.
But those are really exceptions to the rule. Generally you can assume a strong reference.
Regarding this sentence above: "The actual array object that it creates has no references yet unless you assign it to either an ivar, property, or local variable. What you assign it to determines it's lifespan." I'll try to explain:
When you run this piece of code: [someArray arrayByAddingObject:someObject]; you've instantiated a new NSArray or NSMutableArray object (depending on which object type someArray is) but you haven't actually assigned it to any reference. That means that if you're using ARC, it may be immediately released afterwards, or if not using ARC, it will be released when it's autoreleasepool is drained (probably on the next iteration of that thread's runloop).
Now if instead you did this: NSArray *someOtherArray = [someArray arrayByAddingObject:someObject]; you now have a reference to the newly created array, called someOtherArray. In this case, this is a local variable who's scope is only within whichever set of { } it resides (so it could be inside an if statement, a loop, or a method. Now if you do nothing else with it, it will die sometime after it's scope ends (it isn't guaranteed to die right away, but that isn't important, you just can't assume it lives longer).
Now if in your class you have an iVar (instance variable) declared in the header like NSArray *someOtherArray; (which is strong by default in ARC) and you run someOtherArray = [someArray arrayByAddingObject:someObject]; somewhere in your class, the object will live until you either remove the reference (someOtherArray = nil), you overwrite the reference (someOtherArray = someThirdArray), or the class is deallocated. If you were not using ARC, you would have to make sure to retain that to achieve the same effect (someOtherArray = [[someArray arrayByAddingObject:someObject] retain]; which is essentially what ARC is doing behind the scenes).
Or you may have a property declared instead like #property (nonatomic, strong) NSArray *someOtherArray in which self.someOtherArray = [someArray arrayByAddingObject:someObject]; would achieve the same effect but would use the proprety accessor (setSomeOtherArray:) or you could still use someOtherArray = [someArray arrayByAddingObject:someObject]; to set the iVar directly (assuming you #synthesized it).
Or assuming non-ARC, you might have declared the property like #property (nonatomic, retain) NSArray *someOtherArray in which self.someOtherArray = [someArray arrayByAddingObject:someObject]; would behave exactly as ARC would, but when setting the iVar directly you would still need to add that retain manually.
I hope that clears things up a bit, please let me know if there's anything I glossed over or left out.
As you mentioned in your comment, the key here is intuitively knowing when an object would be considered owned by another one or not. Luckily, the Cocoa frameworks follow a pretty strict set of conventions that allow you to make safe assumptions:
When setting an NSString property of a framework object (say the text property of a UILabel for example) it is always copied (if anyone knows of a counter-example, please comment or edit). So you don't have to worry about your string once you pass it. Strings are copied to prevent a mutable string from being changed after it's passed.
When setting any other property other than delegate, it's (almost?) always retained (or strong reference in ARC)
When setting delegate properties, it's (almost?) always an assign (or weak reference) to prevent circular retain cycles. (For instance, object a has a property b that is strong referenced and b has a strong referenced delegate property. You set a as the delegate for b. Now a and b are both strongly referencing each other, and neither object will ever reach a retain count of 0 and will never reach it's dealloc method to dealloc the other object. NSURLConnection is a counter-example that does strongly reference it's delegate, because it's delegate is set via a method -- see that convention below -- and it's convention to nil out or release an NSURLConnection after it completes rather than in dealloc, which will remove the circular retain)
When adding to an array or dictionary, it's always retained (or strong reference).
When calling a method and passing block(s), they are always copied to move them from the stack (where they are initially created for performance purposes) into the heap.
Methods that take in object parameters and don't return a result immediately are (always? I can't think of any that don't) either copying or retaining (strong referencing) the parameters that you pass to ensure that the method can do what it needs to with them. For instance, NSURLConnection even retains it's delegate because it's passed in via a method, whereas when setting the delegate property of other objects will not retain, as that is the convention.
It's suggested that you follow these same conventions in your own classes as well for consistency.
Also, don't forget that the headers of all classes are available to you, so you can easily see whether a property is retain or assign (or strong or weak). You can't check what methods do with their parameters, but there's no need because of the convention that parameters are owned by the receiver.
In general, you should look in the "most global" spot for information about anything in the Cocoa APIs. Since memory management is pervasive across the system APIs and the APIs are consistent in their implementation of the Cocoa memory management policy, you simply need to read and understand the Cocoa memory management guide.
Once understood, you can safely assume that all system APIs implement to that memory management policy unless explicitly documented otherwise.
Thus, for NSMutableArray's addObject: method, it would have to retain the object added to the array or else it would be in violation of that standard policy.
You'll see this throughout the documentation. This prevents every method's documentation from being a page or more long and it makes it obvious when the rare method or class implements something that is, for whatever reason (sometimes not so good), an exception to the rule.
In the "Basic Memory Management Rules" section of the memory management guide:
You can take ownership of an object using retain.
A received object is normally guaranteed to remain valid within the
method it was received in, and that method may also safely return the
object to its invoker. You use retain in two situations: (1) In the
implementation of an accessor method or an init method, to take
ownership of an object you want to store as a property value; and (2)
To prevent an object from being invalidated as a side-effect of some
other operation (as explained in “Avoid Causing Deallocation of
Objects You’re Using”).
(2) is the key; an NS{Mutable}Array must retain any added object(s) exactly because it needs to prevent the added object(s) from being invalidated due to some side-effect. To not do so would be divergent from the above rule and, thus, would be explicitly documented.

Unit Test to verify object getting deallocated

What I am looking for is a way to programmatically verify a target object has been deallocated. Currently I have an NSLog statement in the dealloc methods of the objects I wish to observe.
The unit testing framework is from the Google Toolbox for the mac, and it working nicely. I am just not certain how to frame this particular test.
Use _GTMDevLog :
See the Advanced Stuff | Unit Test Logging on this page.
More info on DevLogNAssert.
You could swizzle the dealloc method. See MethodSwizzling on CocoaDev; a modern approach using Leopard's new method_exchangeImplementations function is (currently) near the bottom of the page.
Your implementation will need to tell your test case object that it had been called. One way to do this would be a static variable in the file where both the test case class and replacement dealloc method are defined; your test method sets that variable to NO, then releases the object, then asserts that the variable's value is now true.
In the past I've created a variable that counts the number of objects of a given class that have been allocated by incrementing the value in the constructor and decrementing it in the destructor. The unit tests just check that the variable is zero at the end of the test.
I did something very similar to this in C#/.Net. I used a "WeakReference" to keep track of the item, and tested that it no longer existed (see link). Can you translate this approach to your environment?
Link
Could you record the dealloc in some kind of event monitor service, so that the test code can then query with that to see if the dealloc has occured. Obviously you will record it by name or id, as the object is being dealloc'd...
I may be naive, but wouldn't a unit test of a deallocation consist of
allocating an object,
deallocating it through your method to be tested,
trying to call something from the object, and then
catching the exception and see if its type is correct?
I’ve written a function that releases the object and returns YES if the object got deallocated:
BOOL getsDeallocatedByReleasing(id object);
There’s also an advanced interface where you can run arbitrary code in a block and you will get a bool indicating if an object of given class was deallocated:
BOOL classGetsDeallocated(Class c, void (^block)(void));
The code uses method swizzling, it’s pretty ugly and definitely not thread-safe, but it works. You can find it on GitHub, I’ll keep it updated if I find any bugs.
P.S. After writing all that code (d’oh!), wouldn’t it be possible to add a single retain at the start, do whatever you want, tear down the object graph you are inspecting and check the object’s retain count?