Best objective-c questions in March 2011

XCode 4 hangs at "Attaching to (app name)"

18 votes

Hey guys, this is driving me crazy! I just upgraded to XCode 4 and for some reason my app won't run in the simulator or iOS device. It was working perfectly in XCode 3, but all of a sudden now when I press run the program stops at "Attaching to...". There doesn't seem to be any other info to help with this problem either. Any ideas?

Fixed it!! Hopefully this helps some people avoid a very frustrating couple hours. I solved this by:

  1. Clicking on the project name in the left pane (at the very top). This will bring up a new menu to the right, something like the project/ target editors in XCode 3.
  2. Click on Build Settings up at the top.
  3. Under Packaging make sure your product name is the same for every build, and equal to whatever it says it's attaching to. Eg if XCode is Hanging at "Attaching to myLCBO" but your product name is "LCBO Finder" then it won't build. That was exactly my problem because I renamed my app half way through development.

Hope this helps!

iOS: Using device modifiers for loading xib files?

16 votes

You can use a device modifier (i.e., ~ipad) to provide a device-specific key in Info.plist, and to specify a device-specific launch image (Default.png for iPhone, and Default~ipad.png for iPad, for example). Those two things are specifically mentioned in Apple Docs, but they don't say that this will work for any other kinds of files.

I've discovered (quite by accident) that this works for loading .xib files via initWithNibName:bundle:. So for example, I can have MyView.xib and MyView~ipad.xib, and this code:

MyViewController *viewController = [[MyViewController alloc] 
                                     initWithNibName:@"MyView" bundle:nil];

... will totally load MyView~ipad.xib on an iPad, and MyView.xib on other devices.

So, 1) Is this documented somewhere? I sure couldn't find it any any Apple docs. It's sure handier than checking UI_USER_INTERFACE_IDIOM() and hardcoding two different nib names everywhere, but I kinda don't trust it if it isn't documented.

And, 2) Does anyone know what version of iOS this started working in? I've only tried it in 4.2, and it works there. Device modifiers in general (even for the documented things listed above) are 4.0 minimum.

I hate to be that guy and answer my own question, but I think the answer is:

1) Nope, not explicitly documented in any Apple documentation, and
2) 4.0 and higher (this based on my own testing)

All you really save is a couple lines of code checking for UI_USER_INTERACE_IDIOM(). Still, I'll take it. Less code is less code.

Should a block literal retain referenced heap-allocated blocks

10 votes

Consider the following code:

// t included so block1 is a stack block. See [1] below
int t = 1;
SimpleBlock block1 = ^{ NSLog(@"block1, %d", t); };

// copy block1 to the heap
SimpleBlock block1_copied = [block1 copy];

// block2 is allocated on the stack, and refers to
// block1 on the stack and block1_copied on the heap
SimpleBlock block2 = ^{
    NSLog(@"block2");
    block1_copied();
    block1();
};
[block1_copied release];

// When the next line of code is executed, block2_copied is
// allocated at the same memory address on on the heap as
// block1_copied, indicating that block1_copied has been
// deallocated. Why didn't block2 retain block1_copied?

SimpleBlock block2_copied = [block2 copy];
block2_copied();
[block2_copied release];

Where, for completeness, SimpleBlock is defined by:

typedef void (^SimpleBlock)(void);

As indicated by the comment in the code, my tests (using both GCC 4.2 and LLVM 2.0) show that block1_copied is deallocated by the time [block2 copy] is called, yet according to the documentation that I have read [1,3], blocks are objective-c objects and blocks retain objective-c objects to which they refer [2] (in the non-instance variable case).

Additionally, note that when block2 is copied, its reference to block1 is also changed to a reference to a new copy of block1 (which is different than block1_copied), as expected, since blocks copy any blocks to which they refer [2].

So, what's going on here?

A) If blocks retain objective-c objects to which they refer and blocks are objective-c objects, why is block1_copied deallocated before block2 goes out of scope?

B) If blocks copy blocks to which they refer, and if sending -(id)copy to a heap-allocated block actually just increments its retain count, why is block1_copied deallocated before block2 goes out of scope?

C) If this is the expected behavior, where is the documentation that explains it?

[1] http://cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html
[2] http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html
[3] http://clang.llvm.org/docs/BlockLanguageSpec.txt

Footnote: In my tests, the result of running this code is an infinitely recursive call to block2_copied(), since block1_copied() had the same memory address as block2_copied.

This is the specification. It is slightly stale right now and doesn't have the formalism of a normal spec. However, Blocks have been proposed in the C working group and a more formal specification has been discussed in that context.

Specifically, the spec says:

The Block_copy operator retains all objects held in variables of automatic storage referenced within the Block expression (or form strong references if running under garbage collection). Object variables of __block storage type are assumed to hold normal pointers with no provision for retain and release messages.

Thus, the behavior you are seeing is correct, though it is definitely a pitfall!

A block won't retain anything until the block is copied. Like blocks starting on the stack, this is largely a performance based decision.

If you were to change your code to:

SimpleBlock block2_copied = [block2 copy];
[block1_copied release];

It behaves as expected.

The static analyzer should catch that, but does not (Please file a bug).

9 votes

hi people , i need help in UITableViewCell of UITableView.My requirement is below:

enter image description here

look at Retweets , list and More when i click retweet following appears enter image description here

you can see that retweet expands and shows other listing and list and more slide below. i want to make the same . Any type of help is highly appreciated ,tutorial link or anything . thank you

You may also find this sample code from Apple, helpful.

Why rename synthesized properties in iOS with leading underscores?

9 votes

When creating a new project in Xcode 4, the boilerplate code adds an underscore character when it synthesizes the ivars in the implementation file as:

@synthesize window = _window;

or:

@synthesize managedObjectContext = __managedObjectContext;

Can someone tell me what is being accomplished here? I'm not a complete nube, but this is one aspect of objective-C I don't understand.

Another point of confusion; in the app delegate implementation, after synthesizing the window iVar as above, in the application didFinishLaunchingWithOptions: method the window and viewController ivars are referred to using self:

self.window.rootViewController = self.viewController
[self.window makeKeyAndVisible];

but in the dealloc method it's _window, or _viewController

Thanks

This is an artifact of a previous version of the Objective-C Runtime. Originally, instance variables had to be instantiated explicitly:

@interface Foo : Bar {
  Baz *_qux;
}

@property (retain) Baz *qux;
@end

@implementation Foo
@synthesize qux = _qux;

- (void)dealloc {
  [_qux release];
  [super dealloc];
}

@end

People would prefix their instance variables to differentiate them from their properties (even though Apple doesn't want you to use underscores, but that's a different matter). You synthesize the property to point at the instance variable. But the point is, _qux is an instance variable and self.qux ([self qux]) is a message qux send to object self.

We use the instance variable directly in -dealloc; using the accessor method instead would look like this (though I don't recommend it, for reasons I'll explain shortly):

- (void)dealloc {
  self.qux = nil; // [self setQux:nil];
  [super dealloc];
}

This has the effect of releasing qux, as well as zeroing out the reference. But this can have unfortunate side-effects: first of all, you may end up firing some unexpected notifications (other objects may be observing changes to qux, which are recorded when an accessor method is used to change it); second of all (not everyone agrees on this point), zeroing out the pointer as the accessor does may hide logic errors in your program. If you are ever accessing an instance variable of an object after the object has been deallocated, you are doing something seriously wrong. Because of Objective-C's nil-messaging semantics, however, you'll never know, having used the accessor to set to nil (whereas, if you had released the instance variable directly and not zeroed-out the reference, it would have caused a nice EXC_BAD_ACCESS).

Later, we got the ability to synthesize instance variables too (not just the accessor methods). Then, the code looked like:

@interface Foo : Bar
@property (retain) Baz *qux;
@end

@implementation Foo
@synthesize qux = _qux;

- (void)dealloc {
  [_qux release];
  [super dealloc];
}

@end

This actually synthesizes an instance variable on Foo called _qux, which is accessed by -qux and -setQux:.

I recommend against this: it's a little messy. (@bbum reminds me that there's one good reason to use the underscore, namely to protect against accidentally direct ivar access). If you think you can trust yourself to remember whether you're using a raw instance variable, or an accessor method, just do it like this instead:

@interface Foo : Bar
@property (retain) Baz *qux;
@end

@implementation Foo
@synthesize qux;

- (void)dealloc {
  [qux release];
  [super dealloc];
}

@end

Then, when you want to access the instance variable directly, just say qux (which translates to self->qux). When you want to use accessors methods (which will notify observers, and do other interesting things, and make things safer and easier with respect to memory management), use self.qux ([self qux]) and self.qux = blah; ([self setQux:blah]).

The sad thing here is that Apple's sample code and template code sucks. Never use it as a guide to proper Objective-C style, and certainly never use it as a guide to proper software architecture. :)

Why bother with virtual functions in c++?

7 votes

Hi,

This is not a question about how they work and declared, this I think is pretty much clear to me. The question is about why to implement this? I suppose the practical reason is to simplify bunch of other code to relate and declare their variables of base type, to handle objects and their specific methods from many other subclasses?

Could this be done by templating and typechecking, like I do it in Objective C? If so, what is more efficient? I find it confusing to declare object as one class and instantiate it as another, even if it is its child.

SOrry for stupid questions, but I havent done any real projects in C++ yet and since I am active Objective C developer (it is much smaller language thus relying heavily on SDK's functionalities, like OSX, iOS) I need to have clear view on any parallel ways of both cousins.

Yes, this can be done with templates, but then the caller must know what the actual type of the object is (the concrete class) and this increases coupling.

With virtual functions the caller doesn't need to know the actual class - it operates through a pointer to a base class, so you can compile the client once and the implementor can change the actual implementation as much as it wants and the client doesn't have to know about that as long as the interface is unchanged.

7 votes

One part of my app shows a landscape, but it's kinda boring as of now. Therefore, I'm planning to animate some particles over the screen (think of something like tiny wings - http://www.youtube.com/watch?v=DpmcX-rWGfs). However, i have not yet found any built-in particle system; How can i do this memory-efficiently? I've already implemented my own animation system for some clouds animating over the landscape using CADisplayLink, and it's kind of sluggish (though i hope to make it faster soon). Another very heavy system, like animating 20 small points at a time i suppose, will probably break it.

Hey there,

I have not yet found any built-in particle system;

There are several "Free" projects that embed particle systems out there, you can visit this video tutorial for a Particle System that will be more than efficient enough for the needs that you mention. That way of making a particle system is basically the same way that Cocos2d is using, so watch the tutorial, and then download the project files, you can easily embed their Particle Emitter in your project.

How can i do this memory-efficiently?

I would recommend you using the "Object Pool Pattern", basically you preallocate a "Pool" of particles, let's say 1000 objects. Then your emitters, ask the pool for particles when they need them. If the pool get's empty you can manage the case accordingly. This may not look efficient from a memory perspective, but it's very efficient performance wise ( to avoid real time allocation of many small objects like particles ).

Some suggestions, when you declare your particle structure try to be lightweight and aligned to powers of 2 ( this will make your structure more cache friendly ), this one is 32 bytes:

struct Particle 
{
    CGPoint position;
    CGPoint speed;  
    float life;
    float decay;
    unsigned short index;
    unsigned char color_R;
    unsigned char color_G;
    unsigned char color_B;
    unsigned char color_A;
    unsigned char rotation;
};

But depending of your needs, this could be much smaller, maybe you don't really need color/index/etc. You will have to evaluate that yourself.

Finally I would recommend you to take a look at cocos2d CCParticleSystem class, you can download the code here. Their implementation is not that lightweight, but it's quite flexible and can achieve very nice effects.

Good luck with your particles :)

Objective-C, protocols and subclasses

6 votes

Let's say that I have the following protocols defined:

// basic protocol for an User Interface object:

@protocol UIObjectProtocol <NSObject>
@property (assign) BOOL touchable;
@end

// basic protocol for an User Interface object that is held by a holder object:

@protocol UIHeldObjectProtocol <UIObjectProtocol>
@property (readonly) id holder;
@end

And the following class hierarchy:

// base class for an User Interface object, which synthesizes the touchable property

@interface UIObject : NSObject <UIObjectProtocol> {
   BOOL _touchable;
}
@end

@implementation UIObject
@synthesize touchable=_touchable;
@end

At this point, everything is OK. Then I create a UIObject subclass named UIPlayingCard. Inherently, UIPlayingCard conforms to the UIObjectProtocol since it's superclass does it too.

Now suppose I want UIPlayingCard to conform to UIHeldObjectProtocol, so I do the following:

@interface UIPlayingCard : UIObject <UIHeldObjectProtocol> {
}
@end

@implementation UIPlayingCard
-(id)holder { return Nil; }
@end

Note that the UIPlayingCard conforms to UIHeldObjectProtocol, which transitively conforms to UIObjectProtocol. However I'm getting compiler warnings in the UIPlayingCard such that:

warning: property 'touchable' requires method '-touchable' to be defined - use @synthesize, @dynamic or provide a method implementation

which means that the UIPlayingCard superclass conformance to the UIObjectProtocol wasn't inherited (maybe because the @synthesize directive was declared in the UIObject implementation scope).

Am I obligated to re-declare the @synthesize directive in the UIPlayingCard implementation ?

@implementation UIPlayingCard
@synthesize touchable=_touchable; // _touchable now must be a protected attribute
-(id)holder { return Nil; }
@end

Or there's another way to get rid of the compiler warning? Would it be the result of bad design?

Thanks in advance,

I'll just throw in one other way to silence the warning: use @dynamic, and the compiler will assume that the implementation will be provided in some other way than in a declaration in the class's implementation (in this case, it's provided by the superclass).

iPhone - Why didn't the Static Analyzer pick this up?

6 votes
@property(nonatomic, retain) NSMutableArray* playerList;

...

team.playerList = [[NSMutableArray alloc] initWithArray:self.playerList];

This is a memory leak right?

So why couldn't the static analysier pick this up?

Yes, that's a memory leak; you need to either autorelease that array or manually release it after setting the property. I'm not sure why the static analyzer missed it—you might consider filing a bug against the developer tools.

Objective C: How does 7 - 1 = 3?

6 votes
NSLog(@"Before: %d",currentArticle);
currentArticle--;
NSLog(@"SUBTRACT %d",currentArticle);

"currentArticle" is an integer. This is only being echoed once in my console. If I do not run this subtraction, the number "currentArticle" remains at 7.

This is being run in the main thread, and only run once per user interaction.

I have also tried

currentArticle = currentArticle - 1;

With the same result. Am I taking crazy pills?

Thanks!

Edit:

Declared as follows:

extern int *currentArticle;

And assigned later as:

currentArticle = 0;

I tried rewriting as this:

int *curArticle; // in my .h file

curArticle = 1;

And then I run the

curArticle--;

and it still decrements by two...

I have stepped through the code and ensured there are no other calls hitting this variable.. Thanks for the feedback so far, I will keep hacking away at it.

I concur with the comments above. I'd bet a dollar that your code looks like:

int *currentArticle = 7; // or something

currentArticle may not even be a pointer to an int, specifically, but it's very likely a pointer to some 4-byte type. The '--' and '++' operators, when applied to pointers, decrement or increment by the size of the type that's pointed to.

iPhone Facebook Video Upload

6 votes

I've been working on this for a couple of days now and just can't seem to find a straight answer or example anywhere. I am trying to upload a video to facebook from within my iPhone App. I can connect to facebook (and have uploaded pictures) without a problem using:

_facebook = [[Facebook alloc] initWithAppId:kAppID];
_permissions =  [[NSArray arrayWithObjects:@"publish_stream", @"offline_access",nil] retain];
[_facebook authorize:_permissions delegate:self];

However I can't seem to get my video uploading working. My current code is:

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"TestMovie" ofType:@"mp4"];
NSData *data = [NSData dataWithContentsOfFile:filePath];

NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                               data, @"video",
                               nil, @"callback",
                               @"test", @"title",
                               @"upload testing", @"description",
                               @"EVERYONE", @"privacy",
                               nil];

[_facebook requestWithMethodName:@"video.upload"
                       andParams:params
                   andHttpMethod:@"POST"
                     andDelegate:self];

And since video upload calls have to be made to a different server I changed the restserver url within the facebook.m file to:

static NSString* kRestserverBaseURL = @"https://api-video.facebook.com/method/";

When I run this the upload crashes with an error:

facebookErrDomain err 353.

Any help would be appreciated.

EDIT:

With Zoul's help I now have the following code implemented (I have done nothing to alter his upload class nor the version of the SDK it came with). The request no longer gets an error however nothing is being uploaded.

I initialize the facebook object and the upload object:

_facebook = [[Facebook alloc] initWithAppId:kAppID];
_permissions =  [NSArray arrayWithObjects:@"publish_stream", @"offline_access",nil];
[_facebook authorize:_permissions delegate:self];
_upload = [[FBVideoUpload alloc] init];  

And then I use it once facebook has logged in:

- (void)fbDidLogin{
    _upload.accessToken = _facebook.accessToken;
    _upload.apiKey = kApiKey;
    _upload.appSecret = kApiSecret;

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Test" ofType:@"mp4"];
    NSURL *fileURL = [NSURL fileURLWithPath:filePath];
    NSData *data = [NSData dataWithContentsOfFile:filePath];

    NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                               data, @"",
                               @"test", @"title",
                               @"upload testing", @"description",
                               @"EVERYONE", @"privacy",
                               nil];

    [_upload startUploadWithURL:fileURL params:params delegate:self];
}

I’ve got a video upload branch in my fork of the Facebook SDK on GitHub. I did not touch it for several weeks, but it used to work fine (only it requires the old-style authentication, see this branch). There are some comments in the FBVideoUpload class header, but the interface is pretty much self-explanatory. There’s also some helpful discussion under my pull request – especially the thing about SSL certificates on the api-video cluster that could make the whole issue easier, but I did not review the code yet.

[Rant: It’s a pity that the Facebook SDK for iOS does not exactly thrive on GitHub. There are many pull requests, but the official developers never seem to merge anything, not even trivial typo fixes in the documentation. Most of the time the pull requests simply sit there until rejected.]

And yes, did I mention that the video upload code is a messy hack? The video upload code is a messy hack. It parses some auth tokens and it could break anytime soon, but it was the only way I could make it work back then.

UITextView ruled line background but wrong line height

6 votes

Hi

I have a UITextView where the user can create notes and save into a plist file. I want to be able to show lines just like a normal notebook. The problem I have is that the text won't align properly.

The image below explains the problem quite well.

My print screen explains the problem quite well

This is the background I use to create the lines like the Notes.app enter image description here

This is my code for creating the background for my UITextView:

textView.font                       =   [UIFont fontWithName:@"MarkerFelt-Thin" size:19.0]; 
textView.backgroundColor            =   [UIColor colorWithPatternImage: [UIImage imageNamed: @"Notes.png"]];

I know that the UIFont.lineHeight property is only available in > iOS 4.x.

So I wonder if there is another solution to my problem?

You should try and draw your lines programmatically rather than using an image. Here's some sample code of how you could accomplish that. You can subclass UITextView and override it's drawRect: method.

NoteView.h

#import <UIKit/UIKit.h>
@interface NoteView : UITextView <UITextViewDelegate> {
}
@end

NoteView.m

#import "NoteView.h"

@implementation NoteView

- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor colorWithRed:1.0f green:1.0f blue:0.6f alpha:1.0f];
        self.font = [UIFont fontWithName:@"MarkerFelt-Thin" size:19];
    }
    return self;
}

- (void)drawRect:(CGRect)rect {

    //Get the current drawing context   
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    //Set the line color and width
    CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.2f].CGColor);
    CGContextSetLineWidth(context, 1.0f);
    //Start a new Path
    CGContextBeginPath(context);

    //Find the number of lines in our textView + add a bit more height to draw lines in the empty part of the view
    NSUInteger numberOfLines = (self.contentSize.height + self.bounds.size.height) / self.font.leading;

    //Set the line offset from the baseline. (I'm sure there's a concrete way to calculate this.)
    CGFloat baselineOffset = 6.0f;

    //iterate over numberOfLines and draw each line
    for (int x = 0; x < numberOfLines; x++) {
        //0.5f offset lines up line with pixel boundary
        CGContextMoveToPoint(context, self.bounds.origin.x, self.font.leading*x + 0.5f + baselineOffset);
        CGContextAddLineToPoint(context, self.bounds.size.width, self.font.leading*x + 0.5f + baselineOffset);
    }

    //Close our Path and Stroke (draw) it
    CGContextClosePath(context);
    CGContextStrokePath(context);
}

@end

MyViewController.h

#import <UIKit/UIKit.h>
#import "NoteView.h"
@interface MyViewController : UIViewController <UITextViewDelegate> {

    NoteView *note;
}

@property (nonatomic, retain) NoteView *note;

@end

MyViewController.m

#import "MyViewController.h"
#import "NoteView.h"

#define KEYBOARD_HEIGHT 216

@implementation MyViewController
@synthesize note;

- (void)loadView {
    [super loadView];
    self.note = [[[NoteView alloc] initWithFrame:self.view.bounds] autorelease];
    [self.view addSubview:note];
    note.delegate = self;
    note.text = @"This is the first line.\nThis is the second line.\nThis is the ... line.\nThis is the ... line.\nThis is the ... line.\nThis is the ... line.\nThis is the ... line.\n";
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    [note setNeedsDisplay];
}

- (void)textViewDidBeginEditing:(UITextView *)textView {
    CGRect frame = self.view.bounds;
    frame.size.height -= KEYBOARD_HEIGHT;
    note.frame = frame;
}

- (void)textViewDidEndEditing:(UITextView *)textView {
    note.frame = self.view.bounds;
}

- (void)dealloc {
    [note release];
    [super dealloc];
}

Take a look at Apple's documentation for Managing the Keyboard, specifically "Moving Content That Is Located Under the Keyboard". It explains how to listen for NSNotifcations and adjust your views properly.

How can I get rid of resident dirty memory in Objective-C?

6 votes

I watched Apple's WWDC 2010 video on Advanced Memory Analysis with Instruments and from that, I was able to find a lot of resident dirty memory. I realize that having so much resident dirty memory is a bad thing (and probably the explanation for my app crashing so much...), but I'm not sure how to fix it. Where should I look?

Instruments shows me a lot of potentially useful information that looks like gibberish to me, such as:

% of Res  Type                      Resident Size
18%       VM_ALLOCATE (8192 pages)  32.00 MB

This is in the "Dirty" category - 32 MB of resident dirty memory is a lot on a device that only has 256 MB, right? :) There are several more large chunks like this. How do I trace this back to my code from Instruments? Or should I just forget Instruments and look for specific issues in my code?

Do you see this 32 MB chunk of VM_ALLOCATE when running on the device or in the simulator?

I ask because when I played around with the allocations instrument on the OS X app I'm working on, I also noticed a 32 MB chunk of VM_ALLOCATE and I'm wondering if this is a by-product of running in the OS X environment. Running on the device may give you a different data set.

In general, though, resident memory is the memory that your app is using that is not swapped out to disk. On iOS, there is no swap, so resident memory should equal your virtual memory footprint.

Dirty memory is memory you've allocated and used. Dirty memory should be less than resident memory because the latter includes code (yours and frameworks).

I'm not sure exactly what you're doing in your app, but I'll guess that you've loaded some large assets from your bundle and are keeping them around. Don't do this, when possible.

There are also APIs you can use when loading NSData objects that use a memory-mapping technique instead of brute-force reading the bytes. These can be better because it allows the OS to read the pages from disk lazily. With NSData (since it's non-mutable), it might also be smart enough to mark the pages as read-only. Theoretically, this is a valuable hint to the OS that it can purge those pages when under pressure, since it knows they can't change. Read the docs for +[NSData dataWithContentsOfMappedFile:].

For images, I recall reading something that suggested avoiding imageNamed: except for images that you regularly used through your app (i.e. UI elements). For large images especially, they can remain in a cache that you don't have control over. (imageNamed: had a leak in the 2.x days, but it was fixed in 3.x and is perfectly safe to use today.) Use imageWithContentsOfFile: for larger images and images that aren't a recurring part of your UI.

If you're loading images from the network, cache them on disk and free the raw bytes after you create the UIImage. If the image views are unloaded due to memory pressure, you don't want to hit the network to load the data again, but you also don't want to keep two copies (an NSData and the UIImage) loaded.

Use BWToolkit through code instead of IB

5 votes

Hi there,

I'm trying to use BWToolkit to make a HUD-style button. Since Xcode 4 doesn't support IB plugins, I'm forced to make this button through code. After importing the framework and importing the header, I tried this:

BWTransparentCheckbox *button = [[BWTransparentCheckbox alloc] initWithFrame:NSMakeRect(0, 0, 100, 20)];
[self addSubview:button]; 

I'd expect this nice-looking button:

button

However, this is what I get (minus the black border):

button

Any idea what I'm doing wrong here?

You'll have to create the correct cell for your button. Something like this will get you closer:

BWTransparentButton *button = [[BWTransparentButton alloc] initWithFrame:NSMakeRect(0, 0, 136, 28)];
BWTransparentButtonCell *buttonCell = [[BWTransparentButtonCell alloc] init];
[button setCell:buttonCell];
[buttonCell setBezelStyle:NSRoundedBezelStyle];
[buttonCell release];
[self addSubview:button];
[button release];