Playing with __attributes__ (二)

本文深入探讨了Objective-C中的多种特性,包括@(表达式)的用法、__attribute__((objc_boxable))的作用、objc_requires_super确保子类调用父类方法、overloadable实现方法重载、objc_runtime_name更改运行时名称以及objc_method_family指定内存管理行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

objc_boxable

OC可能你经常会看到@(100)等用法。不用奇怪,就是这个Function attributes
使用示例:

struct __attribute__((objc_boxable)) some_struct {
  int i;
};
union __attribute__((objc_boxable)) some_union {
  int i;
  float f;
};
typedef struct __attribute__((objc_boxable)) _some_struct some_struct;

some_struct ss;
NSValue *boxed = @(ss);

objc_requires_super

很多OC的class允许子类重载父类方法,但需要在重载的方法中调用父类方法。如:-[UIViewController viewDidLoad],-[UITableViewCell prepareForReuse]等。 对于这样的情况,objc_requires_super就能派上用场。在父类的方法声明时使用该属性,能够使子类重载方法时必须调用父类方法。

- (void)foo __attribute__((objc_requires_super));

Foundation framework已经定义好了一个宏NS_REQUIRES_SUPER让开发者使用这个属性:

- (void)foo NS_REQUIRES_SUPER;

overloadable

使C下的方法调用类似C++中的overload:

float __attribute__((overloadable)) tgsin(float x) { return sinf(x); }
double __attribute__((overloadable)) tgsin(double x) { return sin(x); }
long double __attribute__((overloadable)) tgsin(long double x) { return sinl(x); }

调用tgsin时会根据参数x类型决定调用对应的方法。具体参见C++99标准。不在此赘述。

objc_runtime_name

改变Class或者Protocol的运行时名称。
(水平有限,暂时不知道有何方便之处)

__attribute__((objc_runtime_name("MyLocalName")))
@interface Message
@end

objc_method_family

先来看一段代码:

@interface MyObject: NSObject
@property (nonatomic) newValue;
@end

编译出现error如下:
Property follows Cocoa naming convention for returning 'owned' objects
Explicitly declare getter '-newValue' with '__attribute__((objc_method_family(none)))' to return an 'unowned' object

在支持ARC后,clang有一些对于内存管理的命名规范。

You take ownership of an object if you create it using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy”

所以,如果方法名以alloc, new, copy, mutableCopy开头的函数都会被作为生成新对象的函数对返回对象retainCount自增1.
解决办法为,在property后加入 __attribute__((objc_method_family(none)))

其他用法:

__attribute__((objc_method_family(X)))

X可以是none, alloc, copy, init, mutableCopy, new其中之一。放在property或者函数后面。

当然你也可以使不满足编译器命名规则的方法成为生成新对象的方法,如:

- (id) createObject __attribute__((objc_method_family(new)));

下期会介绍剩下的和一些有用的宏

原作写于segmentfault 链接

float AudioPolicyManager::adjustDeviceAttenuationForAbsVolume(IVolumeCurves &curves, 10761 VolumeSource volumeSource, 10762 int index, 10763 const DeviceTypeSet &deviceTypes) 10764 { 10765 audio_devices_t volumeDevice = Volume::getDeviceForVolume(deviceTypes); 10766 device_category deviceCategory = Volume::getDeviceCategory({volumeDevice}); 10767 float volumeDb = curves.volIndexToDb(deviceCategory, index); 10768 10769 const auto it = mAbsoluteVolumeDrivingStreams.find(volumeDevice); 10770 if (it != mAbsoluteVolumeDrivingStreams.end()) { 10771 audio_attributes_t attributesToDriveAbs = it->second; 10772 auto groupToDriveAbs = mEngine->getVolumeGroupForAttributes(attributesToDriveAbs); 10773 if (groupToDriveAbs == VOLUME_GROUP_NONE) { 10774 ALOGD("%s: no group matching with %s", __FUNCTION__, 10775 toString(attributesToDriveAbs).c_str()); 10776 return volumeDb; 10777 } 10778 10779 float volumeDbMax = curves.volIndexToDb(deviceCategory, curves.getVolumeIndexMax()); 10780 // #ifdef OPLUS_FEATURE_A2DP_SMALLVOLUME 10781 // Chenji.Lei@MULTIMEDIA.AUDIOSERVER.BASE, 2025/05/12, add for A2DP small volume 10782 if (isSteplessVolumeSupport() || mAudioPolicyManagerExt->isA2dpSmallVolumeSupport()) { 10783 int targetIndex = mAudioPolicyManagerExt->getPreScaleAbsVolumeIndex(index, curves.getVolumeIndexMax(), deviceCategory); 10784 ALOGD("%s: index %d for category %d targetIndex %d", __func__, index, deviceCategory, targetIndex); 10785 volumeDbMax = curves.volIndexToDb(deviceCategory, targetIndex); 10786 } 10787 // #endif /* OPLUS_FEATURE_A2DP_SMALLVOLUME */ 10788 VolumeSource vsToDriveAbs = toVolumeSource(groupToDriveAbs); 10789 if (vsToDriveAbs == volumeSource) { 10790 // attenuation is applied by the abs volume controller 10791 // do not mute LE broadcast to allow the secondary device to continue playing 10792 return (index != 0 || volumeDevice == AUDIO_DEVICE_OUT_BLE_BROADCAST) ? volumeDbMax 10793 : volumeDb; 10794 } else { 10795 IVolumeCurves &curvesAbs = getVolumeCurves(vsToDriveAbs); 10796 int indexAbs = curvesAbs.getVolumeIndex({volumeDevice}); 10797 float volumeDbAbs = curvesAbs.volIndexToDb(deviceCategory, indexAbs); 10798 float volumeDbAbsMax = curvesAbs.volIndexToDb(deviceCategory, 10799 curvesAbs.getVolumeIndexMax()); 10800 // #ifdef OPLUS_FEATURE_A2DP_SMALLVOLUME 10801 // Chenji.Lei@MULTIMEDIA.AUDIOSERVER.BASE, 2025/05/12, add for A2DP small volume 10802 if (isSteplessVolumeSupport() || mAudioPolicyManagerExt->isA2dpSmallVolumeSupport()) { 10803 int targetIndex = mAudioPolicyManagerExt->getPreScaleAbsVolumeIndex(index, curves.getVolumeIndexMax(), deviceCategory); 10804 ALOGD("%s: index %d for category %d targetIndex %d", __func__, index, deviceCategory, targetIndex); 10805 volumeDbAbsMax = curves.volIndexToDb(deviceCategory, targetIndex); 10806 } 10807 // #endif /* OPLUS_FEATURE_A2DP_SMALLVOLUME */ 10808 float newVolumeDb = fminf(volumeDb + volumeDbAbsMax - volumeDbAbs, volumeDbMax); 10809 ALOGV("%s: abs vol stream %d with attenuation %f is adjusting stream %d from " 10810 "attenuation %f to attenuation %f %f", __func__, vsToDriveAbs, volumeDbAbs, 10811 volumeSource, volumeDb, newVolumeDb, volumeDbMax); 10812 return newVolumeDb; 10813 } 10814 } 10815 return volumeDb; 10816 }
07-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值