programing

IBOutlet은 속성이고 합성되어야합니까?

goodcopy 2021. 1. 18. 22:04
반응형

IBOutlet은 속성이고 합성되어야합니까?


대부분의 예에서 다음과 같은 IBOutlets 설정을 볼 수 있습니다.



(Example A)

FooController.h:

@interface FooController : UIViewController {
    UILabel *fooLabel;
}

@property (nonatomic, retain) IBOutlet UILabel *fooLabel;

@end

FooController.m:

@implementation FooController

@synthesize fooLabel;

@end

그러나 이것은 또한 잘 작동합니다 (알림 : 속성 및 합성 없음) :



(Example B)

FooController.h:

@interface FooController : UIViewController {
    IBOutlet UILabel *fooLabel;
}

@end

FooController.m:

@implementation FooController

@end

예제 B에서와 같이 IBOutlets를 정의 할 때 단점이 있습니까? 메모리 누수처럼? 잘 작동하는 것 같고 IBOutlet을 공용 속성으로 사용하지 않는 것을 선호합니다. 컨트롤러 구현에서만 사용됩니다. 실제 필요없이 세 곳에서 정의하는 것은 나를 매우 건조하게 생각하지 않습니다 (자신을 반복하지 마십시오).


Mac OS X에서 IBOutlet은 다음과 같이 연결됩니다.

  1. set <OutletName> :이라는 메서드를 찾습니다. 존재한다면 그것을 부르십시오.
  2. 메서드가없는 경우 <OutletName>이라는 인스턴스 변수를 찾고을 유지하지 않고 설정합니다 .

iPhone OS에서 IBOutlets는 다음과 같이 연결됩니다.

  1. [객체 setValue : outletValue forKey : @ "<OutletName>"] 호출

키에 대한 값 설정의 동작은 다음과 같이하는 것입니다.

  1. set <OutletName> :이라는 메서드를 찾습니다. 존재한다면 그것을 부르십시오.
  2. 메서드가 없으면 <OutletName>이라는 인스턴스 변수를 찾아 설정하고 유지 합니다.

속성을 사용하는 경우 두 플랫폼 모두에서 " set <OutletName> : ...이라는 메서드를 찾습니다. "사례에 해당합니다. 인스턴스 변수 만 사용하면 Mac OS X VS iPhone OS에서 다른 유지 / 해제 동작이 발생합니다. 인스턴스 변수를 사용하는 데 아무런 문제가 없습니다. 플랫폼간에 전환 할 때 이러한 동작 차이를 처리하면됩니다.

Here's a link to full documentation on just this topic. https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW6


On Mac OS X, IBOutlets are not retained by defaults. This is the opposite of the behavior on iPhone OS: on iPhone OS, if you don't declare a property it is retained and you must release this property in the dealloc method. Additionally, the 64-bit runtime can synthesize instance variables using property declarations. That means that someday the instance variables (with the IBOutlet) may be omitted.

For these reasons it is more homogeneous and compatible to create always a property and use the IBOutlet only in the property. Unfortunately, it is also more verbose.

In your first example you always have to release the outlet in the dealloc method. In your second example you must release the outlet only with iPhone OS.


The end result is exactly the same, but you have to keep a few things in mind:

  • When using instance fields as outlets, you should NOT release them in dealloc.

  • When using properties that have the (retain) attribute, you have to release the property in dealloc (using self.property=nil or by releasing the backing variable). This makes it a lot more transparent as to what's going on.

Actually it all comes down to the same old rule: "thou shalt release what you alloc/retain". So in case you use an instance field as outlet, you didn't alloc/retain it, so you shouldn't release it.


Its possible that those examples use the retain because the sample code is programmatically allocating and initializing a UILabel and then adding it to the UIView. That's the case for many examples, since learning how to use Interface Builder is often not their point.

The second example (no property and no synthesize) with the IBOutlet is used when the developer 'assigns' the UILabel (Button, View, etc) within the Interface Builder -- by dragging the IBOulet to the Label or other View component. In my opinion, the preceding drag and drop action (Label onto View) also add the subview, the Label to a View -- and so on. Label is retained by a View; a View is retained by Window; Window is retained by File's Owner. File's Owner is usually your Document that is booted up in main.

You will note that when you step through your program (by adding an awakeFromNib

- (void)awakeFromNib
{
    [fooLabel blahblah];
}

that fooLabel already has a memory address.

Thats because the Label was initialized from a file bundle (the nib file) using not init but initWithCoder. Which essentially deserializes the filestream to an object - and then sets the IBOutlet variable. (We're still talking about the IBOutlet method).

Also note that the aforementioned iOS method uses the Key Value method

  call [object setValue:outletValue forKey:@"<OutletName>"]

which is the Observer/Observable pattern. That pattern require the Observable object reference each Observer in a Set/Array. A change in value will iterate the Set/Array and equally update all Observers. That Set WILL already retain each Observer thus the lack of retain in iOS.

Further and the rest is speculation.

It seems that cases when you do use Interface Builder then

 @property (nonatomic, retain) IBOutlet UILabel *fooLabel;

should possibly be changed to

@property (nonatomic, weak) IBOutlet UILabel *fooLabel;

or @property (nonatomic, assign) IBOutlet UILabel *fooLabel;

And then it needn't be released in a dealloc method. Plus it will satisfy the OSX and iOS requirements.

That's based on logic and I could be missing some pieces here.

Nevertheless, it may not matter if the view is persistent through the life of your program. Whereas a label in a modal dialog box (open, close, open, close) may in fact have over-retained and leak per cycle. And that's because (speculation again) each closed dialog box is serialized into a file system and thus persists x,y position and size, along with its subviews, etc. And subsequently deserialized ... on the next session open (Opposed to say minimiz or hidden.)

ReferenceURL : https://stackoverflow.com/questions/1221516/does-an-iboutlet-needs-to-be-a-property-synthesized

반응형