Best objective-c questions in March 2012

Removing a method call from inside a static lib(.a) without recompiling

12 votes

I'm using a static lib thats giving me a warning when uploading my binary for review by apple.

The method in the static lib that causes the warning(non-public selectors) is never called by me, its corresponding .h is deleted from my proj, but warning still persists.

Given that I know the method name causing the problem, is there a way for me to open/edit this .a and comment/delete the offending piece of code and then use the modified .a in my project.

I don't have access to the .a source to recompile it, and its very old and the creator of it has no contact details for me to track down.

Many Thanks, -Cake

Quick and dirty solution: Open the .a file in a hex editor and change all instances of the name. Leave the function name the same length so that offsets in the file don't change, just change a letter or something like that. I did a quick test, adding a dummy function to a subproject we're building as a static library then tweaking the function name in the .a file (there were five instances, for what that's worth) and everything built okay. I don't see any reason it wouldn't pass the App Store check after that.

I'm really surprised the function was still there in the final build, though—I thought Dead Code Stripping was supposed to clean out any unused code. Huh.

How do I animate CATransform3Ds with a CAKeyframeAnimation?

10 votes

I've used CAKeyframeAnimations to animate a layer's transform.rotation and transform.translation.x properties, but I'm having trouble animating the transform property implicitly. I have a layer that must animate between two states and CABasicAnimation's default interpolation is totally incorrect and doesn't follow the path I want. CAKeyframeAnimation to the rescue, or so I thought. Any attempt to animate transform using a CAKeyframeAnimation results in the view immediately snapping to the final transform while the other animations run. If I remove the first half of the following function and let my "transform" events use the CABasicAnimation on the bottom, it animates just fine - albeit with incorrectly interpolated transforms along the way.

My layer delegate has implemented the following:

- (id <CAAction>) actionForLayer:(CALayer *)layer forKey:(NSString *)event
{    
    if ([event isEqualToString:@"transform"])
    {
        CGSize startSize = ((CALayer *)self.layer.presentationLayer).bounds.size;
        CGSize endSize = self.layer.bounds.size;

        CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:event];
        animation.duration = 0.25;

        NSMutableArray *values = [NSMutableArray array];

        int stepCount = 10;
        for (int i = 0; i < stepCount; i++)
        {
            CGFloat p = i / (float)(stepCount - 1);
            CGSize size = [self interpolateBetweenSize:startSize andSize:endSize percentage:p];
            CATransform3D transform = [self transformForSize:size];
            [values addObject:[NSValue valueWithCATransform3D:transform]];
        }

        animation.values = values;
        return animation;
    }

    // All other animations use this basic animation
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.removedOnCompletion = YES;
    animation.fillMode = kCAFillModeForwards;
    animation.duration = 0.25;
    return animation;
}

My transform is a translation followed by a rotate, but I think a group animation with separate keyframe animations animating through a translation AND a rotate would result in crazy town. I've confirmed that size & transform are correct for all values of p that I pass though, and p strictly ranges from 0 to 1.

I've tried setting a non-default timing function, I've tried setting an array of timing functions, I've omitted the keyTImes, I've set a repeatCount of 0, removedOnCompletion=YES, and a fillMode of forwards and that had no effect. Am I not creating the transform keyframe animation correctly?

This technique worked back in iOS 3 but seemed to be broken in iOS 5.0.

5.1 'magically' fixed this, it seemed to be a bug in iOS 5.0. I'd file a radar, but it is now working in 5.1.

@Gsnyder: Some background: I am experimenting with Clear-like UI (for something completely unrelated to Clear) and came up with this: http://blog.massivehealth.com/post/18563684407/clear. That should explain the need for a rotate & translate.

I've since created a shutter transition that subdivides a view into N layers (instead of just 2) that looks like this when viewed from the side: /////.

My code is not animating the bounds, it is using the size at each step to determine the necessary transform.

@Paul.s: Implicit allows me to keep this abstraction within the layer class itself without polluting the view controller that owns it. The view controller should just be changing the bounds around and the layer should move appropriately. I'm not a fan of view controllers having dozens of custom animations when the views themselves can handle it.

I need to use a keyframe animation because the default animation between layer transforms / and _ animate through incorrect angles so the ///\ layers do not line up throughout the transform. The keyframe animations ensure the edges all line up correctly while they all animate.

I'm considering this closed, this seems to be a bug in iOS 5.0 and has since been fixed. Thanks everyone.

How to open prefrences/settings with iOS 5.1?

10 votes

Looks like iOS 5.1 has broken the standard URL encoding for navigating a user to a Preference.

For example:

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=TWITTER"]];

Works in iOS 5 and less but not in iOS 5.1 (both device and simulator).

Has anyone found a way to replicate this functionality in iOS 5.1?

No I don’t know a way to replicate this functionality.

But what you can do is file a Radar requesting the restoration. Here is a radar requesting that the schemes be documented in the first place.

David Barnard has confirmed that iOS 5.1 breaks the settings apps URL schemes.

How to Make Application which Store Sent and Received Messages in iPhone

8 votes

I am new in iPhone and I don't know much about iPhone Technology. I Searched on Stack Overflow but not got any proper solution regarding my Query.

What I need is, I want to Create One Application for iPhone3 as well as iPhone4 WHICH ALLOWS USERS TO VIEW THEIR EXISTING TEXT MESSAGES(only SENT and RECEIVED) FROM "MESSAGE"[of iPhone menu] through a DIFFERENT SCREEN COLOR and BRIGHTNESS SETTING.

Please give me some Suggestion/Helpful Link or any Hint Regard my query. How I start To Code My Application. THANKYOU ALL

Regard,

Tauseef

It looks like it's possible to read stored messages but you'll also gona have to learn something about SQlite.

Take a look at the links here (the accepted answer and link in the comments): read iphone sms messages?

But this will work only on jail-broken iPhones and certainly will not be approved for App Store.

You'll find the location of database in sebsto's answer to this question: iphone app reading sms

iOS: Creating tip / help popups

7 votes

Are there any built in, open source, or tutorials for creating a reusable easy to use popup for use with in game-help.

Essentially I would like to, on first run of a game, show popup tips / help that "point to" various on screen objects to help a user orient themselves with the game.

Update: Here is an example of how I ultimately want it to look / behave although I don't need it that generic but as close as possible would be good

Essentially what you need is a custom view.

You cannot use Apple's UIAlertView since its purpose is very different from what you are looking for.

I don't know what are your specific needs, but you may use a simple UILabel:

CGRect ref = objectToAddress.frame;

UILabel *tip = [[UILabel alloc] initWithFrame:CGRectMake(ref.x+ref.width, 
                                                         ref.y+ref.height,
                                                         width,
                                                         height)];

[tip setText:messageToShow];

[self.view addSubview:tip];
[tip release];

where width and height are the dimensions of the tip you want to show and messageToShow is the message you want to display.
You can, of course, customize your UILabel as you like, changing font or background color. Check the reference for additional informations.

EDIT:

You may take a look at a possible popover implementation for iPhone: WEPopover. On the iPad you can use directly Apple's UIPopoverController

Does C code run faster?

7 votes

Is there any performance gain in calling C code from Objective-C?

I've read somewhere that message passing is slower compared to other languages that use function calling. So if I call a C function from Objective-C code, am I avoiding the messaging overhead?

When optimizing for performance, is it recommended practice to code the most critical functions and procedures in C instead of using Objective-C objects?

EDIT:
Given the ammount of answers warning about premature optimization and code readability, I want to clarify that I was not thinking on regular applications, but very specific ones such as:

  • Graphics
  • Encryption or compression algorithms.
  • Maths

And in general, fuctions or procedures that do not need OO design and are intended to be called many times with parameters.

This is a benchmark that compares messaging to calling C functions. Here are the results of calling different implementations of the fibonacci function about 1.4 billion times.

Message Passing 23.495 seconds
IMP Calling     16.033 seconds
C Function      9.709 seconds

So yes, there is some overhead when calling an Objective C method. But, except in some situations, this is not what will impact the performance of your app. In fact, messaging is still more efficient than most other operations such as floating-point division.

In addition, the majority apps spend most time waiting for user input, downloading data, etc.

Alternative to iPhone device ID (UDID)

7 votes

Even if Apple was not at Barcelone's MWC (mobile world congress), there was the certitude that getting the deviceID will be deprecated in further iOS SDK.

I do not understand why Apple want to restrict this, but that's not the topic.

I must prepare my application to an alternative because my users are identified and known for a better use of my app (don't need to log, or create an account, for example). And I'm sure I'm not alone in that case.

So anybody know an alternative from getting the deviceID ? Is there other unique identifier, like MAC address, for example ? How do you prepare your app ?

UPDATE

What about using CFUUID to generate a UUID. You can than store it in KEYCHAIN on the very first launch.. you can get it like this...

NSString *uuid = nil;
CFUUIDRef theUUID = CFUUIDCreate(kCFAllocatorDefault);
if (theUUID) {
  uuid = NSMakeCollectable(CFUUIDCreateString(kCFAllocatorDefault, theUUID));
  [uuid autorelease];
  CFRelease(theUUID);
}

and also by deprecating the uniqueIdentifier method, Apple is suggesting that you don't identify per device but instead per app install. may be tomorrow they might decide to reject your app for doing this .. :/ hoping this helps.

Why do my table view cells disappear when reloaded using reloadRowsAtIndexPaths?

7 votes

I have a bare-bones sample project here:

http://dl.dropbox.com/u/7834263/ExpandingCells.zip

In this project, a UITableView has a custom UITableViewCell. In each cell are 3 UIViews containing a label.

The goal is to expand the cell when tapped, then collapse it when tapped again. The cell itself must change it’s height to expose the subviews. Inserting or removing rows is unacceptable.

The demo project works almost as expected. In fact, in iOS 4.3 it works perfect. Under iOS 5, however, when the rows collapse, the previous cells magically disappear.

To re-create the problem, run the project in the simulator or device with iOS 5 and tap the first cell to expand it. Then tap the cell again to collapse it. Finally, tap the cell directly underneath it. The previous one disappears.

Continuing the tapping for each cell in the section will cause all the cells to disappear, to where the entire section is missing.

I’ve also tried using reloadData instead of the current setup, but that ruins the animations and feels a bit like a hack anyway. reloadRowsAtIndexPaths should work, but the question is why doesn’t it?

See images of what's happening below:

Table appears:

table appears

Cell expands:

table expands

Cell collapses:

table collapses

Cell disappears (when tapping the cell underneath):

cell disappears

Keep repeating until the entire section disappears:

section disappears

EDIT: Overriding the alpha is a hack, but works. Here is another 'hack' that fixes it as well but WHY does it fix it?

JVViewController.m line 125:

if( previousIndexPath_ != nil )
{
    if( [previousIndexPath_ compare:indexPath] == NSOrderedSame ) currentCellSameAsPreviousCell = YES;

    JVCell *previousCell = (JVCell*)[self cellForIndexPath:previousIndexPath_];

    BOOL expanded = [previousCell expanded];
    if( expanded )
    {
        [previousCell setExpanded:NO];
        [indicesToReload addObject:[previousIndexPath_ copy]];
    }
    else if( currentCellSameAsPreviousCell )
    {
        [previousCell setExpanded:YES];
        [indicesToReload addObject:[previousIndexPath_ copy]];
    }

    //[indicesToReload addObject:[previousIndexPath_ copy]];
}

EDIT 2:

Made a few minor changes to demo project, worth checking out and reviewing JVViewController didSelectRowAtIndexPath method.

Your problem is in setExpanded: in JVCell.m, you are directly editing the frame of the target cell in that method.

- (void)setExpanded:(BOOL)expanded
{
    expanded_ = expanded;

    CGFloat newHeight = heightCollapsed_;
    if( expanded_ ) newHeight = heightExpanded_;

    CGRect frame = self.frame;
    frame.size.height = newHeight;
    self.frame = frame;
}

Update it to:

- (void)setExpanded:(BOOL)expanded
{
    expanded_ = expanded;
}

Then remove the call to -reloadRowsAtIndexPaths:withRowAnimation: at line 163 of JVViewController.m and it will animate as expected.

-reloadRowsAtIndexPaths:withRowAnimation: expects different cells to be returned for the provided indexPaths. Since you are only adjusting sizes -beginUpdates & -endUpdates is sufficent to layout the table view cells again.

Why do we all check for if(self) in init methods?

7 votes

I've been doing it religiously for a couple of years now. Checking for the validity of self after calling [super init...] methods:

self = [super init];
if (self != nil) {
    // initialize
}
return self;

You can do this in a variety of ways, as this question nicely sums up, but that question is about syntax, mine is about the concept.

I recently got a question from a colleague who's learning Objective-C and he asked me "why should I test for the existence of self, isn't it obvious that it's there?" and my short answer was "err, yeah, well there's instances where it can fail, so that's why." But the long answer is that I really don't understand myself why we test for it everywhere, when the instances where it could fail are very rare. Apple's reference guide tells us about some specific cases, like when initializing with files or when dealing with singletons. But these sound like very rare exceptions to the rule that [super init]s should just work.

So my question to you is this: Why do we always test the validity of self? Are we just implementing it everywhere to catch that one exception where it occurs? Why not just skip the whole if (self) thing and initialize our object if the chances of it succeeding are 100% (or is that never the case)?

P.S. I realize this question must be a dupe since it's so basic, but my search queries got a lot of other questions about the syntax of initialization. Dupe links are appreciated, cheers!

Here's a helpful old article on the subject, also including some common misconceptions about the initializer. I'd say the basic idea is that a particular class shouldn't have to be concerned with the implementation of its superclass, so we always check for nil in case of an error.

lldb fails to print variable values with "error: reference to 'id' is ambiguous"

6 votes

Since I updated to xcode 4.3 and let it switch my debugger over to lldb, any request to print a member variable fails with this error message:

(lldb) print request
error: error: reference to 'id' is ambiguous
note: candidate found by name lookup is 'id'
note: candidate found by name lookup is 'id'
error: 1 errors parsing expression

'self' is ok:

(lldb) print self
(LoginViewController *) $6 = 0x1cd54d50

And other forms of printing the member variable also fail:

(lldb) print self.request
error: property 'request' not found on object of type 'LoginViewController *'; did you mean to access ivar 'request'?
error: 1 errors parsing expression
(lldb) print self->request
error: error: reference to 'id' is ambiguous
note: candidate found by name lookup is 'id'
note: candidate found by name lookup is 'id'
error: 1 errors parsing expression

Everything else otherwise seems to be working fine. Xcode's variable window can correctly retrieve the value. I've tried a clean build and deleting ~/Library/Developer/Xcode/DerivedData/. Googling hasn't revealed any other instances of the same problem.

I found one thread on Apple's dev forum but no solution:

https://devforums.apple.com/message/623694

I've reported this to Apple as Bug ID# 11029004.

I found one workaround:

Use 'Edit scheme' under the 'Project' menu, select 'Run' in the left bar, the 'Info' tab, and change the Debugger to gdb.

Apparently Apple thought they'd fixed this bug in xcode 4.3.1, but it still happens. I submitted some extra debug information they requested, so I'm hoping it'll be fixed for the next release of xcode. It's still failing in 4.3.2.

iOS Facebook SDK - Best Practices?

6 votes

I was wondering what the "best practice" guidelines are for using the Facebook iOS SDK.

Specifically - I have several forms that use the Facebook SDK. My initial instinct as an OOP programmer was to create a "FacebookManager" class under my data-access-layer which handles all Facebook activity. Unfortunately since Facebook iOS SDK uses delegates and async methods, this is not so helpful since any other module using FacebookManager would have to pass in delegates for all responses anyway.

Then I figured that each ViewController would be a FBRequestDelegate by itself and handle all Facebook responses.

So, how do you do it in your app?

Thanks, Roey.

What I've done is to create a FacebookManager as you suggested. This manager becomes the FBRequestDelegate. Now I prefer blocks to the delegation model so all my FacebookManager methods are block based.

Here is what my post to a user's wall method looks like

- (void)postToUserWall:(NSDictionary*)postDictionary withCompleteHandler:(void(^)(id result, NSError* error))block {


  if( [facebook_ isSessionValid] ) {
    NSMutableDictionary* params = [postDictionary mutableCopy];
    [params setObject:facebook_.accessToken forKey:@"access_token"];
    FBRequest* request = [facebook_ requestWithGraphPath:@"me/feed" andParams:[postDictionary mutableCopy] andHttpMethod:@"POST" andDelegate:self];
    [[request params] setObject:block forKey:@"result"];
  }

}

Then on a success or error I just execute the block

- (void)processRequest:(FBRequest*)request withResult:(id)result andError:(NSError*)error {
  NSDictionary* params = [request params];
  if( [request params] != nil && [params objectForKey:@"result"] != nil ) {
    void(^completeBlock)(id result,NSError* error) = [params objectForKey:@"result"];
    completeBlock(result, nil);
  }
}


- (void)request:(FBRequest *)request didLoad:(id)result {
  [self processRequest:request withResult:result andError:nil];
}


- (void)request:(FBRequest *)request didFailWithError:(NSError *)error {
  [self processRequest:request withResult:nil andError:error];
}

I wish there was a better way to deal with the block but that's the best one I have found so far. Is this the best way to do it? Probably not but that's what I currently use and it seems to be ok, keeping all the FB interaction away from my View Controllers.

Note all the code here assumes ARC that's why there are no releases

Why does ARC work for iOS 4.0+ only?

6 votes

What is the technical reason for ARC to be supported by iOS 4.0 and above only?

It is my understanding that it is a compiler feature, which merely inserts memory management related code automatically instead of requiring the developer to do so. From what I read the calls themselves remain the same - at least that's what Apples Transitioning to ARC Guide implies.

As such, it should not involve features that have not been present in previous versions of iOS, and indeed ARC does work with iOS 4.0 despite having been introduced later.

I'm asking this question out of curiosity and don't actually need to make ARC work with iOS 3.x.

It is for the same reason that automatic reference counting only supports 64-bit Snow Leopard as a minimum deployment target: ARC support requires certain features present only in a new enough version of the modern runtime. That modern runtime was introduced with iOS 4.0, so older iOS versions lack the runtime capable of handling some of the things required technically by ARC. If it were just keyed to OS versions, 32-bit Snow Leopard applications would be supported as well, but only the 64-bit runtime is the modern one there.

If you watch Apple's presentations from WWDC 2011, particularly the "Objective-C Advancements In-Depth," you'll see that a number of under-the-hood improvements have been made to speed up the retain / release process, as well as things like the faster @autoreleasepool. There's an entire section on runtime support in the LLVM ARC specification. These improvements require more than just compiler support.

We already had to use the modern runtime for features like automatic synthesis of instance variables (as explained in Apple's documentation), so this isn't a terrible surprise.

Even iOS 4.0 as a target lacks support for weak references, so there are clearly technical issues at play here. This isn't just a marketing strategy to drive developers to the newer versions, as has been asserted by others.

UIPopoverController and UINavigationController cuts corners

6 votes

I have a problem with the display of my popover. After initWithContentViewController: and presentPopoverFromBarButtonItem:permittedArrowDirections:animated: it cuts corners of the navigation bar. How should I fix it?? Thanks.

Clipping corners of navigation bar

This is the code I'm using

NavContr *nav = [NavContr new];
nav.navigationBar.backgroundColor = [UIColor redColor];
UIPopoverController *tempPop = [[UIPopoverController alloc] initWithContentViewController:nav];
[tempPop presentPopoverFromBarButtonItem:mainButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];

This is probably because you have no root view controller, or are otherwise fiddling with the navigation controller in ways it was not meant to be played with. This is how you ought to be setting up the popover:

MyCustomViewController *viewController = [[UIViewController alloc] initWithNibName:@"MyCustomViewController" bundle:nil]; //or storyboard or whatever
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:viewController]; //you should have a root view controller before displaying the popover
tintColor = [UIColor redColor];
UIPopoverController *tempPop = [[UIPopoverController alloc] initWithContentViewController:nav];
[tempPop presentPopoverFromBarButtonItem:mainButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];

There are a few very important things going on here:

  • Your navigation controller should have a root view controller before you display it.
  • This code is using a standard UINavigationController instance. According to the documentation, you should not subclass UINavigationController, nor should you try and reinvent the wheel. Apple has created a complex and comprehensive framework, UIKit, that you can use to build amazing apps. If you try and step outside the box, you'll be creating an awful lot of work for yourself without any appreciable benefit.
  • This is using the tintColor property of the UINavigationBar class. If the tint is insufficient for your UI, you can also set the background image manually (refer to the docs).

If you want to make a popover with a navigation controller, use the built-in UINavigationController class. Don't subclass it and don't reinvent it. To customize the appearance of the navigationBar, use the UI_APPEARANCE_SELECTOR methods in the UINavigationBar class.

What is "super" in Objective-C? ( self != super )?

6 votes

I've read the question below, and the story SEEMS simple:

What exactly is super in Objective-C?

Yet ...

- (id) init
{
    NSLog(@"self=%p, super=%p", self, super);
}

That prints out "self=0xa83dc50, super=0xbfffe8d0". The addresses are NOT THE SAME???!?!?

That second address seems like a "special value" or something. What does it mean? (Great comment below notes that this value is a stack address of a special struct used by the compiler to implement the "super" behavior)


I can call [super init] and the call seems to work, or at least, nothing explodes ... not immediately. Calling [((id)0xbfffe8d0) init] fails hard with EXC_BAD_ACCESS.

Then there is the REALLY WEIRD part..... I've got a piece of code that for no explainable reason throws a "NSGenericException: collection was mutated while being enumerated" exception. Inside a DIFFERENT object (basically a wrapper that has a pointer to the NSEnumerator), commenting out the call to "[super init]" causes the exception to not happen. If I could, I'd put out a $$$ reward for an answer to THAT mind-bender.

"id sups = (id)0xbfffe8d0" ... that also leads to "collection is modified." ... WTF? Ok, so I'm posting a 2nd question for that bizzariotity ... Does casting an address to (id) have side-effects??? Is Address 0xbfffe8d0 special? (fixed: issue was with _NSCallStackArray)

You are messing with the man behind the curtain and he is punishing you for it... :)

super is a bit of compiler magic, really. When you say [super doSomething], the compiler will emit a call to objc_msgSendSuper() instead of objc_msgSend(). Most of the time -- there are some special cases.

In general, you should treat super as only a target for method calls. It should never be stored anywhere and should never be considered anything but that target expression for messaging.

In fact, uses of super that involve storage should likely be flagged by the compiler.

In terms of your bug, that sounds an awful lot like there is either corruption of memory, an over-release, and/or concurrency going on. You'll need to provide more code related to the enumeration and other relevant code to deduce further.

Objective-C ARC and passing C arrays of objects

5 votes

I'm sorry if this is a bit of a C-noob question: I know I need to swot up on my pointers. Unfortunately I'm on a deadline so don't have time to work through a whole book chapter, so I'm hoping for a bit more targeted advice.

I want to store some objective-C objects in a C array. I'm using ARC. If I were on the Mac I'd be able to use NSPointerArray instead, but I'm on iOS and that's not available.

I'll be storing a three-dimensional C array: conceptually my dimensions are day, height, and cacheNumber. Each element will either be a pointer to an objective-C object, or NULL.

The number of caches (i.e. the size of the cacheNumber dimension) is known at compile time, but the other two are not known. Also, the array could be very large, so I need to dynamically allocate memory for it.

Regarding ownership semantics, I need strong references to the objects.

I would like the whole three-dimensional array to be an instance variable on an objective-C object.

I plan to have a method that is - tableForCacheNumber:(int)num days:(int*)days height:(int*)height. That method should return a two-dimensional array, that is one specific cache number. (It also passes back by reference the size of the array it is returning.)

My questions:

  • What order should I put my dimensions so that I can easily return a pointer to the subarray for one specific cache number? (I think it should be first, but I'm not 100%.)

  • What should the return type of my method be, so that ARC doesn't complain? I don't mind if the returned array has an increased reference count or not, as long as I know which it's doing.

  • What type should my instance variable that holds the three dimensional array be? I think it should just be a pointer, since that ivar just represents the pointer to the first item that's in my array. Correct? If so, how do I specify that?

  • When I create the three-dimensional array (for my ivar), I guess I do something like calloc(X * Y * Z, sizeof(id)), and cast the result to the type for my ivar?

  • When accessing items from the three-dimensional array in the ivar, I believe I have to dereference the pointer each time, with something like (*myArray)[4][7][2]. Correct?

  • Will the two-dimensional array I return from the method be similarly accessed?

  • Do I need to tag the returned two-dimensional array with objc_returns_inner_pointer?

I'm sorry once again that this is a bit of a bad Stack Overflow question (it's too long and with too many parts). I hope the SO citizens will forgive me. To improve my interweb karma, maybe I'll write it up as a blog post when this project has shipped.

Answering my own question because this web page gave me the missing bit of info I needed. I've also upvoted Graham's answer, since he was very helpful in getting my head round some of the syntax.

The trick I was missing is knowing that if I want to refer to items in the array via the array[1][5][2] syntax, and that I don't know the sizes of my array at compile time, I can't just calloc() a single block of data for it.

The easiest to read (although least efficient) method of doing that is just with a loop:

__strong Item ****cacheItems;

cacheItems = (__strong Item ****)calloc(kMaxZooms, sizeof(Item ***));

for (int k = 0; k < kMaxZooms; k++) 
{
    cacheItems[k] = (__strong Item ***)calloc((size_t)daysOnTimeline, sizeof(Item **));

    for (int j = 0; j < daysOnTimeline; j++) 
    {
        cacheItems[k][j] = (__strong Item **)calloc((size_t)kMaxHeight, sizeof(Item *));
    }
}

I'm allocating a three dimensional array of Item *s, Item being an objective-C class. (I have of course left out the error handling code in this snippet.)

Once I've done that, I can refer to my array using the square brackets syntax:

cacheItems[zoom][day][heightToUse] = item;

The web page I linked to above also describes a second method for performing the memory allocations, that uses only one call to calloc() per dimension. I haven't tried that method yet, as the one I've just described is working well enough at the moment.

Securely send a Plain Text password?

5 votes

I'm working on an application for iOS which will have the user fill out their password. The password will then be posted to a PHP page on my site using either POST or GET. (It must be plaintext because it is used in a script.)

Besides HTTPS, is there any way to secure the password? Encrypt it in Obj-C and then decrypt it in PHP?

NOTE: The username is not sent... only the password is posted to the server.

EDIT: To clarify, David Stratton is correct... I'm trying to prevent malicious sniffers in public locations from simply reading clear text passwords as they are posted to the server.

Challenge response outline

Lets assume you have one-way hash function abc (in practice use md5 or sha1).

The password you store in your database is abc(password + salt) (store the salt separately)

The server generates a random challenge challenge and sends it to the client (with the salt) and calculates the expected response: abc(challenge + abc(password + salt))

The client then calculates: abc(user_password + salt) and applies the challenge to get abc(challenge + abc(user_password + salt)), that is sent to the server and the server can easily verify validity.

This is secure because:

  • The password is never sent in plaintext, or stored in plaintext
  • The hash value that is sent changes every time (mitigates replay attack)

There are some issues:

How do you know what salt to send? Well, I've never really found a solution for this, but using a deterministic algorithm to turn a username into a salt solves this problem. If the algorithm isn't deterministic an attacker could potentially figure out which username exists and which do not. This does require you to have a username though. Alternatively you could just have a static salt, but I don't know enough about cryptography to assess the quality of that implementation.

How to map xml (objects) to methods in Objective-C?

4 votes

I have an xml file that contains a structure.. In this structure, I have Actions node. So under Actions node, there are multiple "Action" nodes that each has Value and Name attributes.

e.g.

<?xml version="1.0" encoding="ISO-8859-1"?>

<Testcases SuiteName="CalculatorActions">

    <Testcase id="101" Name="testAddFunction">
        <Setup/>
        <TearDown/>
        <Test>
            <Action Name="Enter first operand" Type="input" Value="5"/>
            <Action Name="Enter second operand" Type="input" Value="3"/>
            <Action Name="Select operator" Type="input" Value="+"/>
            <Action Name="Click Calculator" Type="operation"/>
        </Test>
        <Validations>
            <Action Name="Validate result" Type="output" Value="8"/>
        </Validations>
    </Testcase>

</Testcases>

What I would like to do is; I want to map these actions to the methods that I have implemented in Objective-C.

Let's say i have a class called; "CalculatorActions" and defined 5 methods inside. I would like to map the actions that i have in xml (text format) to the methods i created in CalculatorActions.

e.g.

@interface CalculatorActions : NSObject

// Property
@property (strong, nonatomic) NSString* actionScript;

// Actions
- (void)enterFirstOperand:(double)operand;

- (void)enterSecondOperand:(double)operand;

- (void)selectOperator:(NSString*)operator;

- (void)clickCalculate;

// Validations

-(void)validateResult:(NSString*)exptectedResult;

@end

so when i read the xml file, I would want to map the actions in xml file to the corresponding method in a class.

I think what i am looking for is something like;

@interface CalculatorActions

[Action("addOperand", "Enter first operand")]
- (void) addOperand:(double)operand1 ToOther:(double)operand2;

What would be the best way to do this?

You can create an NSInvocation instance, set the selector, arguments, and optionally capture the return value. You can create these all with strings.

e.g.

SEL mySelector = NSSelectorFromString(@"testAddFunction");
Class MyClass = NSClassFromString(@"CalculatorActions");
NSString *myArgument = @"5";

NSInvocation *myInvocation = [NSInvocation invocationWithMethodSignature:[MyClass instanceMethodSignatureForSelector:mySelector]];
[invocation setTarget:myClass];
[invocation setSelector:mySelector];
[invocation setArgument:&myArgument atIndex:2];
[invocation invoke];

Note - the setArgument: selector takes a pointer address, and the index of the arguments start at 2.