Czy możesz tworzyć biblioteki dynamiczne dla iOS i ładować je w czasie wykonywania?

114

Czy biblioteki dynamiczne są obsługiwane w systemie iOS (iPhone / iPad)?

W Xcode próbowałem stworzyć nowy projekt -> Framework & Library -> Cocoa Library (dynamiczny) . W ustawieniach projektu ustawiam Base SDK na iOS device 4.1i target na iOS4.1, ale ma błąd kompilacji:

target określa typ produktu „com.apple.product-type.library.dynamic”, ale nie ma takiego typu produktu dla platformy „iphonesimulator”.

Kompilacja, którą wybrałem, to Simulator -> Debug -> i386 .

user510951
źródło
4
iOS8 + obsługuje frameworki oparte na współdzielonej bibliotece.
eonil
1
@Eonil, czy możesz to rozwinąć? Chciałbym dowiedzieć się więcej na ten temat, artykuł lub link do niektórych informacji byłby bardzo wdzięczny.
Maxim Chetrusca

Odpowiedzi:

105

W czasie, gdy zadawano to pytanie, biblioteki dynamiczne nie były obsługiwane przez system iOS i spowoduje to odrzucenie aplikacji. Dozwolone są tylko biblioteki statyczne.

Jednak w iOS8 możesz używać dynamicznych bibliotek i frameworków. Powinien „po prostu działać”

DarkDust
źródło
14
Czy ktoś wie, dlaczego tak jest? Wydaje mi się to po prostu szalone.
Erik de Castro Lopo
73
@Erik de Castro Lopo: Powodem jest bezpieczeństwo: ponieważ biblioteka dynamiczna może być ładowana i usuwana w czasie wykonywania, możesz pobrać dodatkowy kod wykonywalny i załadować go (pomyśl o wtyczce). Może to zostać naruszone przez hakera, a następnie wykonanie złośliwego kodu na telefonie jest bardzo złą rzeczą. Umożliwiłoby również dodanie niezatwierdzonych funkcji do zatwierdzonej aplikacji. Krótko mówiąc: w tym środowisku Apple uważa dynamiczne linkowanie za skrzynkę Pandoras, która musi być ściśle kontrolowana, w przeciwnym razie może zagrozić bezpieczeństwu i zgadzam się, że ma to sens w przypadku telefonu .
DarkDust
6
Tworzę własną aplikację, która nie będzie dystrybuowana za pośrednictwem AppStore, więc nie obchodzą mnie ograniczenia Apple dotyczące AppStore. Czy technicznie możliwe jest utworzenie biblioteki dynamicznej dla aplikacji na iOS?
Aliaksei
3
@Aliaksei: Technicznie tak, bo inaczej nie byłbyś w stanie połączyć się z bibliotekami Apple. Obsługa bibliotek dynamicznych AFAIK jest mniej więcej taka sama jak w systemie Mac OS X. Jednak Xcode jej nie obsługuje, ale wygląda na to, że możesz używać pakietów. Zobacz ten artykuł .
DarkDust
3
Nieobsługiwane to nie to samo, co niedozwolone.
dtech
162

Nie jestem naprawdę nie zgadzając się z odpowiedzią DarkDust za , ale jeśli mogę skierować moje wewnętrzne Billa Clintona, to zależy od tego, jaki jest sens obsługiwana jest :)

Apple nie chce, abyś robił to w aplikacjach App Store, ale system operacyjny z pewnością na to pozwala. Aplikacje Jailbreak używają tej techniki przez cały czas. Zasadniczo używasz standardowej techniki UNIX do dynamicznego otwierania struktury / biblioteki, a następnie używania jej elementów. Funkcja dlopen umożliwia otwarcie biblioteki przez przekazanie ścieżki do tego frameworka lub dylib. Z niektórych dokumentów dotyczących tworzenia aplikacji jailbreak , oto przykład wywoływania init()funkcji zaimplementowanej we własnej, oddzielnej dylib:

#include <dlfcn.h>

initWrapper() {
    char *dylibPath = "/Applications/myapp.app/mydylib2.dylib";

    void *libHandle = dlopen(dylibPath, RTLD_NOW);
    if (libHandle != NULL) {
        // This assumes your dylib’s init function is called init, 
        //    if not change the name in "".
        void (*init)() = dlsym(libHandle, "init");
        if (init != NULL)  {
            init();
        }
        dlclose(libHandle);
    }
}

Ponadto domyślne ograniczenie uniemożliwiające tworzenie projektu biblioteki dynamicznej dla systemu iOS jest czymś w Xcode, co można zastąpić, edytując niektóre pliki XCode xml:

Twórz i używaj dylib na iOS

Gdy to zrobisz, możesz zbudować normalną bibliotekę .dylib iOS i użyć jej zgodnie z przykładowym kodem powyżej. (tak, prawdopodobnie będziesz musiał ponownie odblokować tę możliwość za każdym razem, gdy zainstalujesz nową wersję XCode).

Nie jest to więc ograniczenie techniczne, ale ograniczenie zasad App Store. Jeśli nie jesteś ograniczony do App Store, możesz to zrobić. Zauważ, że ta technika nie wymaga jailbreakingu, chociaż jeśli aplikacja jest w piaskownicy, może ograniczać miejsce, z którego można ładować dylibs.

Edycja: aby upewnić się, że te informacje nie zostaną utracone przez przyszłą rotację linków, oto treść linku, który podałem, jak włączyć dylibs iOS w Xcode. ( Uwaga: ten proces nadal działa w Xcode 4, ale zobacz komentarz (y) poniżej, aby uzyskać aktualizacje ścieżek itp.) Źródłem jest blog iOS Place :


Xcode nie pozwala na tworzenie dylib dla iOS. Aplikacja zostanie odrzucona, jeśli nie jest pojedynczym plikiem binarnym. Ale mam aplikację, która ma architekturę wtyczek do ładowania opcjonalnych modułów. Chcę tylko szybkiego prototypu, który udowodniłby koncepcję przed pełnym przeniesieniem go na iOS. Jest to szybsze, jeśli dylib może po prostu działać. Ten post pokazuje, jak zbudować i używać dylib, ale pamiętaj, że nie zostanie on zatwierdzony do App Store. (Testowane z Xcode 3.2.4 w 10.6.4)

1. Otwórz te pliki w Edytorze listy właściwości: /Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX Product Types.xcspec and /Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications / iPhone Simulator ProductTypes.xcspec

2. Znajdź element w „ MacOSX Product Types.xcspec ”, który ma typ produktu com.apple.product-type.library.dynamici przeciągnij go do „ iPhone Simulator ProductTypes.xcspec ”.

Zrzut ekranu Xcode 1

3. Otwórz „ MacOSX Package Types.xcspec ” i „ iPhone Simulator PackageTypes.xcspec ”, które znajdują się w tych samych miejscach.

4. Znajdź element w „ MacOSX Product Types.xcspec ”, który ma typ pakietu com.apple.package-type.mach-o-dylibi przeciągnij go do „ iPhone Simulator PackageTypes.xcspec ”.

Zrzut ekranu Xcode 2

5. Powtórz kroki dla „ iPhoneOS.platform ” i ponownie uruchom Xcode, jeśli był uruchomiony.

Teraz zbudujmy dylib. Zacznij od szablonu „ Cocoa Touch Static Library ”. Powinno to obejmować Foundation.framework w projekcie. Oto zmiany, które wprowadziłem w górnej części szablonu, aby zbudować dylib.

1. Otwórz plik project.pbxproj (znajdujący się w pakiecie plików projektu Xcode) w edytorze tekstu. Wyszukaj ciąg „ typ produktu ”, zmień jego wartość na com.apple.product-type.library.dynamic;

Teraz otwórz projekt za pomocą Xcode, przejdź do Project-> Edit Project Settings

2.Katalog instalacyjny ” ustawiony na, @executable_path/ponieważ planuję umieścić dylib w tym samym katalogu, w którym znajduje się plik wykonywalny aplikacji.

3.Mach-O Type ” ustawiony na Dynamic Library

4.Rozszerzenie wykonywalne ” ustawione na dylib

5.Przedrostek wykonywalny ” ustawiony na pusty

6. Dodaj jedną lub dwie proste metody do biblioteki i zbuduj ją.

Teraz utwórz aplikację, aby ją przetestować. Tym razem wybieram aplikację opartą na widoku . Podłącz UIButton i UILabel, aby wywołać bibliotekę i wyświetlić komunikat zwrotny. Możesz pobrać kompletny projekt TestApp i bawić się nim.

Nate
źródło
2
Począwszy od wersji XCode 4.5, pliki te można znaleźć pod adresem (np.) /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Specifications
Chris Devereux
@ChrisDevereux, dzięki! Umieściłem notatkę, aby sprawdzić Twój komentarz pod kątem aktualnych ścieżek ... które oczywiście mogą ulec zmianie w przyszłej wersji :)
Nate
3
Ta odpowiedź wymaga więcej głosów pozytywnych (i powinna być odpowiedzią zaakceptowaną, ale wątpię, czy użytkownik510951 wróci po 2 latach nieobecności w SO). Bardzo ładna odpowiedź, Nate!
chown
1
Powinien istnieć jakiś rodzaj nadpisania mastera, w którym jeśli @chown mówi, że odpowiedź jest poprawna ... jest cholernie dobrze poprawna.
Tim
@Panagiotis, zadaj nowe pytanie, aby można było właściwie odpowiedzieć na to pytanie. Pokaż kod, którego używasz, i wszystkie komunikaty o błędach. Jeśli chcesz, możesz również podać link do tego pytania / odpowiedzi. Jeśli dodasz tag „iphone-privateapi”, zobaczę go. Powinieneś oświadczyć, że to nie jest dla sklepu z aplikacjami lub ludzie mogą głosować za zamknięciem pytania.
Nate
0

Począwszy od Xcode 11.4.1 biblioteki dynamiczne są niedozwolone (Twój projekt nie zostanie skompilowany dla wszystkich miejsc docelowych). Nowym sposobem korzystania z bibliotek / frameworków jest create-xcframework z xcodebuild.

Carla Camargo
źródło