Как написать приложение для iOS исключительно на C

Я прочитал здесь Изучить C до Objective-C?

Обычно я затем заменяю некоторый код Obj-C чистым кодом C (в конце концов, вы можете смешивать их сколько угодно, содержание метода Obj-C может быть полностью чистым кодом C)

Это правда?

Можно ли создать приложение для iPhone исключительно на языке программирования C?


person 001    schedule 23.04.2012    source источник
comment
Где вы читали, что можно создать приложение для iPhone исключительно на C?   -  person Thilo    schedule 24.04.2012
comment
@thilo возможно ... используя среду выполнения objc   -  person Richard J. Ross III    schedule 24.04.2012
comment
Возможный? да. И совершенно бессмысленно. Практически все API-интерфейсы и шаблоны системы iOS являются производными от API-интерфейсов Objective-C и Objective-C. Вы будете зря тратить время; Если вы хотите научиться программировать iOS, начните с Objective-C и по пути возьмите C.   -  person bbum    schedule 24.04.2012
comment
@Thilo Обычно я затем заменяю некоторый код Obj-C чистым кодом C (в конце концов, вы можете смешивать их сколько угодно, содержание метода Obj-C может быть полностью чистым кодом C) ссылка 1-е сообщение stackoverflow.com/questions/180549 /   -  person 001    schedule 24.04.2012
comment
@ 001: точно. Имейте в основном программу Obj-C (в частности, с использованием инфраструктуры Cocoa Touch) и напишите некоторые критические для производительности разделы на C.   -  person Thilo    schedule 24.04.2012
comment
Настоящий программист сделает это с помощью ассемблера ARM.   -  person Kristopher Johnson    schedule 25.04.2012
comment
Ах, это просто. Расскажите мне о написании iOS-приложения на чистом HTML5.   -  person keune    schedule 28.04.2012
comment
@bbum Я бы не сказал, что это бессмысленно. Когда я портировал свою игру на ПК, я был более чем счастлив, что все было написано на C ++ (да, все можно делать и на C ++). Я мог бы портировать свою игру за несколько дней, если бы я везде использовал Obj-c, это заняло бы месяцы.   -  person fbafelipe    schedule 28.06.2012
comment
Я даже не предполагал, что objective-c повсюду является обязательным требованием. Распространенной архитектурой является переносимый движок C ++ с, иногда очень тонким, слоем objective-c наверху. Полное исключение OBJC - пустая трата времени; вы используете его для доступа ко всем видам стандартных функций iOS, которыми может воспользоваться даже портативная игра.   -  person bbum    schedule 01.07.2012
comment
@KristopherJohnson, настоящий программист, использует двоичный код. : D   -  person holex    schedule 15.08.2012
comment
Однако этот вопрос не касался рабочего стола. Речь шла конкретно об iOS / iPhone.   -  person bbum    schedule 20.10.2012
comment
@bbum, конечно, конечно, но я уверен, что концепции сохранятся. Если можно взломать среду выполнения Objective C для создания приложения для iPhone, я уверен, что те же концепции будут работать и для приложения Mac OS.   -  person jmort253    schedule 24.10.2012
comment
Настоящие программисты пишут все в шестнадцатеричном формате. На бланках с 80 столбцами.   -  person Hot Licks    schedule 03.01.2013
comment
Если вы умеете пользоваться сборкой, то с ней все возможно.   -  person burak emre    schedule 07.06.2014


Ответы (4)


Блин, это заняло у меня время, но я понял:

main.c:

#include <CoreFoundation/CoreFoundation.h>

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

// This is a hack. Because we are writing in C, we cannot out and include 
// <UIKit/UIKit.h>, as that uses Objective-C constructs.
// however, neither can we give the full function declaration, like this:
// int UIApplicationMain (int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
// So, we rely on the fact that for both the i386 & ARM architectures, 
// the registers for parameters passed in remain the same whether or not 
// you are using VA_ARGS. This is actually the basis of the objective-c 
// runtime (objc_msgSend), so we are probably fine here,  this would be
// the last thing I would expect to break.
extern int UIApplicationMain(int, ...);

// Entry point of the application. If you don't know what this is by now, 
// then you probably shouldn't be reading the rest of this post.
int main(int argc, char *argv[])
{
    // Create an @autoreleasepool, using the old-stye API. 
    // Note that while NSAutoreleasePool IS deprecated, it still exists 
    // in the APIs for a reason, and we leverage that here. In a perfect 
    // world we wouldn't have to worry about this, but, remember, this is C.
    id autoreleasePool = objc_msgSend(objc_msgSend(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")), sel_registerName("init"));

    // Notice the use of CFSTR here. We cannot use an objective-c string 
    // literal @"someStr", as that would be using objective-c, obviously.
    UIApplicationMain(argc, argv, nil, CFSTR("AppDelegate"));

    objc_msgSend(autoreleasePool, sel_registerName("drain"));
}

AppDelegate.c:

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

// This is equivalent to creating a @class with one public variable named 'window'.
struct AppDel
{
    Class isa;

    id window;
};

// This is a strong reference to the class of the AppDelegate 
// (same as [AppDelegate class])
Class AppDelClass;

// this is the entry point of the application, same as -application:didFinishLaunchingWithOptions:
// note the fact that we use `void *` for the 'application' and 'options' fields, as we need no reference to them for this to work. A generic id would suffice here as well.
BOOL AppDel_didFinishLaunching(struct AppDel *self, SEL _cmd, void *application, void *options)
{
    // we +alloc and -initWithFrame: our window here, so that we can have it show on screen (eventually).
    // this entire method is the objc-runtime based version of the standard View-Based application's launch code, so nothing here really should surprise you.
    // one thing important to note, though is that we use `sel_getUid()` instead of @selector().
    // this is because @selector is an objc language construct, and the application would not have been created in C if I used @selector.
    self->window = objc_msgSend(objc_getClass("UIWindow"), sel_getUid("alloc"));
    self->window = objc_msgSend(self->window, sel_getUid("initWithFrame:"), (struct CGRect) { 0, 0, 320, 480 });

    // here, we are creating our view controller, and our view. note the use of objc_getClass, because we cannot reference UIViewController directly in C.
    id viewController = objc_msgSend(objc_msgSend(objc_getClass("UIViewController"), sel_getUid("alloc")), sel_getUid("init"));

    // creating our custom view class, there really isn't too much 
    // to say here other than we are hard-coding the screen's bounds, 
    // because returning a struct from a `objc_msgSend()` (via 
    // [[UIScreen mainScreen] bounds]) requires a different function call
    // and is finicky at best.
    id view = objc_msgSend(objc_msgSend(objc_getClass("View"), sel_getUid("alloc")), sel_getUid("initWithFrame:"), (struct CGRect) { 0, 0, 320, 480 });

    // here we simply add the view to the view controller, and add the viewController to the window.
    objc_msgSend(objc_msgSend(viewController, sel_getUid("view")), sel_getUid("addSubview:"), view);
    objc_msgSend(self->window, sel_getUid("setRootViewController:"), viewController);

    // finally, we display the window on-screen.
    objc_msgSend(self->window, sel_getUid("makeKeyAndVisible"));

    return YES;
}

// note the use of the gcc attribute extension (constructor). 
// Basically, this lets us run arbitrary code before program startup,
// for more information read here: http://stackoverflow.com/questions/2053029
__attribute__((constructor))
static void initAppDel()
{
    // This is objc-runtime gibberish at best. We are creating a class with the 
    // name "AppDelegate" that is a subclass of "UIResponder". Note we do not need
    // to register for the UIApplicationDelegate protocol, that really is simply for 
    // Xcode's autocomplete, we just need to implement the method and we are golden.
    AppDelClass = objc_allocateClassPair(objc_getClass("UIResponder"), "AppDelegate", 0);

    // Here, we tell the objc runtime that we have a variable named "window" of type 'id'
    class_addIvar(AppDelClass, "window", sizeof(id), 0, "@");

    // We tell the objc-runtime that we have an implementation for the method
    // -application:didFinishLaunchingWithOptions:, and link that to our custom 
    // function defined above. Notice the final parameter. This tells the runtime
    // the types of arguments received by the function.
    class_addMethod(AppDelClass, sel_getUid("application:didFinishLaunchingWithOptions:"), (IMP) AppDel_didFinishLaunching, "i@:@@");

    // Finally we tell the runtime that we have finished describing the class and 
    // we can let the rest of the application use it.
    objc_registerClassPair(AppDelClass);
}

View.c

#include <objc/runtime.h>

// This is a strong reference to the class of our custom view,
// In case we need it in the future.
Class ViewClass;

// This is a simple -drawRect implementation for our class. We could have 
// used a UILabel  or something of that sort instead, but I felt that this 
// stuck with the C-based mentality of the application.
void View_drawRect(id self, SEL _cmd, struct CGRect rect)
{
    // We are simply getting the graphics context of the current view, 
    // so we can draw to it
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Then we set it's fill color to white so that we clear the background.
    // Note the cast to (CGFloat []). Otherwise, this would give a warning
    //  saying "invalid cast from type 'int' to 'CGFloat *', or 
    // 'extra elements in initializer'. Also note the assumption of RGBA.
    // If this wasn't a demo application, I would strongly recommend against this,
    // but for the most part you can be pretty sure that this is a safe move 
    // in an iOS application.
    CGContextSetFillColor(context, (CGFloat []){ 1, 1, 1, 1 });

    // here, we simply add and draw the rect to the screen
    CGContextAddRect(context, (struct CGRect) { 0, 0, 320, 480 });
    CGContextFillPath(context);

    // and we now set the drawing color to red, then add another rectangle
    // and draw to the screen
    CGContextSetFillColor(context, (CGFloat []) { 1, 0, 0, 1 });
    CGContextAddRect(context, (struct CGRect) { 10, 10, 20, 20 });
    CGContextFillPath(context);
}

// Once again we use the (constructor) attribute. generally speaking, 
// having many of these is a very bad idea, but in a small application 
// like this, it really shouldn't be that big of an issue.
__attribute__((constructor))
static void initView()
{
    // Once again, just like the app delegate, we tell the runtime to 
    // create a new class, this time a subclass of 'UIView' and named 'View'.
    ViewClass = objc_allocateClassPair(objc_getClass("UIView"), "View", 0);

    // and again, we tell the runtime to add a function called -drawRect: 
    // to our custom view. Note that there is an error in the type-specification
    // of this method, as I do not know the @encode sequence of 'CGRect' off 
    // of the top of my head. As a result, there is a chance that the rect 
    // parameter of the method may not get passed properly.
    class_addMethod(ViewClass, sel_getUid("drawRect:"), (IMP) View_drawRect, "v@:");

    // And again, we tell the runtime that this class is now valid to be used. 
    // At this point, the application should run and display the screenshot shown below.
    objc_registerClassPair(ViewClass);    
}

Это некрасиво, но работает.

Если вы хотите загрузить это, вы можете получить его из моего Dropbox здесь < / с>

Вы можете получить его из моего репозитория GitHub здесь:

ScreenShot

person Richard J. Ross III    schedule 24.04.2012
comment
@ 001 спасибо, мне действительно нравится возиться со средой выполнения Obj-C, посмотрите на мой второй по популярности вопрос f.x. - person Richard J. Ross III; 24.04.2012
comment
@ 001 На самом деле, моим первым языком программирования был C #. Я перешел с C # на Java, затем с Java на ObjC, с ObjC на C, с C на C ++. Хотя C, C ++ и ObjC идут рука об руку. - person Richard J. Ross III; 24.04.2012
comment
Большой. Итак, чтобы избежать изучения Objective-C (что, я думаю, и было сутью вопроса), вам теперь нужно изучить детали реализации и API уровня C среды выполнения Objective-C. - person Thilo; 24.04.2012
comment
@Thilo Ага, это в значительной степени подводит итог :) - person Richard J. Ross III; 24.04.2012
comment
@Andrea по иронии судьбы, сборки не знаю :) - person Richard J. Ross III; 24.04.2012
comment
есть идеи, как скомпилировать и запустить приведенный выше образец кода? - person XCool; 25.04.2012
comment
@XCool Я добавил в пост ссылку, где вы можете это получить. У меня есть несколько незначительных изменений, таких как переименование файлов .m в файлы .c, но в остальном это в основном то же самое. - person Richard J. Ross III; 25.04.2012
comment
Если вы все же решите преобразовать это в сборку, в соответствии с несколькими предложениями, обязательно сделайте это в ARM (обычный набор команд и набор команд большого пальца!) И в x86, чтобы он работал в симуляторе. Может быть, также PowerPC для хорошей меры, если вы хотите перенести его на Mac OS X v10.4. - person Adam Rosenfield; 27.04.2012
comment
Технически это не чистый C! Этот @"AppDelegate является константой NSString и не будет компилироваться компилятором только для Си. Вместо этого используйте CFSTR("AppDelegate"). - person ; 02.07.2012
comment
Без обид, приятель. Вы заметили, что я только что проголосовал за вас? (И да, уважение к тому, что у меня в 2 раза больше репутации, чем у меня, несмотря на то, что я на 3 года моложе ...) - person ; 02.07.2012
comment
@CodaFi Хорошо, я обновил ответ, насколько я знаю, теперь он имеет чистый C. - person Richard J. Ross III; 03.07.2012
comment
@ H2CO3 Под давлением прогнулся, поправил файл main.c. - person Richard J. Ross III; 03.07.2012
comment
Блин ... ворчать ворчать ... Что ж, я все равно не удалю свой ответ. БУАХАХАХАХАХА - person CodaFi; 03.07.2012
comment
Как бы то ни было, (CGFloat []) - это не приведение: это часть составного литерала (функция C99). - person Dave; 08.07.2012
comment
@ Дэйв, но это все еще C, так что он остается. - person Richard J. Ross III; 09.07.2012
comment
С ними нет проблем - я исправил, что они не являются, как утверждают ваши комментарии, кастомами. Бита C99 была лишь дополнительной деталью. - person Dave; 09.07.2012
comment
@Dave не стесняйтесь редактировать комментарии. (с соответствующей ссылкой на спецификацию для этого) - person Richard J. Ross III; 09.07.2012
comment
Только что наткнулся на это после того, как вы ответили на один из моих вопросов. Я потерял дар речи, лол. - person 0xSina; 25.08.2012
comment
@ 0xSina, спасибо, ха-ха. Я только хотел бы сделать это в сборке :( - person Richard J. Ross III; 25.08.2012
comment
Мне нравится комментарий Точка входа в приложение. Если вы еще не знаете, что это такое, то вам, вероятно, не следует читать оставшуюся часть этого поста. :-D - person Dan; 06.02.2013
comment
Поправьте меня, если я ошибаюсь, но разве id не ключевое слово objective-c (используемое в основном методе)? Разве это не должно быть void *? - person esh; 15.04.2013
comment
@ blackFlam3 нет, id - это typedef для struct objc_object *, он определен в objc/objc.h. - person Richard J. Ross III; 15.04.2013
comment
@landonf не совсем так. Это тот случай, если вы компилируете как objective-c, но поскольку мы компилируем только как C, компилятор не знает, что этот метод особенный, он фактически вызывает его с помощью varargs. - person Richard J. Ross III; 18.04.2013
comment
@iandonf ну, хорошо, что ios разработан для архитектур ARM и x86, так как регистры, используемые для параметров, не меняются. - person Richard J. Ross III; 20.04.2013
comment
@ RichardJ.RossIII Если вам удобно, что люди берут этот ответ и пишут код, который на самом деле зависит от архитектуры, я полагаю. Конечно, я даже не коснулся обработки _stret / _fpret, это еще одна проблема. Просто невозможно написать переносимый ObjC на C; сгенерированный код неизбежно зависит от ABI. - person landonf; 21.04.2013
comment
@iandof, вы можете возразить, что весь C специфичен для ABI и не переносится (как часто вам нужно вставлять #if MSVC в переносимый код), потому что у каждой платформы и компилятора есть свои причуды и ошибки, но это не значит что вам не следует писать код на C! - person Richard J. Ross III; 21.04.2013
comment
@landonf Я это прекрасно понимаю. Я просто говорю, что игра в стандарты или, в данном случае, игра в архитектуру редко бывает полезной, поскольку эти ABI вряд ли изменятся в ближайшем будущем, когда этот ответ уместен. В любом случае, мы забиваем здесь комментарии, так что +1 и / thread. - person Richard J. Ross III; 22.04.2013
comment
@Quuxplusone Я бы мог, если бы подумал об этом. По-прежнему технически неопределенное поведение - передавать один тип функции, объявленной для приема другого, даже если существует неявное преобразование. Однако мне нравится этот комментарий, поэтому он остается. - person Richard J. Ross III; 01.05.2013
comment
@Quuxplusone, и я не думаю, что хочу менять эту строчку. Меня не особо волнует +new, так как я чувствую, что это менее ясно из того, что происходит за кулисами. Различие между распределением и инициализацией важно ИМО. - person Richard J. Ross III; 01.05.2013
comment
@Quuxplusone Я не думаю, что есть способ обойти тот факт, что этот код действительно загадочен. - person Richard J. Ross III; 02.05.2013
comment
@Maxthon, конечно, это правильно - и я могу в конечном итоге внести эти изменения в репозиторий git, но я не собираюсь снова поднимать вопрос из-за таких незначительных изменений. - person Richard J. Ross III; 17.06.2013
comment
@ RichardJ.RossIII Эта вещь __class фактически взята из моего проекта HTTP-сервера Objective-C - с этим я выставил несколько постоянных строк и CGIAppllicationMain(int, const char **, const char *, const char *) в C (и, таким образом, я могу использовать CGIApplicationMain в main.c) - person Maxthon Chan; 17.06.2013
comment
@ RichardJ.RossIII, я хотел бы перенести приложение C / OpenGL на iOS, и мне нужно взаимодействовать с существующими механизмами ввода ввода (касание, IME) Obj-C. Какую документацию Apple я бы хотел найти для этого? Или что-то в этом роде - например, что вы здесь сделали - полностью недокументировано? - извините за вопрос, совершенно новичок в iOS. - person Engineer; 06.08.2015
comment
не могли бы вы объяснить, что делает ключевое слово Class в заявителях Class isa; и Class AppDelClass;? это ключевое слово C? Я пытался погуглить, но я ничего не нашел при поиске в Google "Класс" - person Benj; 26.10.2016
comment
@Benj Class - это typedef, определенный в objc/runtime.h для структуры objc_class, которая является непрозрачным указателем. - person Richard J. Ross III; 26.10.2016

Objective-C - это надмножество языка C, поэтому теоретически возможно написать программу полностью на C, однако, если вы не разбираетесь в OpenGL ES, вам нужно будет сделать хотя бы несколько objC (Даже в образце Rich есть const NSString *), иначе вам придется писать представления самостоятельно.

Хорошо, вышесказанное совершенно неверно. Позвольте мне сказать, я поражен, что Рич достиг этой высокой цели, поэтому я перенес ее на Mac (источник здесь). Приведенные ниже файлы не имеют заголовков, не ссылаются на Какао, и у проекта нет пера:

AppDelegate.m

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

extern id NSApp;

struct AppDel
{
    Class isa;

    //Will be an NSWindow later, for now, it's id, because we cannot use pointers to ObjC classes
    id window;
};


// This is a strong reference to the class of the AppDelegate
// (same as [AppDelegate class])
Class AppDelClass;

BOOL AppDel_didFinishLaunching(struct AppDel *self, SEL _cmd, id notification) {
    //alloc NSWindow
    self->window = objc_msgSend(objc_getClass("NSWindow"),
                                sel_getUid("alloc"));
    //init NSWindow
    //Adjust frame.  Window would be about 50*50 px without this
    //specify window type.  We want a resizeable window that we can close.
    //use retained backing because this thing is small anyhow
    //return no because this is the main window, and should be shown immediately
    self->window = objc_msgSend(self->window,
                                sel_getUid("initWithContentRect:styleMask:backing:defer:"),(NSRect){0,0,1024,460}, (NSTitledWindowMask|NSClosableWindowMask|NSResizableWindowMask|NSMiniaturizableWindowMask),NSBackingStoreRetained,NO);

    //send alloc and init to our view class.  Love the nested objc_msgSends!
    id view = objc_msgSend(objc_msgSend(objc_getClass("View"), sel_getUid("alloc")), sel_getUid("initWithFrame:"), (struct CGRect) { 0, 0, 320, 480 });

    // here we simply add the view to the window.
    objc_msgSend(self->window, sel_getUid("setContentView:"), view);
    objc_msgSend(self->window, sel_getUid("becomeFirstResponder"));

    //makeKeyOrderFront: NSWindow to show in bottom left corner of the screen
    objc_msgSend(self->window,
                 sel_getUid("makeKeyAndOrderFront:"),
                 self);
    return YES;
}

static void initAppDel()
{
    //Our appDelegate should be NSObject, but if you want to go the hard route, make this a class pair of NSApplication and try initing those awful delegate methods!
    AppDelClass = objc_allocateClassPair((Class)
                                         objc_getClass("NSObject"), "AppDelegate", 0);
    //Change the implementation of applicationDidFinishLaunching: so we don't have to use ObjC when this is called by the system.
    class_addMethod(AppDelClass,
                    sel_getUid("applicationDidFinishLaunching:"),
                    (IMP) AppDel_didFinishLaunching, "i@:@");

    objc_registerClassPair(AppDelClass);
}

void init_app(void)
{
    objc_msgSend(
                 objc_getClass("NSApplication"),
                 sel_getUid("sharedApplication"));

    if (NSApp == NULL)
    {
        fprintf(stderr,"Failed to initialized NSApplication...  terminating...\n");
        return;
    }

    id appDelObj = objc_msgSend(
                                objc_getClass("AppDelegate"),
                                sel_getUid("alloc"));
    appDelObj = objc_msgSend(appDelObj, sel_getUid("init"));

    objc_msgSend(NSApp, sel_getUid("setDelegate:"), appDelObj);
    objc_msgSend(NSApp, sel_getUid("run"));
}

//there doesn't need to be a main.m because of this little beauty here.
int main(int argc, char** argv)
{
    //Initialize a valid app delegate object just like [NSApplication sharedApplication];
    initAppDel();
    //Initialize the run loop, just like [NSApp run];  this function NEVER returns until the app closes successfully.
    init_app();
    //We should close acceptably.
    return EXIT_SUCCESS;
}

View.m

#include <objc/runtime.h>
#include <objc/message.h>
#include <ApplicationServices/ApplicationServices.h>

// This is a strong reference to the class of our custom view,
// In case we need it in the future.
Class ViewClass;


// This is a simple -drawRect implementation for our class. We could have
// used a UILabel  or something of that sort instead, but I felt that this
// stuck with the C-based mentality of the application.
void View_drawRect(id self, SEL _cmd, CGRect rect)
{
    //make a red NSColor object with its convenience method
    id red  = objc_msgSend(objc_getClass("NSColor"), sel_getUid("redColor"));

    // fill target rect with red, because this is it!
    NSRect rect1 = NSMakeRect ( 21,21,210,210 );
    objc_msgSend(red, sel_getUid("set"));
    NSRectFill ( rect1 );
}

// Once again we use the (constructor) attribute. generally speaking,
// having many of these is a very bad idea, but in a small application
// like this, it really shouldn't be that big of an issue.
__attribute__((constructor))
static void initView()
{

    // Once again, just like the app delegate, we tell the runtime to
    // create a new class, this time a subclass of 'UIView' and named 'View'.
    ViewClass = objc_allocateClassPair((Class) objc_getClass("NSView"), "View", 0);

    // and again, we tell the runtime to add a function called -drawRect:
    // to our custom view. Note that there is an error in the type-specification
    // of this method, as I do not know the @encode sequence of 'CGRect' off
    // of the top of my head. As a result, there is a chance that the rect
    // parameter of the method may not get passed properly.
    class_addMethod(ViewClass, sel_getUid("drawRect:"), (IMP) View_drawRect, "v@:");

    // And again, we tell the runtime that this class is now valid to be used.
    // At this point, the application should run and display the screenshot shown below.
    objc_registerClassPair(ViewClass);
}

prefix.pch

//
// Prefix header for all source files of the 'CBasedMacApp' target in the 'CBasedMacApp' project
//

#ifdef __OBJC__
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#endif

введите описание изображения здесь

person CodaFi    schedule 23.04.2012
comment
Неправда, вы можете использовать среду выполнения objc для создания приложения на C, дайте мне несколько минут, и я покажу вам - person Richard J. Ross III; 24.04.2012
comment
Да, и вы можете выкопать основу ложкой, но это не делает ее ни хорошей идеей, ни очень эффективной. - person bbum; 24.04.2012
comment
@ MahmoudAl-Qudsi Я не сдавался :) - person Richard J. Ross III; 24.04.2012
comment
@ Ричард, ты накрыл основу ложкой и не сдался? Хвалю тебя! (Я шучу, я шучу ... но это была моя шутка в предыдущем комментарии :) - person Mahmoud Al-Qudsi; 24.04.2012
comment
Что ж, умение также может пригодиться, когда вы находитесь в искуплении Шоушенка ... - person Hejazzman; 25.04.2012
comment
Ага. Что меня понимает, так это то, что если бы не современный код времени выполнения, это работало бы на каждом Mac с X в названии программного обеспечения. - person CodaFi; 04.07.2012
comment
Привет, CodaFi, похоже, ваша ссылка не работает: github.com/CodaFi/CBasedMacApp. Есть ли шанс исправить это? Кроме того, я заметил, что вы все еще используете файлы .m? Компилируются ли они как файлы .c? - person jmort253; 24.10.2012
comment
@ jmort253: мои извинения. Я переименовал репо в C-Mac (ха!) И не подумал переделывать ссылку. Исправляем это сейчас. Кроме того, файлы должны иметь расширение .m, чтобы избежать странных проблем с импортом заголовков. Все равно все превращается в .o. - person CodaFi; 24.10.2012
comment
Я был бы осторожен с этим. Приложение в значительной степени зависит от пользователя, имеющего libObjc для связи (что означает Mac и случайного пользователя Linux). - person CodaFi; 24.10.2012
comment
Это не чистый C. NSApp - это динамически разделяемая переменная. Для этого требуются специальные разделы в файле Mach-O, которые создаются компилятором ObjC. Если вы скомпилируете его с помощью компилятора C, он не будет работать, возможно, даже не будет компилироваться. - person PineForestRanch; 02.04.2016
comment
Если вы хотите получить техническую информацию, у меня есть репозиторий, в который вы можете внести исправления. Я уверен, что есть способ имитировать NSApplication со средой выполнения, чтобы добиться чистой реализации к вашему удовлетворению, не так ли? - person CodaFi; 02.04.2016
comment
Да, и если clang -x c -arch x86_64 -std=gnu99 -I ./CMacs -c $(SRCFILES) когда-нибудь не сработает - что, кажется, имеет место с вашей стороны - сообщите о проблеме. Я не могу вам помочь в комментариях! - person CodaFi; 02.04.2016

Я прочитал здесь Изучить C до Objective-C?

Обычно я затем заменяю некоторый код Obj-C чистым кодом C (в конце концов, вы можете смешивать их сколько угодно, содержание метода Obj-C может быть полностью чистым кодом C)

Это правда?

Могу ли я создать приложение для iPhone исключительно на языке программирования C?

Цитируемый отрывок верен, но ответ на ваш вопрос отрицательный.

Чтобы проиллюстрировать, о чем говорил Меки на другой вопрос:

- (void) drawRect:(CGRect)dirtyRect { //Objective-C

    CGContextRef context = UIGraphicsGetCurrentContext();  //C
    CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0); //C
    CGContextFillRect(context, dirtyRect);                 //C

} //Objective-C (balances above “- (void) drawRect:…” line)

В этом методе нет ничего, кроме чистого кода C внутри, но сам метод является кодом Objective-C, как и класс, содержащий этот метод.

Таким образом, можно сделать то, что сказал Меки, но вы не можете (практически - как показал Ричард Дж. Росс III, это технически возможно, но довольно много набора текста) написать целую программу Cocoa Touch на чистом C.

person Peter Hosey    schedule 24.04.2012

На самом деле, часть кода, размещенного здесь, хотя и написана на C, по-прежнему вызывает код Objective-C :). Я не знаю, соответствует ли это сценарию оригинального плаката, когда он спросил

Можно ли создать приложение для iPhone исключительно на языке программирования C?

но я согласен с людьми, которые говорят, что, вообще говоря, и для приложения с графическим интерфейсом вам нужно будет написать свой графический интерфейс в OpenGL (это C).

Я думаю, что это то, что делает большинство игр, верно? Хотя я не уверен, есть ли доступ к вводу-выводу iPhone (например, сенсорному экрану) в C.

И последнее, но не менее важное: ребята, написавшие код выше, молодцы! :)

person make.it.floss    schedule 19.11.2013
comment
в соответствии с требованиями мы используем c-код при разработке для iPhone и iOS. - person Sport; 19.11.2013
comment
objc_msgSend() - это чистый C. Тот факт, что я вызываю initWithFrame:, не имеет значения, поскольку реализации методов также являются функциями C. - person Gabriele Petronella; 19.11.2013
comment
objc_msgSend () - это функция C, да, но это часть среды выполнения Objective-C, верно? - person make.it.floss; 20.11.2013
comment
Я не видел никаких конструкций Obj-C в размещенном там коде. Но все же это работает даже при вызове библиотек obj-c на языке C! - person techcraver; 31.12.2016