Pytanie w Xcode6 Gold Master, używając objc_msgSend teraz wyrzuca błąd składni mówiąc, że liczba argumentów jest błędna


 id<MyProtocol> topLayoutGuideObj = objc_msgSend(viewController, @selector(myselector));

"Zbyt wiele argumentów wywołania funkcji, oczekiwane 0, ma 2"

Jednak funkcja signature dla objc_msgSend wygląda następująco:

#if !OBJC_OLD_DISPATCH_PROTOTYPES
OBJC_EXPORT void objc_msgSend(void /* id self, SEL op, ... */ )
    __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
OBJC_EXPORT void objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )
    __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
#else
/** 
 * Sends a message with a simple return value to an instance of a class.
 * 
 * @param self A pointer to the instance of the class that is to receive the message.
 * @param op The selector of the method that handles the message.
 * @param ... 
 *   A variable argument list containing the arguments to the method.
 * 
 * @return The return value of the method.
 * 
 * @note When it encounters a method call, the compiler generates a call to one of the
 *  functions \c objc_msgSend, \c objc_msgSend_stret, \c objc_msgSendSuper, or \c objc_msgSendSuper_stret.
 *  Messages sent to an object’s superclass (using the \c super keyword) are sent using \c objc_msgSendSuper; 
 *  other messages are sent using \c objc_msgSend. Methods that have data structures as return values
 *  are sent using \c objc_msgSendSuper_stret and \c objc_msgSend_stret.
 */
OBJC_EXPORT id objc_msgSend(id self, SEL op, ...)
    __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

Argumenty są "void" lub variadic?! Nie rozumiem, jak mam to nazwać.


16
2017-09-15 15:54


pochodzenie


Ciekawe, dlaczego po prostu nie dzwonisz [viewController mySelector];. - rmaddy
uczciwe pytanie. Nie napisałem tego kodu, próbuję go naprawić - i zmienię go tak mało, jak to tylko możliwe. Jednak może się to skończyć - nont
iOs 8 GM i Xcode 6 GM są pod NDA, wypróbuj forum programistów Apple lub wsparcie Apple. - A-Live
@ A-Live Są one objęte pozwoleniem NDA i mogą wysyłać pytania i rozmawiać o tym poza ekosystemem Apple. - Legoless


Odpowiedzi:


Zobacz tylko kilka linii powyżej.

 /* 
  * ...
  *
  * These functions must be cast to an appropriate function pointer type 
  * before being called. 
  */

Możesz nazwać to tak:

#import <objc/runtime.h>
#import <objc/message.h>

id<MyProtocol> topLayoutGuideObj = ((id (*)(id, SEL))objc_msgSend)(viewController, @selector(myselector));

LUB

id (*typed_msgSend)(id, SEL) = (void *)objc_msgSend;
id<MyProtocol> topLayoutGuideObj = typed_msgSend(viewController, @selector(myselector));

26
2017-09-15 17:41



Najwyraźniej powodem, dla którego pojawia się w Xcode 6, jest to, że ostrzeżenie "Włącz ścisłe sprawdzanie wywołań objc_msgSend" jest teraz domyślnie włączone i domyślnie włączone po otwarciu starego projektu i "Zaktualizowaniu projektu do zalecanych ustawień". - Jerry Krinock
Podobna poprawka jest wymagana dla objc_msgSendSuper (). Po drugim przykładzie rintaro, odpowiedź brzmi: id (* typed_msgSendSuper) (struct objc_super *, SEL, ...) = (void *) objc_msgSendSuper; returnValue = typed_msgSendSuper (& yourSuperStruct, yourSelector, yourFirstArg, ...); - Jerry Krinock


Sprawdziłem to, głównym problemem był @Jerry Krinock powiedział w komentarzu zaakceptowanej odpowiedzi;

  1. Przejdź do swojego projektu Ustawienia kompilacji
  2. Wyszukaj objc_msgSend
  3. Ustaw jego wartość na "Nie" zamiast "Tak"

10
2018-06-17 08:23



Nie rób tego. Ostrzeżenie istnieje z jakiegoś powodu; bez odlewania typu objc_msgSend () do specyficznie wpisanego zestawu parametrów, które chcesz przekazać, nie będzie działać na niektórych ABI. Varargs to nie to samo, co jawnie wpisana lista parametrów. - bbum
Jako przykład tego, co @bbum mówi, kiedy mijamy a char (lub BOOL, który typuje się do char) przez varargs, jest promowany do int, co nie jest, jeśli typujesz funkcję na typie, który faktycznie ma. Regularne połączenie również nie promuje znaków, więc jeśli wyłączysz ostrzeżenie, otrzymasz tylko to, że nie zdajesz sobie sprawy, kiedy przekazujesz losowe śmieci do swojej funkcji. - uliwitness


jeśli zdarza się to w lib cocoapod, wystarczy zaktualizować przynajmniej do cocoapods 36.1. Jeśli nie możesz tego zrobić, dodaj następujący kod na końcu pliku podfile:

(zamień AFNetworking na strąk, w którym widzisz te błędy)

when /AFNetworking/            
    target.build_configurations.each do |config|
        config.build_settings['ENABLE_STRICT_OBJC_MSGSEND'] = "NO"
end

1
2017-07-29 07:53