Difference between objectAtIndexedSubscript and objectAtIndex - ios

I have searched quite bit on stackoverflow and other resources, can't find an answer.
What is the difference between the NSArray methods objectAtIndexedSubscript and objectAtIndex?
Or, if there is no difference, why do both exist?
In the Apple Docs it says they are "identical".
I am super new to programming but if they are identical, isn't that breaking the DRY principle? Obviously the guys at Apple know what they are doing, but why are they both provided if they are identical? Or maybe a better question is, why should I use one over the other?

They are identical.
-objectAtIndex: is the method you should use.
-objectAtIndexedSubscript: is the method that provides support for obj-c subscripts. In other words, this method is what the compiler uses if you say array[3]. But for NSArray* it does the exact same thing as -objectAtIndex:. The reason why it's a different method is so other classes can implement this in order to support obj-c subscripts without having to use the generically-named -objectAtIndex:.

Related

Swift / UIKit: understanding the structure of built-in methods

I'm new to Swift and UIKit and, coming primarily from Python, I'm having trouble with the copy-paste-ness of tutorials and documentation I've been looking at thus far. I'm having a hard time getting a fundamental understanding of methods like:
override func tableView( ... numberOfRowsInSection ... )
override func tableView( ... cellForRowAt ... )
In practice I can use them without much issue, but I would appreciate any clarification or pointing to references that would explain:
Why are UIKit methods structured like this, rather than having a dedicated
func tableViewNumberOfRowsInSection( ... )
func tableViewCellForRowAt( ... )
(Or, why not have numberOfRowsInSection as an attribute of the subclass of UITableViewController, rather than one parameter of a function (tableView) that seems to have hundreds of uses?)
Function/Method basics such as labels, parameter names, etc make perfect sense to me, but I can't seem to make the jump to why func tableView would be structured the way it is.
What does the eventual call of tableView look like?
Thanks in advance for any help or pointers!
These are not the same function used in different ways — they are completely different functions, because the argument labels are part of the functions' names. The full name of each function is tableView(_:numberOfRowsInSection:) and tableView(_:cellForRowAt:) as you can see in the documentation. You might also want to read the Function Argument Labels and Parameter Names section of this guide, and maybe the naming guidelines.
You are unlikely to call these methods yourself, since they exist to provide data to the table view itself. UITableView will call your methods internally, which would look something like dataSource.tableView(self, cellForRowAt: indexPath). See the Delegation section in the Protocols guide for more on this pattern.
It's also worth noting that this API was created for Objective-C (before Swift was released), where their selectors are tableView:numberOfRowsInSection: and tableView:cellForRowAtIndexPath:. That might be less confusing because the first argument label isn't "privileged" by being outside parentheses. That said, it's still considered a good design by Swift's naming standards, at least as long as the design needs to use classes (which it might not, if it didn't have to support Obj-C).
I won't go into too much detail in this answer, but it is true that delegate methods from UIKit (like the ones you show) tend to be long and near impossible to type out without help from auto-complete.
Nobody I know has memorized all of them (I've tried, and failed).
The reason being is somewhat legacy due to UIKit itself being written in Objective-C by Apple.
If UIKit were to be rewritten in Swift today (this will never happen due to the huge amount of effort Apple has invested into the framework over the years and the rise of SwiftUI), it's likely that the API would better follow practices for Swift API design.
To answer your questions specifically:
That's the way they've always been–if they were changed at all it would break a lot of developer's source code. Arguably the kind of method signatures you are proposing are not any better, just different. Also, if you read the full method signatures they do make sense and are clear enough.
Look into some tutorials for UITableView. The methods you are showing off come from UITableViewDelegate which is kind of the 'glue' you use to configure the table from your code. This is because back in the early Objective-C days the only way to do this sort of customisation was through this 'delegation pattern'.

Typedef NSArray of type in Objective C

It has been a long time since I have worked in Objective C but now I am using it because I need to write something that will remain mostly source compatible for future versions. I want to create an init method that allows me to init my viewController with an array of my custom model object. In Swift I would do it like this:
typealias Stack = [StackBarTabItem]
…
func init(stacks:[Stack])
But how would I typedef an NSArray like that? I am pretty sure I can't do something like typedef NSArray<StackBarTabItem> Stack; so what is the syntax in objective c?
Until iOS 9 and Xcode 7, this isn't officially supported. One way to do this is to subclass NSArray or NSMutableArray and enforce typing in your subclass, but this isn't really recommended. One way to deal with the fact that NSArray can only hold ids is to use respondsToSelector before calling a method on any of the objects in the array.
This solution isn't really a substitute for a good typing system, but it's a common practice to get around this limitation. Thankfully, generic support is getting added soon!
Objective-C is dynamically typed. You simply do not check for it.
Asking the audience on talks and in internet fora, the real danger that code will be shipped with a typing bug is minimal and by far lower than other sources of errors. Simply do not care about this.
Ask yourself: How could that happen without getting a runtime error at the very beginning of your next program run?

Is the use of id type in method a good practice?

I am creating a set of API and some users have suggested that I use id type for a particular method that can accept custom object (defined by the API) or string instead of creating two versions. Is the use of id type in method a good or acceptable practice? Does Apple do it with their any of their API?
That would be very poor practice. If you're creating an API you need to retain full control, and allowing users to pass any object to your method at which point you would have to cast it to that object or string you mentioned could be fatal depending on what's passed. Creating two methods with different parameters is not only okay, but follows the tenets of polymorphism to the T.
Accepting id is not in itself good or bad practice. How much manual procedural if/then/else/if/then/else nonsense will you acquire? If quite a lot then something is wrong.
Put another way: if the conditional logic related to different kinds of object ends up being implicit, via the Objective-C dispatch mechanisms, then the design is good. If you end up impliedly reimplementing dynamic dispatch then you've gone completely wrong.
Apple does it frequently. Just off the top of my head there are:
as per Nikolai's comment, all the collection types: set, dictionary, array, etc.
anything that takes %# as a format specifier: NSLog, certain methods on NSString, etc.
anything that still uses an informal protocol.
anything in or semi-close to the runtime like key-value coding.
archiving and the user defaults.
anywhere that storage is offered for your own use — the hardy userInfo on NSTimer and the rest.
anywhere that target/action is used — all UIControls, the notification centre, etc.
As per my comment, suppose your custom class had this method:
- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
And suppose it were the only method being called by whomever is being passed either a string or your custom object. Then id would be the right choice, since you'd have in effect implemented an informal protocol, and the thing being passed an object genuinely doesn't care whether it's a string or not. The only contractual requirement is the informal protocol and the protocol is informal i.e. has no footprint on the type syntax.
Conversely, suppose your custom class had no methods in common with NSString and your code just looked like:
- (void)myMethod:(id)object
{
if([object isKindOfClass:[NSString class]])
[self myMethodOnString:object];
else
[self myMethodOnCustomClass:object];
}
Then id would be inappropriate. You're just obscuring what the method does and implicitly reproducing work that's built into the runtime anyway.

Why do we needed category when we can use a subclass? and Why we needed blocks when we can use functions?

These two questions are quite common when we search it but yet I need to get a satisfying answer about both.When ever we search a difference between say subclass and a category we actually get definition of both not the difference.I went to an interview to a very good MNC working on iOS and I was encountered with these two questions and I gave almost all the answers I have read here but the interviewer was not satisfied.He stuck to his questions and was that-
Why do we needed category when we can use a subclass?
Why we needed blocks when we can use functions?
So please explain me what specific qualities blocks and category add in objective C that their counter part can't do.
First...
Just reading the documentation "Subclassing Notes" for NSString shows why creating categories is sometimes better than subclassing.
If you wanted to add a function -(void)reverseString (for instance) to NSString then subclassing it is going to be a massive pain in comparison to categories.
Second...
Blocks are useful for capturing scope and context. They can also be passed around. So you can pass a block into an asynchronous call which then may be passed elsewhere. TBH you don't care where the block is passed or where it is finally called from. The scope captured at the time of creating the block is captured too.
Yes, you can use methods too. But they both have different uses.
Your questions are a bit odd. It's like asking...
Why do hammers exist when we can just use wrenches?
You can't use subclassing when someone else is creating the objects. For instance, NSString is returned from hundreds of system APIs, and you can't change them to return MyImprovedString.
Functions split up the logic; blocks allow you to write it closer together. Like:
[thing doSomethingAndWhenFinishedDo: ^{ some_other_thing; }];
the same code written with functions would put the second part of the logic several lines away in the file. If you have a few nested scopes in your logic then blocks can really clean it up.
Why do we needed category when we can use a subclass?
Categories let you expand the API of existing classes without changing their type. Subclassing does the same thing but introduces a new type. Additionally subclassing lets you add state.
Why we needed blocks when we can use functions?
Block objects are a C-level syntactic and runtime feature. They are similar to standard C functions, but in addition to executable code they may also contain variable bindings to automatic (stack) or managed (heap) memory. A block can therefore maintain a set of state (data) that it can use to impact behavior when executed.
You can use blocks to compose function expressions that can be passed to API, optionally stored, and used by multiple threads. Blocks are particularly useful as a callback because the block carries both the code to be executed on callback and the data needed during that execution
Category : It is used if we want to add any method on a given class whose source is not known. This is basically used when we want to alter the behaviour of any Class.
For example : If we want to add a method on NSString to reverse a string we can go for categories.
Subclassing : If we want to modify state as well as behaviour of any class or override any methods to alter the behaviour of the parent class then we go for subclassing.
For example : We subclass UIView to alter its state and behaviour in our iOS code.
Reference :
When to use categories and when to use subclassing?
What is the difference between inheritance and Categories in Objective-C
We need new method but we don't need new class so we need category.
We need function but we don't need named function so we need block.

A NSZombie of an odd type

so i am getting a NSzombie and it says this
-[__NSArrayI _cfTypeID]: message sent to deallocated instance
Any idea what that is? assumably an array although i thought if it were an NS type it would say.
Yes — that'll be some type of array. Rather than being single classes, most of the foundation types are class clusters. So exactly how you initialise the array affects exactly which subclass of NSArray you get back.
The exact behaviour is undocumented and basically guaranteed to change over time but for example if you created an immutable array with less than a certain number of entries then the system might decide to return a single linked array and perform searches as simple linear searches. If you create one above the threshold then it might instead create an array that adds some sort of hierarchical logic for searching (or, more likely, contains the logic to create suitable hierarchical tables if the user starts trying to search the array).
Related lessons to learn:
never try to subclass a foundation class;
don't expect isMemberOfClass: to work properly;
don't even expect isKindOfClass: necessarily to be able to tell immutable from mutable versions of the foundation classes.
Apple needs a way to differentiate these classes and to flag them as private, so you end up with underscores and suffixes. In practice I think __NSArrayI is a vanilla immutable array.
Basically that means your NSArray object is already deallocated.
Something in Foundation.framework tried to access your NSArray's private method _cfTypeID and crashed.
And about question why there's _cfTypeID method in NSArray object. NSArray Core Foundation counterpart of CFArray. Two type's are interchangeable with "toll-free bridge".
So actually apple uses that method for internal uses.
If you want deeper understand of this. You can visit http://code.google.com/p/cocotron/source/browse/Foundation/NSArray/NSArray.m and this is Cocotron's implementation of NSArray. It is not same with the apple's implementation but still implementations are similar.

Resources