2014-04-18 3 views
0

모든 형식을 반환 할 수있는 메서드/함수를 사용하려면 어떻게해야합니까? 예를 들어 유형이 float 일 때가 있고 때로는 NSString* 일 필요가 있으므로 floatid이 아니기 때문에 id이 작동하지 않습니다. 나는 C 또는 C++ 함수를 사용하는 것이 쉽지 않다면 반대하지 않는다.다양한 반환 형식 목표 -C 또는 C

동적 반환 형식이 필요한 이유는 Ivar를 얻기 위해 objc/runtime을 사용하기 때문입니다.

난 아무것도 할 수 some_type 싶습니다 :

- (some_type)getIvarWithName:(const char *)name in:(id)obj 
{ 
Ivar ivar(class_getInstanceVariable(object_getClass(obj),name)); 
return (some_type)ivar; 
} 
+0

왜 C에 대해 묻고 있습니까? C는'id' 나'NSString * '을 지원하지 않습니다. C 타입을 원한다면 아마도'void *'를 반환하고 싶을 것이다. – rmaddy

+0

어디에서 값을 얻고 있습니까? iVars를 가지고 있다면 속성을 사용하는 것을 고려한 다음 동적으로 액세스하려면 'valueForKey :'를 사용하십시오. – Rich

답변

3

돌려 주어 NSNumber에 싸여 float, 당신은 id 반환 형식을 사용할 수 있습니다. 를 단순화하기 위해

, 당신은 심지어 예를 들어, 권투 리터럴을 사용할 수 있습니다 : 당신이 어떤 형식을 반환 할 수있는 기능을 필요로하는 이유에 대해 생각하는

return @(1.1f); 
1

가장 먼저하는 일입니다. 유형을 모르기 때문에 값을 할당 할 수 없으므로 실제로 이해가되지 않습니다. 물론 언어가 id 키워드로 알려지지 않은 객체를 사용하기 때문에 Obj-C 객체를 엄격하게 처리 할 때 상황이 다릅니다. 알 수없는 개체는 Honeycrisp 사과와 매킨토시 사과를 섞어 쓰는 것과 비슷합니다. Honeycrisp 사과와 항공기를 섞는 것과 같습니다. 그러나 매개 변수 (예 : int의 경우 int 매개 변수, float의 경우 float 매개 변수)를 기반으로 특정 유형이 반환되도록하려면 함수를 오버로드 할 수 있습니다. 그렇지 않으면, 절대적으로 아무것도 반환하지 않는 것으로 알고있는 유일한 방법은 무효 포인터 (void *)입니다. 이것은 실제로 아무것도 될 수있는 데이터 덩어리를 가리 킵니다. 그러나 원래의 문제로 되돌아갑니다. 그게 무엇을 대표하며 얼마나 걸리나요? 행운을 빕니다!

UPDATE : 다른 답변 언급, 당신은 당신의 경우에 작동합니다 간단한 데이터 유형 등 NSNumbers 또는 NSValues ​​같은 개체에서 (int, float 등), 포장 할 수 있습니다. 그러나 구조체와 같은 복잡한 유형의보다 일반적인 시나리오로 확장하면 일반적으로 내장 클래스로 래핑 될 수 없습니다. Obj-C를 사용하여 클래스를 만들어야합니다.

+0

'- [NSDictionary objectForKey :]'는 정확하게 모든 타입을 반환 할 수 있습니다. 우리는 그가 무엇을하고 싶어하는지 알지 못한다. 배열에'- (id) objectForKey : (id) key atIndex : (NSUInteger) index'와 같은 사전 값을 객체화하는 래퍼 함수를 ​​가질 수있다. – Rich

+1

NSDictionary는 객체 만 저장할 수 있으므로 알 수없는 객체 유형 인'id'를 반환합니다. NSDictionary는'int'와 같은 간단한 타입을 반환하지 않습니다. – user2105505

+0

그 점은 당신의 성명서에 나와 있습니다. " – Rich

0

Obj-C에는 이러한 종류의 다형성이 없습니다. 무엇이 반환 될지 미리 아는 경우 물론 방법에 사용할 수 있습니다. NSNumber를 float 값으로 사용하면 Retruning ID가 작동합니다. 나중에 처리하기 위해 숫자 또는 문자열을 전달하는 응답 개체를 도입하고 (bool) isNumber(bool) isString 메서드를 제공 할 수도 있습니다.

하지만 실제로 무엇을하고 있습니까? 어떤 맥락에서 당신은 그것을 사용하고 있으며 실제로 무엇을 성취하려고합니까. 나에게 더 나은 솔루션을 사용할 수있는 것처럼 들린다.

0

물론 이상한 해결책이지만 이상한 질문이 있습니다.

objective-C++을 활성화해야합니다. .m- 파일의 이름을로 변경하십시오.mm 그런 다음 당신은 코드처럼 보일 것입니다 : 방법은 그 같은 것을 구현 될 수

void weird_function(int a) 
{ 
    switch (a) 
    { 
     case 0: throw @"Hello"; 
     default: throw a; 
    } 
} 

void some_code(int a) 
{ 
    try 
    { 
     weird_function(a); 
    } 
    catch (int a) 
    { 
     NSLog(@"Catch int: %d", a); 
    } 
    catch (NSString* str) 
    { 
     NSLog(@"Catch string: %@", str); 
    } 
} 

너의가 :

union ValueHolder 
{ 
    void* voidPtrValue; 
    int intValue; 
    float floatValue; 
    NSString* nssstringValue; 
}; 

- (void)getIvarWithName:(const char *)name in:(id)obj 
{ 
    ValueHolder vh; 
    Ivar ivar = object_getInstanceVariable(obj,name, &vh.voidPtrValue)); 
    if (NULL == ivar) 
     return; 
    const char* encoding = ivar_getTypeEncoding(ivar); 
    if (0 == strcmp(encoding, @encode(int))) 
     throw vh.intValue; 
    if (0 == strcmp(encoding, @encode(float))) 
     throw vh.floatValue; 
    if (0 == strcmp(encoding, "@\"NSString\"")) 
     throw vh.nsstringValue; 
} 
0

I 작동 C++에서 템플릿을 사용하여 사용자 정의 유형 을 가지고 있음을 발견 코드를 다음과 나의 상황에 가장 잘 작동합니다

:

template <typename _type> 
static inline _type & hookVar(id self, NSString*name) 
{ 
    Ivar ivar(class_getInstanceVariable(object_getClass(self),[name UTF8String])); 
    #if __has_feature(objc_arc) 
    void *pointer(ivar == NULL ? NULL : reinterpret_cast<char *>((__bridge void *)self) + ivar_getOffset(ivar)); 
    #else 
    void *pointer(ivar == NULL ? NULL : reinterpret_cast<char *>(self) + ivar_getOffset(ivar)); 
    #endif 
    return *reinterpret_cast<_type *>(pointer); 
} 

난 그냥 같은 것을 사용하는 함수를 호출하기

NSWindow *win = hookVar<NSWindow*>(self, @"_window"); 
+0

물론 변수 유형을 알아야합니다. 타입과 변수 이름을 알고 있다면'self -> _ window'를 호출 할 수없는 이유는 무엇입니까? –