Different methods to set the text of a UITableViewCell - objective-c

What's the difference (if indeed there is a difference) between:
UITableViewCell *cell;
...
cell.textLabel.text = [self.adviceData objectAtIndex:indexPath.row];
and
UITableViewCell *cell;
...
NSString *text = [self.adviceData objectAtIndex:indexPath.row];
[cell.textLabel setText:text];
They both seem to do the same thing, but one has more brackets. Do the brackets do something?

The first one is just using the dot-notation syntax added in Objective-C 2.0. They both call the setText: method on the textLabel.
By the way, here's an article which will help you decide whether to use dot-notation syntax or not in your code.

They both do exactly the same thing, but the first one uses the alternative syntax for calling a setter (I'm ignoring the difference due to introduction of the NSString *text variable). Behind the scene, the compiler generates identical code for the two calls.

Related

Is there NSMutableDictionary literal syntax to remove an element?

There is a literal syntax to add object and change object in an NSMutableDictionary, is there a literal syntax to remove object?
Yes, but... :-)
This is not supported by default, however the new syntax for setting dictionary elements uses the method setObject:forKeyedSubscript: rather than setObject:forKey:. So you can write a category which replaces the former and either sets or removes the element:
#implementation NSMutableDictionary (RemoveWithNil)
- (void) setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key
{
if (obj)
[self setObject:obj forKey:key];
else
[self removeObjectForKey:key];
}
#end
Add that to your application and then:
dict[aKey] = nil;
will remove an element.
No. There is not. I have tried to find proof link but did not succeed :)
As of iOS 9 and macOS 10.11, these two are equivalent:
[dictionary removeObjectForKey:#"key"];
dictionary[#"key"] = nil;
See the Foundation release notes (search for the heading NSMutableDictionary subscript syntax change).

Why are table view cell identifiers' variable names capitalised?

Largely curious really. In the provided Apple UITableViewDataSource method tableView:cellForRowAtIndexPath:, the name given to the static NSString variable used for the cell identifier is always capitalised, like so:
- (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableViewCell"; // CAPITALISED VARIABLE NAME
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
// Configure cell
return cell;
}
Whilst I realise it makes no difference to the program when it runs, Objective-C naming conventions state that variables should have their first letter lower case and classes should have theirs uppercase. Why is this not the case here?
Capitalizing the first letter is used to denote that CellIdentifier is a constant.
Now, you may wonder, why can't you just do this...
static const NSString *cellIdentifier = #"TableViewCell";
The answer is because const does not work with NSString as the programmer would expect. The string value of NSString can still be changed even if it is marked as const, so the following series of expressions...
static const NSString *cellIdentifier = #"TableViewCell";
cellIdentifier = #"Changed!"
NSLog(#"%#", cellIdentifier);
Would log "Changed!" to the console, NOT "TableViewCell". Because of this, a capital letter is used to imply that CellIdentifier is a constant, although it can technically still be altered, it is just "not supposed" to be altered.
The cell identifier here is effectively a constant, which by convention are capitalised

warning received at objectsAtIndexes

I am trying to fetch data from core data, it works fine. But when I try to fill a Table Cell then it gives me warning at the following line
cell.textLabel.text = [fetchedObjects objectAtIndex:indexPath.row];
Warning : passing argument 1 of 'objectsAtIndexes:' makes pointer from integer without a cast.
fetchedObjects is an NSArray object declared in header file. Kindly guide me where I am doing wrong. I can provide whole method for more understanding.
Regards.
EDIT
Here is my complete method code:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"] autorelease];
cell.textLabel.text = [fetchedObjects objectAtIndex:indexPath.row];
return cell;
}
Your posted code says you're calling objectAtIndex, which does indeed take an integer parameter. However, your error says you're using objectAtIndexes, which takes a pointer to an NSIndexSet. As indexPath.row is not an NSIndexSet pointer, you're getting that warning (saying that you're trying to use a raw integer as a pointer).
Check your actual code. Almost certainly, you're using objectAtIndexes by mistake.

Trouble subclassing UITableViewCell (2 warnings)

Following the documentation on custom cells from a NIB (the Dynamic option), I have this method. (The view itself is not a UITableViewController, but it's hooked up properly.)
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ReusableCell";
UITableViewCell *cell = (LoadGameCell *)
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[NSBundle mainBundle]
loadNibNamed:#"LoadGameCell" owner:self options:nil];
cell = loadGameCell;
self.loadGameCell = nil;
}
/*
cell setup
*/
return cell;
}
The first line in the if statement is the bit I'm having trouble with.
Incompatible pointer types assigning to 'UITableViewCell *' from 'NSArray *'
Incompatible Objective-C types assigning 'struct NSArray *',
expected 'struct UITableViewCell *'
No errors/crashes running the app with these warnings, but I'd rather not ignore/suppress them. It'll hurt a whole lot more later on.
If it isn't a direct result of the warnings above, there's another problem. I can't get the method to take views, only labels. (That is, I can customize a label, but not the image view it's sitting next to.)
As the documentation will tell you, loadNibNamed:owner:options: returns an array. To access the cell in the NIB (assuming it is the only root-level object in the NIB), call objectAtIndex:0 on the result of loadNibNamed:owner:options.

Obj-c dot notation for reading properties: why can't i combine it like this?

i have this line of code:
[[[EntitlementsManager instance] entitlements] objectAtIndex:indexPath.row];
Why won't it work in the way below:
[EntitlementsManager.instance.entitlements objectAtIndex:indexPath.row];
Seems like it should work to me? I'm a little confused as to why it doesn't compile.
FYI, EntitlementsManager, 'instance' is the '+' method to return its singleton, and 'entitlements' is an NSArray property.
-edit: For those why say it doesn't work because 'instance' is a static '+' method, then why does the following work just fine? I'm really intrigued:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return EntitlementsManager.instance.entitlements.count;
}
-edit2: This does work, strangely:
... = [[EntitlementsManager instance].entitlements objectAtIndex:indexPath.row];
Possibly the parser got confused when it sees a Type appearing on the left of a . inside an Obj-C method call. For example, if the grammar
'[' Type methodAndArguments ']'
exists, then it will be parsed before recognizing a '.' b, and since .instance ... isn't an expected construct of methodAndArguments, the compiler will fail. As Type.method isn't one expected use of the dot syntax, it is valid for the compiler not to support it, or even making its use a syntax error in the future.
Either always use the bracket notation for class methods as you're expected to:
[[EntitlementsManager instance].entitlements objectAtIndex:0]
or move that expression outside of bracket:
NSArray* entitlements = EntitlementsManager.instance.entitlements;
[entitlements objectAtIndex:0];
or force that '[' Type methodAndArguments ']' not to be matched:
[(nil, EntitlementsManager.instance.entitlements) objectAtIndex:0]
Try this way
[(EntitlementsManager.instance.entitlements) objectAtIndex:indexPath.row];
might work