Qt for iOS, mixed programming of Qt and Objective C, iosobjective
Recently, some friends who use Qt asked about Qt for iOS, because I have little experience in this field and cannot write system articles. I am very sorry, I cannot give a satisfactory answer. I suggest you go to Jason's Home. There is also a link in the left sidebar of my blog. He provides some very meaningful articles on Qt for iOS, in addition, it is based on practice that his App has been launched in the App Store.
As for me, this article briefly introduces how to mix Qt and OC programming.
Most of the content I want to talk about is available in Qt help. Please enter "Qt for iOS" in index mode and find the article Qt for iOS. It introducesBuild a Development Environment,Compile an application,Hybrid OC ProgrammingThese three aspects are already very detailed.
If you do not want to chew on English, you can continue to read my article.
Project Settings
Since we want to talk about Qt hybrid OC programming, we should first briefly introduce Objective C. I only have one sentence: Go, ask the search engine to Go. Because I know it is limited, I am afraid to mislead you. Of course, if you are not afraid, let's take a look.
OC source file Introduction
First, let me talk about the source file of Objective C with the suffix of. m or. mm. In the. mm file, C ++ code can be directly used. Therefore, to mix the Qt code and OC code, we need to add the mm file to the Qt project.
Pro file configuration
After the Qt SDK for Mac is installed, Qt Creator uses the compilation tool chain provided by XCode to compile the code, correctly compile the mm file, or link the iOS library file.
To mix the OC code, you need to change the pro file. One is to add the mm file, and the other is to connect the library file for iOS.
Add the source file and use the OBJECTIVE_SOURCES variable, such:
OBJECTIVE_SOURCES += ocview.mm
To connect to the library provided by XCode, you need to use QMAKE_LFLAGS, which is similar to sauce purple:
ios { QMAKE_LFLAGS += -framework OpenGLES QMAKE_LFLAGS += -framework GLKit QMAKE_LFLAGS += -framework QuartzCore QMAKE_LFLAGS += -framework CoreVideo QMAKE_LFLAGS += -framework CoreAudio QMAKE_LFLAGS += -framework CoreImage QMAKE_LFLAGS += -framework CoreMedia QMAKE_LFLAGS += -framework AVFoundation QMAKE_LFLAGS += -framework AudioToolbox QMAKE_LFLAGS += -framework CoreGraphics QMAKE_LFLAGS += -framework UIKit}
The above is my configuration for iOS programming using Qt. I used a lot of libraries for iOS, so I added a lot of frameworks.
"-Framework UIKit" is a parameter passed to Clang through Makefile, and-framework is a keyword used to indicate a framework (or library) to be linked, it is followed by the Framework (Library) Name.
Note that we use a library for iOS instead of using "LIBS + =. Of course, you still need to use the "LIBS + =" method for the. a library implemented by Qt.
Specify plist File
Sometimes you need to specify the plist file for your project. The full name of the plist file is Property List and the suffix is. plist. It is used to define the attributes of iOS applications, such as the display name, executable file name, signature, and certificate of a Bundle (an application on iOS is called a Bundle, of course, you can also save some configuration data. For more information, see the iOS development documentation.
To add plist to the pro file, use the QMAKE_INFO_PLIST keyword. As shown in the following figure:
QMAKE_INFO_PLIST += MultiWindow.plist
Okay, that's all about the configuration items related to the mixed use of OC in the pro file. Next, let's look at how to write Objective C code.
Use Objective C code in combination
Sorry, I am very scared. This is my weakness and I have not written many OC codes. Therefore, please do not ask me OC-related questions. I really don't know ......
Background
In my example, a native iOS interface, such as UIView and UIWindow, is superimposed on the QML interface. Because OC is a close relative of C and has a natural kinship with C ++, it is especially convenient to mix it and it is much easier to use than JNI programming on Android.
However, OC applies the [] syntax to call functions. If XCode is used, syntax prompts and Automatic completion functions are very powerful. You can find the functions you need without thinking about. And Qt Creator, hey, there's no such thing as well, just handwriting. I was using XCode to read the API documentation, which was quite painful.
What is QQuickView?
I used the Qt Quick App Project template and QQuickView to load the QML document. This is also an example.
First, let's talk about what QQuickView is.
QQuickView is actually a UIView. UIView is the root of many interface elements in the iOS development framework. For example, UIWindow is a subclass of UIView.
QQuickView of Qt is a UIView. After a QQuickView instance is created, a UIView is created. Then Qt plays some magic and obtains the OpenGL Context of UIView and runs the Qt event loop, in this OpenGL Context, you have drawn your own scenario and UI system from scratch.
In this case, you can refer to the Qt source code for further understanding.
It should be noted that the rendering of the QML interface elements is not in the same thread as the rendering of the native interface such as UIView. Besides, iOS supports OpenGL ES very well. You can use multiple OpenGL Context at the same time. Better yet, you can create an OpenGL Context in window mode. Unlike the Android version, Qt uses full screen mode when using OpenGL, and partial update is not supported. Therefore, when we use Camera and VideoOutput in QML on Android to develop Photo apps, videoOutput must be in full screen mode (fill_parent is required ). On iOS, there is no such restriction. It seems that iOS is still wonderful.
I rely on it for a long time. Recently, I have written fewer technical articles and become more and more arrogant. Let's get down to the truth.
Because QQuickView is actually a UIView, You can forcibly convert it to a UIView, and then use the OC method to create a new UIView or UIWindow, so that you have a native UI component, you can use OpenGL on this native UI component to draw your own things or add other native controls, which is very nice.
However, the native iOS interface elements created using this method will always cover the interface elements in the QML scenario on the QML interface.
Hybrid code
To use the OC class library, you need to include the relevant header file in the mm file, and there are some work to do. Add the SDK path to the pro file and use the INCLUDEPATH variable. Another point is to include the OC header file in the mm file, which is the same as the C ++ header file.# ImportOh. Similar to soy sauce:
#import <UIKit/UIKit.h>#import <GLKit/GLKit.h>
If the header file is included, you can use the OC class library. For example, if I want to create a new iOS native UIView on QQuickView, The. mm file can be like this:
void addOCView(QQuickWindow *w){ UIView *view = reinterpret_cast<UIView *>(w->winId()); CGRect viewRect = CGRectMake(10, 10, 100, 100); UIView* myView = [[UIView alloc] initWithFrame:viewRect]; [myView setBackgroundColor:[UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0]]; [view addSubview: myView];}
As you can see, I wrote an addOCView method whose parameter is QQuickView. In the addOCView method, I forcibly convert QQuickView to UIView.
I created a new UIView, set its background color, and add it as a subwindow of QQuickView. That's easy.
Let's talk about main. cpp and see how it uses the addOCView () method. The Code is as follows:
int main(int argc, char *argv[]){ QGuiApplication app(argc, argv); QQuickView viewer; viewer.setResizeMode(QQuickView::SizeRootObjectToView); viewer.setSource(QUrl("qrc:/main.qml")); viewer.show(); addOCView(&viewer); return app.exec();}
I'm not surprised at all, right? I called addOCView directly. Haha.
Location ing between the iOS Native Interface and QML Elements
When using the iOS native interface, you can also seamlessly integrate the native interface with the QML interface. The key lies in calculating the location of the QML interface element, and then setting the location of the Native Interface Based on the location of the QML interface element.
QML element position Conversion
QML provides a method for converting element positions. Item has a method called mapToItem (), which maps a region relative to Qt Quick Item to another Item and obtains coordinates. For example, your qml file looks like the following:
Rectangle { ... Rectangle { id: videoLayer; anchors.margins: 8; anchors.left: parent.left; anchors.right: parent.right; anchors.top: parent.top; anchors.bottom: actionBar.top; color: "green"; } ...}
To locate the native UIView inside the videoLayer element, you can convert the following coordinates and use it:
var coordinate = videoLayer.mapToItem(null, 8, 8, videoLayer.width - 16, videoLayer.height - 16);winUtil.addUIView(coordinate.x, coordinate.y, coordinate.width, coordinate.height);
The calculated coordinate has the attributes x, y, width, and height. When mapToItem's first parameter is null, the conversion result is relative to QQuickView. When we add a UIView, we can use this conversion result to construct a CGRect object and use this CGRect to initialize the position of the UIView.
Set the UIView location
In the preceding sample code, winUtil is a helper class that I implemented in C ++ and exported to the QML environment. Its addUIView method sets the native UIView position based on the input coordinates. The reference code is as follows:
UIView *v = reinterpret_cast<UIView*>(view->winId()); uiw = [[UIWindow alloc] initWithFrame:CGRectMake(x, y, width, height)]; [v addSubview: uiw];
In the code above, view is QQuickView. This time, we used the input x, y, width, and height when creating the UIView. In this way, the newly created UIView is integrated with the QML element, and it seems to be integrated.
OK, this is all.