Best objective-c questions in November 2011

How to change a particular color in an image?

13 votes

My question is if I have a Lion image just I want to change the color of the lion alone not the background color. For that I referred this SO question but it turns the color of whole image. Moreover the image is not looking great. I need the color change like photoshop. whether it is possible to do this in coregraphics or I have to use any other library.

EDIT : I need the color change to be like iQuikColor app

enter image description here

Here is the sketch of a possible solution using OpenCV:

  • Convert the image from RGB to HSV using cvCvtColor (we only want to change the hue).
  • Isolate a color with cvThreshold specifying a certain tolerance (you want a range of colors, not one flat color).
  • Discard areas of color below a minimum size using a blob detection library like cvBlobsLib. This will get rid of dots of the similar color in the scene.
  • Mask the color with cvInRangeS and use the resulting mask to apply the new hue.
  • cvMerge the new image with the new hue with an image composed by the saturation and brightness channels that you saved in step one.

There are several OpenCV iOS ports in the net, eg: http://www.eosgarden.com/en/opensource/opencv-ios/overview/ I haven't tried this myself, but seems a good research direction.

iOS 5 does not allow to store downloaded data in Documents directory?

13 votes

I have made an application for my client by keeping target iOS as 4.
But since the application still not submitted to Apple store, my client is planning to upgrade it for iOS 5.0.

For this I read the guideline from Apple and found that "Only user-generated data or that cannot otherwise be recreated by your application, should be stored in the /Documents directory and rest should be stored to /Library/Caches directory"

In my application, I am using server model of in-app purchase for non-consumable product. For this I am storing all my downloaded data (which are basically books or magazines) to Documents directory. The Database is also present in the same directory which contains the details about the downloaded products.

My question is,
1. Should I have to change my code to store the downloaded data to Library/Caches directory instead of to the Documents directory?
2. Where should my database file be placed (to Documents or Caches)?

If I put it products in the Caches then I have to change the logic of retrieval also, since it is considered that if record is present in database, there is no need change the existence of the file and it directly opens it when user clicks on the magazine.

Kindly guide me on this issue.
Thanks in advance.

Here are the trade-offs:

  • If you put your files in the Documents directory then they are backed up to iTunes or iCloud but if they are too big and it's possible to download the files again then Apple may reject your app
  • If you put your files in the Cache directory then they won't be backed up and Apple won't reject your app. However, when iOS 5 gets low on space it may delete all the files in there.

However, with iOS 5.0.1 there is a third option:

  • Put files in Documents but flag them so that they are not backed up. There's a technote (QA1719) on how to do this.

I think this is probably the best answer for you.

Disadvantages of Objective-C++?

12 votes

I'm writing a large project for iOS in Objective-C++. I'm mainly using Objective-C for the UI and other Apple APIs, and C++ for internal audio processing and other information handling. I was wondering about the drawbacks of mixing Objective-C and C++ freely.

Of course, mixing two object models has its inherent limitations and potential for messiness and confusion. I'm more curious about how using Objective-C++ will affect the compilation process, syntactic pitfalls I might run into, problems with readability and how I might avoid those, etc. I'm interested to hear what your experiences with Objective-C++ have been like and tips you might have for approaching this.

ObjC++ is extremely powerful - you can select and mix the features you need for your problems and interface with C, ObjC, and C++ all at the same time. I've been using it for many years. There are of course, a few caveats, and it's good to be aware of them so you can minimize the issues you might encounter:

Compilation

The compilation times are much higher than ObjC or C++ when you begin creating nontrivial programs.

There are a few common approaches to declaring your C++ types in ObjC types:

  • Opaque types
  • Forward Declarations
  • Forward Declarations with smart pointers
  • By value

I'll just gloss over this, as it is inferred from the OP that you are familiar with both languages. As well, this is one of the more publicly written about introductory topics on ObjC++.

Given the C++ type:

class t_thing { public: int a; };

You have a number of ways to declare your ivars:

Opaque type:

@interface MONClass : NSObject { void* thing; } @end

This should be avoided. It's not good to erase type safety. The two forward options will introduce type safety.

This variant is compatible with ObjC translations.

Forward Declaration:

class t_thing;
@interface MONClass : NSObject { t_thing* thing; } @end

This is better than an opaque type, but the smart pointer is even better - pretty obvious if you are used to writing modern C++.

This variant is compatible with ObjC translations as long as your C++ types are in the global namespace.

Forward Declaration using smart pointers:

class t_thing;
@interface MONClass : NSObject { t_smart_pointer<t_thing> thing; } @end

This one is the best if you intend to set up translation firewalls (e.g. use PIMPL and forwards to reduce dependencies). As well, the ObjC object is already going through locking and allocations, so it's not a bad point to allocate a C++ type. If you have several declarations, you may prefer to create a wrapper type for your implementation to reduce individual allocations.

This variant is not compatible with ObjC translations.

This is a good time to remind you that there is a compiler option with ObjC++ that you should enable: GCC_OBJC_CALL_CXX_CDTORS. What happens when this flag is set? The compiler produces hidden objc methods which invoke your C++ ivars' constructors and destructors. If you use GCC_OBJC_CALL_CXX_CDTORS your C++ ivars must be default constructible. If you do not enable this flag, you must manually construct and destruct your ivars perfectly - if you construct it twice or do not override an initializer of the subclass, then you are facing UB.

By value:

#include "thing.hpp"    
@interface MONClass : NSObject { t_thing thing; } @end

Highest dependency. This is (in general) the route I chose, and I have some regrets about that. I've just moved things over to use more C++ and use composition with smart pointers (outlined above) to reduce dependency.

This variant is not compatible with ObjC translations.

One other thing about the modern ObjC compilers: The compiler lays out your C++ types' ivars/structure in the binary. Believe it or not, this can consume a lot of binary space.

The point here is that there are multiple forms the program can take. You can mix these techniques to reduce dependency, and this is one of the best places to introduce dependency firewalls because ObjC is very dynamic (its methods must be exported in one translation), and object creation requires allocations, locks, introduction into the reference counting system - initialization time for a single object is already relatively high, and the implementation will always be hidden.

If much of your program is still in ObjC and you want to keep it that way, then you will need to resort to forwards of types which are declared in the global namespace or opaque base types which you vend specializations through an object factory. Personally, I just use so much C++ that this was not an ideal option, and wrapping implementations in global types quickly became tiresome.

Meanwhile, since compilation times are high, the inverse is true: If you can keep significant portions of your implementation as C++, then you will save a lot of compilation time. For this reason and ARC (below) you can gain a lot by keeping your primitive Apple types as CF types where possible, so you can continue building C++ programs without the ObjC extensions.

Syntax

I rarely have problems but I keep my C++ classes quite strict:

  • I prohibit copy and assignment by default.
  • I rarely declare customized operators for C++ types.

If you're awesome at C++, then you could avoid this problem, but I prefer the compiler to catch silly mistakes I make.

One evident problem is C++ scope resolution within an ObjC message send. This requires a space:

[obj setValue:::func(a)]; // << bad
[obj setValue: ::func(a)]; // << good

Readability

One problem I have encountered is that I have never found a code formatter that supports the ObjC++ syntax well.

ObjC Messaging

  • ObjC Messaging and return by value: You need to check before messaging nil when returning C++ types by value. If the object you message is nil, then the result will be zeroed memory on the modern runtimes (x86_64 and iOS). If you use that instance, it is undefined behaviour.

  • ObjC Messaging and return by reference: You need to check before messaging nil when returning C++ types by reference. If the object you message is nil, then the result will be undefined behaviour (reference to 0/NULL).

To overcome the ObjC Messaging issues, I typically use a form like this:

- (bool)selector:(std::string&)outValue;

where the return value is false for some internal error, and true for success.

then you can safely write:

if (![obj selector:outString]) { /* bail here */ }

Miscellanea

  • ARC Compatibility: ObjC++ is not good for ARC. The primary reason is that ARC does not follow through mixed object models. Example: If you try to put a ObjC member into a C++ type, the compiler will reject the program under ARC. This is not really an issue because MRC is dead simple with ObjC++ (assuming you also use SBRM), but it may be a concern for the lifetime of your program.

  • Synthesized Properties: You will have to define your properties for C++ types.

  • External Tools: Beyond Xcode's toolset, there are few programs that handle or recognize ObjC++ well. Text editors, IDEs, utilities.

  • Apple's Tools: Within Xcode's utilities, Xcode's support for ObjC++ is a bit low. Refactoring (unavailable), navigation (improved with clang parser), outlining (is rather primitive), ObjC++ can disrupt IB's utilities, project upgrading is often not supported.

Is there a way to check if process is 64 bit or 32 bit?

10 votes

I am trying to find process type (32 bit/ 64bit) from process pid?

I get the process information and process list from using GetBSDProcessList method described here.

how can we get the process type information? Any Ideas?

I can use defined(i386) or defined(x86_64) but only if we are in process. I am out of the process.

GetBSDProcessList returns a kinfo_proc. The kinfo_proc has a kp_proc member which is of type extern_proc. The extern_proc has a p_flag member, which one of the flags is P_LP64, indicating "Process is LP64"). So you should be able to check with:

int is64bit = proc->kp_proc.p_flags & P_LP64;

(Note: As shown in the comment, you need to use the B_get_process_info found in http://osxbook.com/book/bonus/chapter8/core/download/gcore.c:

static int
B_get_process_info(pid_t pid, struct kinfo_proc *kp)
{
    size_t bufsize      = 0;
    size_t orig_bufsize = 0;
    int    retry_count  = 0;
    int    local_error  = 0;
    int    mib[4]       = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 0 };

    mib[3] = pid;
    orig_bufsize = bufsize = sizeof(struct kinfo_proc);

    for (retry_count = 0; ; retry_count++) {
        local_error = 0;
        bufsize = orig_bufsize;
        if ((local_error = sysctl(mib, 4, kp, &bufsize, NULL, 0)) < 0) {
            if (retry_count < 1000) {
                sleep(1);
                continue;
            }
            return local_error;
        } else if (local_error == 0) {
            break;
        }
        sleep(1);
    }

    return local_error;
}

)

How do I use regex to search ignoring certain characters with NSPredicate?

10 votes

In Hebrew, there are certain vowels that NSPredicate fails to ignore even when using the 'd' (diacritic insensitive) modifier in the predicate. I was told that the solution is to use regular expressions to do the search.

How do I take a search string and "use regex" to search hebrew text that contains vowels, ignoring those vowels?

Edit:

In other words, If I wanted to search the following text, disregarding dashes and asterisks, how would I do so using regex?

Example Text:

I w-en*t t-o the st*o*r*-e yes-ster*day.

Edit 2:

Essentially, I want to:

  1. Take an input string from a user
  2. Take a string to search
  3. Use a regex based on the user's search string to search for "contains" matches in the larger block of text. The regex should ignore vowels as shown above.

Edit 3:

Here's how I'm implementing my search:

//
//  The user updated the search text
//

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller 
shouldReloadTableForSearchString:(NSString *)searchString{

    NSMutableArray *unfilteredResults = [[[[self.fetchedResultsController sections] objectAtIndex:0] objects] mutableCopy];

    if (self.filteredArray == nil) {
        self.filteredArray = [[[NSMutableArray alloc ] init] autorelease];
    }

    [filteredArray removeAllObjects];

    NSPredicate *predicate;

    if (controller.searchBar.selectedScopeButtonIndex == 0) {
        predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", searchString];
    }else if (controller.searchBar.selectedScopeButtonIndex == 1) {
        predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[cd] %@", searchString];            
    }else if (controller.searchBar.selectedScopeButtonIndex == 2){
        predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", searchString];
    }else{
        predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (dvarTorahContent CONTAINS[cd] %@)", searchString,searchString,searchString];
    }

    for (Article *article in unfilteredResults) {

        if ([predicate evaluateWithObject:article]) {
            [self.filteredArray addObject:article];
        }

    }

    [unfilteredResults release];


    return YES;
}

Edit 4:

I am not required to use regex for this, was just advised to do so. If you have another way that works, go for it!

Edit 5:

I've modified my search to look like this:

NSInteger length = [searchString length];

NSString *vowelsAsRegex = @"[\\u5B0-\\u55C4]*";

NSMutableString *modifiedSearchString = [searchString mutableCopy];

for (int i = length; i > 0; i--) {
    [modifiedSearchString insertString:vowelsAsRegex atIndex:i];
}

if (controller.searchBar.selectedScopeButtonIndex == 0) {
            predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", modifiedSearchString];
        }else if (controller.searchBar.selectedScopeButtonIndex == 1) {
            predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[cd] %@", modifiedSearchString];            
        }else if (controller.searchBar.selectedScopeButtonIndex == 2){
            predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", modifiedSearchString];
        }else{
            predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (dvarTorahContent CONTAINS[cd] %@)", modifiedSearchString,modifiedSearchString,modifiedSearchString];
        }

for (Article *article in unfilteredResults) {
  if ([predicate evaluateWithObject:article]) {
    [self.filteredArray addObject:article];
  }          
 }

I'm still missing something here, what do I need to do to make this work?

Edit 6:

Okay, almost there. I need to make two more changes to be finished with this.

I need to be able to add other ranges of characters to the regex, which might appear instead of, or in addition to the character in the other set. I've trie changing the first range to this:

[\u05b0-\u05c, \u0591-\u05AF]?

Something tells me that this is incorrect.

Also, I need the rest of the regex to be case insensitive. What modifier do I need to use with the .* regex to make it case insensitive?

This answer picks up where the question left off. Please read that for context.

As it turns out, iOS can make regular expressions case insensitive using an Objective-C modifier to NSPredicate. All that's left is to combine the two ranges. I realized that they are actually two consecutive ranges. My final code looks like this:

NSInteger length = [searchString length];

NSString *vowelsAsRegex = @"[\u0591-\u05c4]?[\u0591-\u05c4]?"; //Cantillation: \u0591-\u05AF Vowels: \u05b0-\u05c

NSMutableString *modifiedSearchString = [searchString mutableCopy];

for (int i = length; i > 0; i--) {
    [modifiedSearchString insertString:vowelsAsRegex atIndex:i];
}

if (controller.searchBar.selectedScopeButtonIndex == 0) {
  predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", modifiedSearchString];
}else if (controller.searchBar.selectedScopeButtonIndex == 1) {
    predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[c] %@", modifiedSearchString];            
}else if (controller.searchBar.selectedScopeButtonIndex == 2){
    predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[c] %@", modifiedSearchString];
}else{
    predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[c] %@) OR (dvarTorahTitle CONTAINS[c] %@) OR (dvarTorahContent CONTAINS[c] %@)", modifiedSearchString,modifiedSearchString,modifiedSearchString];
}

[modifiedSearchString release];

for (Article *article in unfilteredResults) {
  if ([predicate evaluateWithObject:article]) {
    [self.filteredArray addObject:article];
  }          
}

Note that the range portion of the regular expression repeats itself. This is because there can be both a cantillation mark and a vowel on a single letter. Now, I can search uppercase and lowercase English, and Hebrew with or without vowels and cantillation marks.

Awesome!

Objective-C blocks and C++ objects

8 votes

I have a method that is being executed on a background thread. From that method I'm trying to dispatch_async a block on the main thread. The block uses a local C++ object which is supposed to be copy constructed according to the Apple reference. I'm getting a segmentation fault and from the trace I see that something very sketchy is going on. Here's the simplified version of my code.

struct A
{
    A() { printf("0x%08x: A::A()\n", this); }
    A(A const &that) { printf("0x%08x: A::A(A const &%p)\n", this, &that); }
    ~A() { printf("0x%08x: A::~A()\n", this); }
    void p() const { printf("0x%08x: A::p()\n", this); }
};

- (void)runs_on_a_background_thread
{
    A a;
    a.p();
    dispatch_async(dispatch_get_main_queue(), ^{
        printf("block begins\n");
        a.p();
        printf("block ends\n");
    });
}

And this is the output:

0xbfffc2af: A::A()
0xbfffc2af: A::p()
0xbfffc2a8: A::A(A const &0xbfffc2af)
0x057ae6b4: A::A(A const &0xbfffc2a8)
0xbfffc2a8: A::~A()
0xbfffc2af: A::~A()
0xbfffdfcf: A::A(A const &0x57ae6b4)
0xbfffdfcf: A::~A()
block begins
0xbfffdfcf: A::p()
block ends
0x057ae6b4: A::~A()

There are two things that I don't understand. The first one is why by the time it gets to 0xbfffdfcf: A::p() the destructor on that object has been called already.

The second thing I'm struggling with is why there are so many copy constructors being called. I expect one. That should happen when a copy of a is created to be captured by the block.

I'm using Xcode 3.2.5 with GCC. I experience the same behavior on the simulator and on the device.

I just tested this on LLVM 3.0.

0xb024ee18: A::A()
0xb024ee18: A::p()
0xb024ee04: A::A(A const &0xb024ee18)
0x06869364: A::A(A const &0xb024ee04)
0xb024ee04: A::~A()
0xb024ee18: A::~A()
block begins
0x06869364: A::p()
block ends
0x06869364: A::~A()

As you can see the destructors get called appropriately in this case, I'd chalk this up to a complier bug in the extremely outdated compiler you're using.

The copies in this instance seem inline with what I'd expect. The block copies the stack based object into the block when it gets captured. And then again when the block gets copied from the stack to the heap.

Is self.iVar necessary for strong properties with ARC?

7 votes
  1. If I declare a property strong, like so:

    @property (strong, nonatomic) UIView *iVar;
    

    When I'm setting it, does it matter if I do iVar = ... or self.iVar = ...? It seems that with ARC, they do the same thing.

  2. If I only declare the instance variable (not the @property), e.g., BOOL selected, does that mean it's inferred to be __unsafe_unretained (since there's no property specifying it to be strong), or must I explicitly specify that?

It seems like I may have answered my own questions above in answering ARC: How to release static variable?, but I'm still slightly confused on the above questions.

From a memory management perspective, using ivar = ... or self.property = ... (note: there's no such thing as self.ivar) are the same. However, using ivar = ... doesn't invoke the setter while self.property = ... does. This has 3 important ramifications, in no particular order:

  1. If the property is not marked nonatomic, then access to the underlying ivar will not take the lock and you will be breaking the atomicity implications.
  2. If the property is overridden, either by you or by a subclass, the overridden setter will not be invoked.
  3. KVO notifications will not be sent.

As for only declaring the ivar, it has the same memory management semantics as declaring a local variable. This is documented in section 4.4 of the Objective-C Automatic Reference Counting document, but basically, if it's an object, it will be inferred to be __strong.

Objective-C - ARC - NSNumber - Segmentation Fault

7 votes

I have an objective-C program and I am using ARC (Automatic Reference Counting), it throws a segmentation fault in line 23 (see program below).

Question 1) Why does the segmentation fault occur ?

Given below is the program:

#import<Foundation/Foundation.h>

@interface Car : NSObject
@property (weak) NSNumber* doors;
@end

@implementation Car 
@synthesize doors;
@end

int main()
{
    system("clear");

    @autoreleasepool
    {    
        Car *car1 = [[Car alloc] init];

        printf("1\n");
        NSNumber *d1 = [[NSNumber alloc] initWithInteger: 4]; 

        printf("2\n");
        car1.doors = d1;   //Segmentation fault.. why ?

        printf("3\n");
    }   

    printf("---- end\n");

    return(0);
}

Output:

1
2
Segmentation fault: 11

Congratulations: you’ve found a bug in Core Foundation!

As Bill suspected, this is related to tagged pointers in Lion. When you create

NSNumber *d1 = [[NSNumber alloc] initWithInteger: 4];

d1 doesn’t point to an actual NSNumber instance. Instead, d1 is a tagged pointer containing 0x4c3, where 0x4 is the payload in the tagged pointer.

When you try to use a tagged pointer as the value of a weak property, one of the steps executed by the Objective-C runtime is to send -allowsWeakReference to the instance to verify whether it can be used as a weak reference. Since NSNumber doesn’t override that method, the default implementation in NSObject is executed, which in turn sends _isDeallocating, which in turn calls _CFIsDeallocating() as shown in this stack trace:

#0  0x00007fff8ccdbacd in _CFIsDeallocating ()
#1  0x00007fff8ccd3119 in -[__NSCFNumber _isDeallocating] ()
#2  0x00007fff8be34b15 in -[NSObject(NSObject) allowsWeakReference] ()
#3  0x0000000100000ded in main () at test.m:12

If you read CFRuntime.c, you’ll see that _CFIsDeallocating() casts the corresponding pointer to CFRuntimeBase * in order to read _cfinfo. For normal Core Foundation objects, this works because every regular Core Foundation reference points to an instance that starts with the isa pointer, followed by _cfinfo. However, tagged pointers do not point to actual (allocated) memory, so _CFIsDeallocating() tries to dereference a pointer that is not valid, hence the segmentation fault.

You should file a bug report with Apple. In the meanwhile, use a strong or unsafe_unretained property.


Edit: to get the backtrace, build your executable with -g to include debug information, e.g.:

$ clang test.m -g -fobjc-arc -framework Foundation -o test

and run it with GDB:

$ gdb test
…
(gdb) run

The program will crash:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000000000004cb
0x00007fff8ccdbacd in _CFIsDeallocating ()

Use the bt command in GDB to get the backtrace:

(gdb) bt
#0  0x00007fff8ccdbacd in _CFIsDeallocating ()
#1  0x00007fff8ccd3119 in -[__NSCFNumber _isDeallocating] ()
#2  0x00007fff8be34b15 in -[NSObject(NSObject) allowsWeakReference] ()
#3  0x00007fff875173a6 in weak_register_no_lock ()
#4  0x00007fff875179f9 in objc_storeWeak ()
#5  0x0000000100000c0e in -[Car setDoors:] (self=0x100113f60, _cmd=0x100000e7a, doors=0x4c3) at test.m:8
#6  0x0000000100000d45 in main () at test.m:23

and then the quit command to exit GDB:

(gdb) quit

In Xcode, use the Mac OS X > Application > Command Line Tool template. When you run your program, Xcode should automatically show the GDB prompt in the debug area. If the debug area doesn’t show up in the Standard Editor, select View > Debug Area > Show Debug Area.

How to test whether the square root of a number will be rational?

7 votes

How can you test whether the square root of a number will be rational or not?

Is this even possible?

I need this because I need to work out whether to display a number as a surd or not in a maths app I'm developing at the moment.

After reading comments and the answers to another question I have since asked, I realised that the problem came from a floating point inaccuracy which meant that some values (eg 0.01) would fail the logical test at the end of the program. I have amended it to use NSDecimalNumber variables instead.

double num, originalnum, multiplier;
int a;

NSLog(@"Enter a number");
scanf("%lf", &num);
//keep a copy of the original number
originalnum = num;

//increases the number until it is an integer, and stores the amount of times it does it in a
for (a=1; fmod(num, 1) != 0 ; a++) {
    num *= 10;
}

a--;
//when square-rooted the decimal points have to be added back in
multiplier = pow(10, (a/2));
if (fmod(originalnum, 1) != 0) {
    multiplier = 10;
}

NSDecimalNumber *temp = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithDouble:sqrt(num)/multiplier] decimalValue]];
NSDecimalNumber *result = [temp decimalNumberByMultiplyingBy:temp];
NSDecimalNumber *originum = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithDouble:originalnum] decimalValue]];

if ((fmod(sqrt(num), 1) == 0) && ([result isEqualToNumber:originum])) {
    NSLog(@"The square root of %g is %@", originalnum, temp);
}
else {
    NSLog(@"The square root of this number is irrational");
}

Mixing C++ and Objective-C

7 votes

I am using C++ as the app backbone and Objective-C for the GUI, that's fine.

But when it comes to mixing those code together in Objective-C++ (.mm file), I have got a few question:

1. Can I mix STL containers with Objective-C or Cocos2D objects?

E.g. In Objective-C header, can I do the following?

#include <vector>
#include <boost\shared_ptr.hpp>
@interface MyClass : NSObject {
  std::vector<boost::shared_ptr<CCSprite> > m_spriteList;
}

And then in the .mm file, I want to do

CCSprite* newSprite = [/* cocos2d stuff here... */];
m_spriteList.push_back(newSprite);

Is the above code valid? It certainly is in C++, but I am not sure when mixing C++ and Objective-C and Cocos2D.

2. Memory management using C++ smart pointer object in Objective-C?

When I try to use the C++ code in Objective-C, I want to declare a C++ object as a member variable in the Objective-C header file.

Say I have a C++ class declared in the test.h header:

Test{
};

In Objective-C header file, I want to do

#include "test.h"
#incude <boost/scoped_ptr.hpp>

#include <vector>
@interface MyClass : NSObject {
   Test* m_testObjectPtr; // (1)
   boost::scoped_ptr<Test>  m_testOjbSmartPtr; // (2)
}

In the above code, is (2) okay? Can I use smart pointers in Objective-C just like in C++ code? And can I assume the Test class destructor will be called when the MyClass object is destroyed?

Or if (2) is not okay in Objective-C++, is (1) okay? Would I need to manually call delete m_testObjectPtr in dealloc?

You can use smart pointer only on c++ classes. if you use then on objective-c classes you will either get compile error or crash somewhere.
You can also use containers with pointers of objective-c classes like

std::vector<CCSprite *> spriteList;

just make sure you retain them when you insert them to list and release them when you remove them.
In both cases, you can make a smart pointer of your own that calls retain and release in constructor/destruct/copy like needed and then don't worry about retain release.
Also destructor for member c++ objects will be called automatically when the object is deallocated.
An example of an objective c wrapper would be

template<typename T>
struct shared_objc_object
{
    T *Object;
    shared_objc_object : Object(nil) { }
    shared_objc_object(T *Object) : Object([Object retain]) { }
    shared_objc_object(shared_objc_object &other) :
        Object([other.Object retain]) { }
    ~shared_objc_object() { [Object release]; }
    shared_objc_object &operator =(shared_objc_object &other)
    {
        [Object release];
        Object = [other.Object retain];
    }
}

And you can use

std::vector<shared_objc_object<CCSprite *>> spriteList;
spriteList.push_back(some_sprite);

and don't care about retain/release

How should private and public members be implemented in objective-c?

7 votes

I had some discussion related to the use of properties and instance variables at work, therefore I would like to find a wiki answer for that. Now, I know there's no real private member type in objective-c, everything is pretty much public. However, I'm a little bit concerned about the way we should design our classes and also to comply to OOP principles. I would like to hear opinions of these three design approaches:

A. According to various post and even to a new Stanford university iPhone development courses, you should always use properties everywhere you can. However IMHO, this approach brakes OOP design principles because in this case, all members become public. Why do I need to publish all my internal/local instance variables to outside? Also, there's some very little (but still) overhead if you use synthesized setters via properties, instead using local ivar directly. Here's a sample:

//==== header file =====//
@interface MyClass : NSObject

@property (nonatomic, retain) NSString *publicMemberWithProperty;
@property (nonatomic, retain) NSString *propertyForPrivateMember;

@end

B. Another approach is to declare ivars in header file (without declaring relative properties) for private members, and in the same header file, to declare pure properties (without declaring relative ivars) for public members. In such case, ivars would be used directly in the class. This approach makes sense but not uses all benefits from properties because we have manually to release old values before setting the new ones. Here's a sample:

//==== header file =====//
@interface MyClass : NSObject{
  NSString *_privateMember;
}

@property (nonatomic, retain) NSString *publicMemberWithProperty;

@end

C. To declare pure properties (without declaring relative ivars) for public members in header file, and to declare pure properties (without declaring relative ivars) for private members in private interface in implementation file. This approach IMHO is more clear than the first one, but the same question remains: why do we have to have properties for internal/local members? Here's a sample:

//==== header file =====//
@interface MyClass : NSObject

@property (nonatomic, retain) NSString *publicMemberWithProperty;

@end

//==== implementation file =====//
@interface MyClass()

@property (nonatomic, retain) NSString *propertyForPrivateMember;

@end

This decision freedom annoys me a little bit and I would like to find a confirmation from respective sources about how things should be done. However, I was unable to find such strict statements in Apple docs on that, so please post a link to apple docs if any exists, or to any other theory that clears that.

By using class extensions you can have private properties.

A class extension syntax is simple:

Inside the .m-file, that has the class, create a unnamed category:

.h

@interface OverlayViewController : UIViewController <VSClickWheelViewDelegate>
- (IBAction)moreButtonClicked:(id)sender;
- (IBAction)cancelButtonClicked:(id)sender;
@end

.m

#import "OverlayViewController.h"

@interface OverlayViewController ()
@property(nonatomic) NSInteger amount;
@property(retain,nonatomic)NSArray *colors;
@end

@implementation OverlayViewController
@synthesize amount = amount_;
@synthesize colors = colors_;

//…

@end

Now you got all the aspects of properties for private members, without exposing them to public. There should be no overhead to synthesized properties to written getter/setters, as the compiler will create more or less the same at compile time.

Note that this code uses synthesized ivars. No ivar declaration in the header is needed.

There is a nice cocoawithlove article, about this approach.

You also ask why to use properties for private ivars. There are several good reasons:

iOS 5: Curious about UIAppearance

7 votes

On the tech talk 2011 I saw a speech about the new UIAppearance protocol. There is not a lot of documentation out there yet. I will shortly summarize what I remember to explain where my question is coming from:


ABOUT UIAppearance:

So far you had to customize EVERY navigation bar property in all your app view controllers. With the new appearance property you can do it in only one place for all navigation bars in your app. For instance: if you want to customize your Navigation bar background image you could do it like this:

[[UINavigationBar appearance] setBackgroundImage:
   [UIImage imageNamed:@"MyImageName"] forBarMetrics:UIBarMetricsDefault]; 

This will set the background image of ALL navigation bars within your application. With the barMetrics you specify whether you want the image to be used also in landscape mode or not.

If you want to specify the appearance to be applied only in some view controllers there is also a method in the docs to control that by specifying where your objects are located:

[[UIBarButtonItem appearanceWhenContainedIn:
    [ABPeoplePickerNavigationController class], nil] setTintColor:myNavBarColor];

Also worth to mention is, if you have single customized instances, differing from your appearance settings, theses instances will not be effected by the appearance proxy.


QUESTION:

a) How do I know which instances of a class work with the appearance property? For e.g. since UITableView conforms to the UIAppearance protocol I was thinking I could do something like

[[UITableView appearance] setBackgroundColor:mytableViewColor];

to manipulate the background color of all my table views, but I can't!

b) Is there a list of all properties that are manipulatable with the appearance property?

c) At what point is the appearance customization being called? I was hoping to make changes threw the appearance property at runtime, but unfortunately the changes aren't taking place.

a) How do I know which instances of a class work with the appearance property? For e.g. since UITableView conforms to the UIAppearance protocol I was thinking I could do something like

You look in the header of the class (and the headers of all the superclasses). Any method that has UI_APPEARANCE_SELECTOR next to it is supported for use with the UIAppearance proxy.

[[UITableView appearance] setBackgroundColor:mytableViewColor];

The backgroundColor property is not decorated with UI_APPEARANCE_SELECTOR in UIView.h. Thus it is not technically supported for use with the appearance proxy. It will probably work, but (given the lack of method decoration) isn't guaranteed to.

From the UIAppearance Protocol Reference:

To support appearance customization, a class must conform to the UIAppearanceContainer protocol and relevant accessor methods must be marked with UI_APPEARANCE_SELECTOR.

(note "and relevant accessor methods must be marked..." [emphasis added])


b) Is there a list of all properties that are manipulatable with the appearance property?

Is there a single page showing every setter that works with the appearance proxy? I don't know of one, nor is there a way to build the list at runtime.


c) At what point is the appearance customization being called? I was hoping to make changes threw the appearance property at runtime, but unfortunately the changes aren't taking place.

You can use the appearance proxy at any point during execution. The changes won't be applied to the affected views until the next time those views have their -layoutSubviews method invoked.

How to create documentation for instance variable and methods in Xcode?

7 votes

I'd like to be able to Alt-Click an instance variable (or a method) as part of the program i created and read what it's purpose is.

The fact that Xcode is telling me the class variable is declared at - is nice but not enough. In this case i'd like to see custom text i typed to describe what an asset really is. Additionally type of the ivar would also be useful to know.

How can this be done? In this case, i wonder what exactly did i mean by assets

I specifically wonder if this information can be viewed from inside Xcode, similar to how Eclipse shows JavaDoc content.

enter image description here

You would need to create a documentation set for your project and install it in Xcode. appledoc can help you with this. This is a command-line tool that can generate documentation in Apple's style from specially formatted comments in your headers. You can also integrate this into your build process with a run script build phase, so that documentation is always up-to-date.

For small projects, it's usually not worth the effort though and you're probably better off just adding comments to your header files and jumping there with Cmd-click (Ctrl+Cmd+left-arrow to go back to where you came from).

Why can some methods (-retainWeakReference, -allowsWeakReference, +load, +initialize) on class NSObject not be added to other classes at runtime?

7 votes

It is straightforward at runtime to create a copy MyNSObject of the Class NSObject:

First, create a new class pair.

Class MyNSObject = objc_allocateClassPair(nil, "MyNSObject", 0);

Second read the methods, protocols, and ivars from NSObject and add them to the new class.

uint instanceMethodCount;
Method *instanceMethodArray = class_copyMethodList([NSObject class], &instanceMethodCount);
for (int i = 0; i < instanceMethodCount; i++) {
    Method method = *(instanceMethodArray + i);
    SEL selector =  method_getName(method);
    IMP implementation = method_getImplementation(method);
    const char *types = method_getTypeEncoding(method);
    BOOL success = class_addMethod(MyNSObject, selector, implementation, types);
}
free(instanceMethodArray);

uint protocolCount;
Protocol **protocolArray = class_copyProtocolList([NSObject class], &protocolCount);
for (int i = 0; i < protocolCount; i++) {
    Protocol *protocol = *(protocolArray + i);
    BOOL success = class_addProtocol(MyNSObject, protocol);
}
free(protocolArray);

uint ivarCount;
Ivar *ivarArray = class_copyIvarList([NSObject class], &ivarCount);
for (int i = 0; i < ivarCount; i++) {
    Ivar ivar = *(ivarArray + i);
    const char *name = ivar_getName(ivar);
    const char *typeEncoding = ivar_getTypeEncoding(ivar);
    NSUInteger size, alignment;
    NSGetSizeAndAlignment(typeEncoding, &size, &alignment);
    BOOL success = class_addIvar(MyNSObject, name, size, alignment, typeEncoding);
}
free (ivarArray);

Third, read the methods from the metaclass of NSObject and add them to the new metaclass.

uint classMethodCount;
Method *classMethodArray = class_copyMethodList(object_getClass([NSObject class]), &classMethodCount);
for (int i = 0; i < classMethodCount; i++) {
Method method = *(classMethodArray + i);
SEL selector =  method_getName(method);
IMP implementation = method_getImplementation(method);
const char *types = method_getTypeEncoding(method);
BOOL success = class_addMethod(object_getClass(MyNSObject), selector, implementation, types);
}
free(classMethodArray);

And finally, register the class pair.

objc_registerClassPair(MyNSObject);

Well, it's almost that straightforward. There are a couple of problems with this. Well, a couple of couples. If we were to add the following lines at the end but within the first for block

if (!success) {
    NSLog(@"unable to add method with selector named %@ to class MyNSObject", NSStringFromSelector(selector));
}

and the following lines at the end but within the last for block

if (!success) {
    NSLog(@"unable to add method with selector name %@ to metaclass MyNSObject", NSStringFromSelector(selector));
}

Then we would see the following output:

unable to add method with selector name retainWeakReference to class MyNSObject
unable to add method with selector name allowsWeakReference to class MyNSObject
unable to add method with selector name load to metaclass MyNSObject
unable to add method with selector name initialize to metaclass MyNSObject

What is going on here? Do classes (resp. metaclasses) implement retainWeakReference and allowsWeakReferenc (resp. load and initialize) "out of the box"?

References: 1. Cocoa with Love - What is a meta-class in Objective-C?
2. Stack Overflow - Justin Spahr-Summers response to "How can one obtain the sizeof a type for which one has an encoding?"

NSObject is an even more interesting beast than expected. Typically one thinks about the map

method_getName: Method -> SEL

as being one-to-one. I.e one usually thinks that method_getName(methodA) == method_getName(methodB) just in case methodA == methodB. One is encouraged to think this: one cannot create a class during coding via @interface which has multiple methods with the same selector, nor can one add two methods with the same selector to a class using class_addMethod() during runtime.

However, it is evidently possible to do it by hand. The following code demonstrates this. This code gets all the instance methods on NSObject and prints out each one named either "retainWeakReference" or "allowsWeakReference" and then gets all the class methods on NSObject and prints out each one named either "initialize" or "load".

uint NSObjectInstanceMethodCount;
Method *NSObjectInstanceMethodArray = class_copyMethodList([NSObject class], &NSObjectInstanceMethodCount);
for (int i = 0; i < NSObjectInstanceMethodCount; i++) {
    Method method = *(NSObjectInstanceMethodArray + i);
    SEL selector = method_getName(method);
    IMP implementation = method_getImplementation(method);
    const char *types = method_getTypeEncoding(method);
    if (strcmp(selector, "retainWeakReference") == 0 || strcmp(selector, "allowsWeakReference") == 0) {
        NSLog(@"NSObject implements method(%s,%p,%s)", selector, implementation, types);
    }
}

uint NSObjectClassMethodCount;
Method *NSObjectClassMethodArray = class_copyMethodList(object_getClass([NSObject class]), &NSObjectClassMethodCount);
for (int i = 0; i < NSObjectClassMethodCount; i++) {
    Method method = *(NSObjectClassMethodArray + i);
    SEL selector = method_getName(method);
    IMP implementation = method_getImplementation(method);
    const char *types = method_getTypeEncoding(method);
    if (strcmp(selector, "initialize") == 0 || strcmp(selector, "load") == 0) {
        NSLog(@"metaNSObject implements method(%s,%p,%s)", selector, implementation, types);
    }
}

The output is not what one might, aside from the preceding build-up, have expected:

NSObject implements method(retainWeakReference,0x7fff8a120b1f,c16@0:8)
NSObject implements method(allowsWeakReference,0x7fff8a120b05,c16@0:8)
NSObject implements method(retainWeakReference,0x7fff80ad6db0,c16@0:8)
NSObject implements method(allowsWeakReference,0x7fff80ad6d90,c16@0:8)
metaNSObject implements method(load,0x7fff8a09e4f2,v16@0:8)
metaNSObject implements method(initialize,0x7fff8a00cb89,v16@0:8)
metaNSObject implements method(load,0x7fff80a57670,v16@0:8)
metaNSObject implements method(initialize,0x7fff80a133d0,v16@0:8)

So, as is now evident, NSObject has two implementations for each of the selectors -retainWeakReference, -allowsWeakReference, +load, and +initialize. These are the only four methods on NSObject for which there are multiple implementations, which is demonstrated by the fact that these were the only four reported by the code in the question as being unable to be added to MyNSObject.

A statement which gets close to counting as an answer to the question then is that you can't add multiple methods with the same selector to a class created at runtime via class_addMethod(). In particular, though, no, no methods are implemented by a class created at runtime with objc_allocateClassPair() "out of the box".

What are the different ways for calling my method on separate thread?

7 votes

I have some data calculation method (let it be "myMethod:"), and I want to move the call to another thread because I don't want to block my main UI functionality. So, started to do some research on how to call my method on another thread. As far as I see, currently, there are a lot of different ways for doing that. Here's a list:

a) using pure threads (available since iOS 2.0):

[NSThread detachNewThreadSelector:@selector(myMethod:) toTarget:self withObject:_myParamsArray];

b) using a simple shortcut (available since iOS 2.0). Available from inherited NSObject but the method belongs to NSThread class too:

[self performSelectorInBackground:@selector(myMethod:) withObject:_myParamsArray];

c) using a new approach of Grand Central Dispatch queues (available since iOS 4.0):

dispatch_async(dispatch_get_global_queue(0, 0),
  ^ {
      [self myMethod:_myParamsArray];
    });

d) somehow, using some classes such as NSOperation, NSBlockOperation or NSOperationQueue, though not sure how exactly to do it (some example would be appreciated)

Currently, I have used case "b" but curious about pros and cons and other related suggestions on that.

Usually, you would prefer the GCD approach.

It's simpler when it comes to synchronization/locking than pure threads (NSThread - pthread), and it may be more accurate in a performance perspective.

When using pure threads, the problem is you may have performance issues, depending on the number of available cores/processors.

For instance, if you have only one core, creating many threads may slow down your application, because the CPU will spend most of its time switching from one thread to another, saving the stack, registers, etc.

On the other hand, if you have a lot of cores available, it may be nice to create a lot of different threads.

This is where GCD helps, as it manages this for you. It will create the appropriate number of threads, based on the available system resources, to guarantee an optimal utilization, and schedule your actions appropriately.

However, for that reason, tasks launched with GCD may not be real-time.

So if you REALLY needs that a detached task runs immediately, use an explicit threads. Otherwise, use GCD.

Hope this will help you : )

EDIT

A note about performSelectorInBackground: it simply creates a new thread. So there's basically no difference with the NSThread approach.

EDIT 2

NSOperation related stuff are a bit different. On Mac OS X, they are implemented using GCD since version 10.6. Previous versions uses threads.

On iOS, they are implemented using threads only.

Reference

All of this is very well explained in the Concurrency Programming Guide. It discusses the GCD and thread approaches, with a lot of details about the uses and implementations.

If you haven't read it already, you should take a look.

Objective C + Reskit - How do I wrap my dictionary with a key to avoid formatting problems?

5 votes

I'm trying to wrap my HTTP POST request with a key. In other words, I want to turn this:

{
"category_id"=>"1", 
"food_name_token"=>"Pizza", 
 "id"=>"1"
}

into this:

{
"dish" => 
    {
    "category_id"=>"1", 
    "food_name_token"=>"Pizza", 
    "id"=>"1"
    }
}

I tried using the 'rootKeyPath' method in RestKit:

serializationMapping.rootKeyPath = @"dish";    

But that gave me this weirdly formatted string :

{
"dish"=>
    "{
    \n \"category_id\" = 1; 
    \n \"food_name_token\" = Pizza;
    \n id = 1;
    \n}
"}

It uses equal signs and semicolons instead of arrows and commas, and adds in all these linebreaks and escape backslashes.

Any idea why? And any suggestions on what I can do instead?

P.S. I'm using a Rails backend

I found out with Restkit I can wrap attributes using brackets:

    [dishMapping mayKeyPath:@"dish[food_name_token]" toAttribute:@"placeToken"];

And this gives me a normal output without the weird formatting.

Sorting an nsarray of strings not string based

5 votes

So i have an array that i retrieve from a web service in no particular order

example:

0 => x large, 
1 => large, 
2 => XX large, 
3 => small,
4 => medium, 
5 => x small

I need to sort them: firstly based on specific - which could be reverse alphabetic:

small
medium
large

Secondly i need to sort them based on their 'x' counter parts:

x small
small
medium
large
x large
xx large

I know i can do this with brute force string matching but i would really like a suggestion on how to do this tidily, perhaps a regex or something more elegant?

Use NSComparator block syntax. Something like

NSArray * sizes = [NSArray arrayWithObjects:  @"x small",@"small",@"medium",@"large",@"x large", nil];

NSArray *sortedBySizes =[array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    if ([sizes indexOfObject:[obj1 size]]> [sizes indexOfObject:[obj2 size]])
        return (NSComparisonResult)NSOrderedAscending;
    if ([sizes indexOfObject:[obj1 size]]< [sizes indexOfObject:[obj2 size]])
        return (NSComparisonResult)NSOrderedDescending;
    return (NSComparisonResult)NSOrderedSame;
}];

In the second approach I added a mapping between the numbers send by the web server and the x-sizes. Now [obj size]; is suppose to return a NSNumber object.

NSArray * sizesStrings = [NSArray arrayWithObjects:  @"x small",@"small",
                                                     @"medium",@"large",
                                                     @"x large",@"xx large", 
                                                     nil];
NSArray * sizesNumbers = [NSArray arrayWithObjects:[NSNumber numberWithInt:5],
                                                   [NSNumber numberWithInt:3],
                                                   [NSNumber numberWithInt:4],
                                                   [NSNumber numberWithInt:1],
                                                   [NSNumber numberWithInt:0],
                                                   [NSNumber numberWithInt:2], 
                                                   nil];

NSDictionary *sizes = [NSDictionary dictionaryWithObjects:sizesStrings 
                                                   forKeys:sizesNumbers];

NSArray *sortedBySizes = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    NSString *sizeObj1String = [sizes objectForKey:[obj1 size]];
    NSString *sizeObj2String = [sizes objectForKey:[obj1 size]];

    int i1 = [sizesStrings indexOfObject:sizeObj1String];
    int i2 = [sizesStrings indexOfObject:sizeObj2String];

    if (i1 > i2)
        return (NSComparisonResult)NSOrderedAscending;
    if (i2 > i1)
        return (NSComparisonResult)NSOrderedDescending;
    return (NSComparisonResult)NSOrderedSame;
}];

The second task of the question — the grouping into small, medium, large — could be done like this:

NSDictionary *groups = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[NSMutableArray array],[NSMutableArray array],[NSMutableArray array], nil] 
                                    forKeys:[NSArray arrayWithObjects:@"small",@"medium",@"large",nil]
                        ];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    int i = [[obj size] intValue];
    if (i == 5 || i == 3) 
        [[groups objectForKey:@"small"] addObject:obj];
    else if (i == 2 || i == 0 || i == 1)
        [[groups objectForKey:@"large"] addObject:obj];
    else
        [[groups objectForKey:@"medium"] addObject:obj];

}];

Note: Codes untested, as directly typed.