如果您想了解使用Swift的UIApplication子类和swiftuiview的知识,那么本篇文章将是您的不二之选。我们将深入剖析使用Swift的UIApplication子类的各个方面,并为您解
如果您想了解使用Swift的UIApplication子类和swift uiview的知识,那么本篇文章将是您的不二之选。我们将深入剖析使用Swift的UIApplication子类的各个方面,并为您解答swift uiview的疑在这篇文章中,我们将为您介绍使用Swift的UIApplication子类的相关知识,同时也会详细的解释swift uiview的运用方法,并给出实际的案例分析,希望能帮助到您!
本文目录一览:- 使用Swift的UIApplication子类(swift uiview)
- 6.10 Swift的懒加载(lazy initialization)使用解析 [Swift原创教程]
- android.app.Application子类,onTerminate不被调用
- c# – 在Winforms-Application中嵌入的Unity-Application上调用函数[复制]
- diffrence between UIApplication sharedApplication
使用Swift的UIApplication子类(swift uiview)
在Objective C中很简单:只需更新main.m文件并更改UIApplicationMain()参数即可
return UIApplicationMain(argc, argv, NSStringFromClass([CustomUIApplication class]), NSStringFromClass([AppDelegate class]));
但是由于该指南指出,因此没有main.m文件
“在全局范围内编写的代码被用作程序的入口点,因此您不需要主要功能。”
那么,如何快速将UIApplication子类化?有什么建议吗?
答案1
小编典典注意: 如果您正在寻找以前的语法,请在2019年6月对XCode 10.1和Swift
5的语法进行了更新
好,我找到了解决方案
首先,我注意到,在AppDelegate.swift文件的顶部,有这行
@UIApplicationMain
由于该行在任何范围之外(在文件级别),因此将立即执行,并且我假设编译器将其转换为标准的main函数。
因此,我从一个新的Swift-Only应用程序开始执行此操作:
- 注释掉
@UIApplicationMain
- 像这样添加了一个main.swift文件(FLApplication是我的子类)。
重要
文件必须命名为main.swift,因为其他文件不支持顶级语句!您不能在任何其他文件中添加UIApplicationMain()调用,否则将收到此错误:
不允许在顶层使用表达式
这是main.swift文件
UIApplicationMain( CommandLine.argc, CommandLine.unsafeArgv, NSStringFromClass(FLApplication.self), NSStringFromClass(AppDelegate.self))
然后,使用以下代码为UIApplication子类FLApplication.swift创建一个swift文件:
import UIKitimport Foundationclass FLApplication: UIApplication { override func sendEvent(_ event: UIEvent) { super.sendEvent(event) print("send event") }}
现在,UIApplication已正确子类化,您将在日志中看到“发送事件”消息
旧版本
供参考,由于此版本从版本1到版本3发生了很大变化,因此我将所有以前的编辑保留在此处
编辑-2015年3月
正如UIApplicationMain
胡俊峰所评论的那样,有关和main.swift文件的说明已记录在《
Swift语言参考:链接》的
“属性”部分中
正如Thomas Verbeek在XCode 6.3
Beta中所评论的那样,您可能会发现C_ARGC和C_ARGV已分别重命名为Process.argc和Process.unsafeArgv。您在main.swift文件中的UIApplicationMain调用将需要更新为:
UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(FLApplication), NSStringFromClass(AppDelegate))
XCode 8之前的语法是
import Foundationimport UIKitUIApplicationMain(C_ARGC, C_ARGV, NSStringFromClass(FLApplication), NSStringFromClass(AppDelegate))
编辑-2016年12月
Beta 6之前的Xcode 8解决方案
import Foundationimport UIKitUIApplicationMain( CommandLine.argc, UnsafeMutableRawPointer(CommandLine.unsafeArgv) .bindMemory( to: UnsafeMutablePointer<Int8>.self, capacity: Int(CommandLine.argc)), NSStringFromClass(FLApplication.self), NSStringFromClass(AppDelegate.self))
6.10 Swift的懒加载(lazy initialization)使用解析 [Swift原创教程]
原文:http://coolketang.com/staticCoding/5a99261f17d0090035986bfc.html
1. 本节课将为你解析懒加载的概念。顾名思义,懒加载就是用到的时候再开辟内存空间,多次使用只会加载一次。
2. 首先导入需要使用到的界面工具框架。
3. 然后创建一个类,该类将拥有一个具有懒加载特性的属性。
4. 给类添加一个字符串类型的变量。
5. 添加另一个字符串类型的变量,并通过懒加载关键词,设置该变量具有懒加载的特性。当该变量被使用到的时候,才会执行等号后面的闭包语句。
6. 在闭包语句中,判断如果字符串是以超文本传输协议开头的字符串,则直接返回属性的值。
7. 否则在上一个属性的值的前方,增加超文本传输协议,并返回最终的结果。
8. 添加一个初始化方法,对第一个属性进行设置。
9. 接着初始化该类的实例,并设置实例的属性的值。
10. 查看第一个属性的值。
11. 点击右侧的查看结果图标,查看实例的内容。
12. 从结果列表可以看出,第二个属性的值为空。
13. 接着获取第二个属性的值,由于使用到了该属性,所以懒加载发挥作用,对该属性的值进行了设置。从右侧的实时反馈区,可以看到该属性的值。
14. 点击右侧的查看结果图标,查看实例的内容。
15. 从结果列表可以看出,实例的第二个属性已经拥有了值。
android.app.Application子类,onTerminate不被调用
“需要维护全球应用状态的人的基础类”
我正在使用我自己的子类来维护一个我用来查询服务器的对象.还从文档中:
“onTerminate()当应用程序停止时调用”.
但是,我的类中的onTerminate()从不被调用.在查看主要活动的同时按下后退按钮,一切似乎都被关闭.我的主要Activity的onDestroy()方法被调用,isFinishing()返回true,但是我的android.app.Application的onTerminate()方法从未被调用.
为什么是这样?我失踪了什么有什么东西保持开放吗?
解决方法
javadoc也指出不要依赖onTerminate代码被调用.
Note: never depend on this method being called; in many cases an unneeded application process will simply be killed by the kernel without executing any application code.
c# – 在Winforms-Application中嵌入的Unity-Application上调用函数[复制]
> Embed Unity3D app inside WPF application 1个
我目前正在为编辑器开发一个简单的原型.编辑器将使用WinForms(或WPF,如果可能)提供主用户界面,并且还将嵌入Unity 2017独立应用程序以可视化数据并提供其他控制元素(例如缩放,旋转,滚动……).
感谢下面的这篇好文章,让一个嵌入式Unity应用程序在WinForms应用程序中运行非常容易.
https://forum.unity.com/threads/unity-3d-within-windows-application-enviroment.236213/
此外,还有一个简单的示例应用程序,您可以在此处访问:
Example.zip
遗憾的是,无论是示例还是我找到的任何帖子都没有回答一个非常基本的问题:如何从嵌入式Unity应用程序中的WinForms应用程序传递数据(或调用方法)(反之亦然)?
您的WinForms应用程序是否可以在Unity应用程序中简单地调用MonoBehavIoUr脚本或静态方法?如果是这样,怎么样?如果没有,那么什么是好的解决方法? Unity-to-WinForms通信如何能够作为回报呢?
更新:
使用Programmer(link)提到的重复页面来实现一个解决方案,该解决方案使用命名管道在WinForms和Unity应用程序之间进行通信.
两个应用程序都使用BackgroundWorkers,WinForms应用程序充当服务器(因为它在客户端启动之前首先启动并需要一个活动的连接侦听器),而嵌入式Unity应用程序充当客户端.
不幸的是,Unity-application抛出NotImplementedException,在创建NamedPipeClientStream(使用Unity 2017.3和Net 2.0(不是Net 2.0子集)测试)时声明“Mono不支持ACL”).在the post mentioned above的一些评论中已经报道了这个例外,但如果它已经解决,则不清楚.建议的解决方案“确保服务器在客户端尝试连接之前启动并运行”和“以管理模式启动”已经尝试过,但到目前为止都失败了.
解:
经过一些更多测试后,很明显,“Mono不支持ACL”异常导致在创建NamedPipeClientStream实例时使用TokenImpersonationLevel参数.将其更改为TokenImpersonationLevel.None解决了该问题.
这里是WinForms应用程序使用的代码,它充当命名管道服务器.确保在Unity应用程序客户端尝试连接之前执行此脚本!此外,请确保在启动服务器之前已构建并发布Unity应用程序.将Unity应用程序的Unity可执行文件放在WinForms-applications文件夹中,并将其命名为“Child.exe”.
using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; using System.Diagnostics; using System.IO.Pipes; namespace Container { public partial class MainForm : Form { [DllImport("User32.dll")] static extern bool MoveWindow(IntPtr handle,int x,int y,int width,int height,bool redraw); internal delegate int WindowEnumProc(IntPtr hwnd,IntPtr lparam); [DllImport("user32.dll")] internal static extern bool EnumChildWindows(IntPtr hwnd,WindowEnumProc func,IntPtr lParam); [DllImport("user32.dll")] static extern int SendMessage(IntPtr hWnd,int msg,IntPtr wParam,IntPtr lParam); /// <summary> /// A Delegate for the Update Log Method. /// </summary> /// <param name="text">The Text to log.</param> private delegate void UpdateLogCallback(string text); /// <summary> /// The Unity Application Process. /// </summary> private Process process; /// <summary> /// The Unity Application Window Handle. /// </summary> private IntPtr unityHWND = IntPtr.Zero; private const int WM_ACTIVATE = 0x0006; private readonly IntPtr WA_ACTIVE = new IntPtr(1); private readonly IntPtr WA_INACTIVE = new IntPtr(0); /// <summary> /// The Background Worker,which will send and receive Data. /// </summary> private BackgroundWorker backgroundWorker; /// <summary> /// A Named Pipe Stream,acting as the Server for Communication between this Application and the Unity Application. /// </summary> private NamedPipeServerStream namedPipeServerStream; public MainForm() { InitializeComponent(); try { //Create Server Instance namedPipeServerStream = new NamedPipeServerStream("NamedPipeExample",PipeDirection.InOut,1); //Start Background Worker backgroundWorker = new BackgroundWorker(); backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork); backgroundWorker.WorkerReportsProgress = true; backgroundWorker.RunWorkerAsync(); //Start embedded Unity Application process = new Process(); process.StartInfo.FileName = Application.StartupPath + "\\Child.exe"; process.StartInfo.Arguments = "-parentHWND " + splitContainer.Panel1.Handle.ToInt32() + " " + Environment.CommandLine; process.StartInfo.UseShellExecute = true; process.StartInfo.CreateNowindow = true; process.Start(); process.WaitForInputIdle(); //Embed Unity Application into this Application EnumChildWindows(splitContainer.Panel1.Handle,WindowEnum,IntPtr.Zero); //Wait for a Client to connect namedPipeServerStream.WaitForConnection(); } catch (Exception ex) { throw ex; } } /// <summary> /// Activates the Unity Window. /// </summary> private void ActivateUnityWindow() { SendMessage(unityHWND,WM_ACTIVATE,WA_ACTIVE,IntPtr.Zero); } /// <summary> /// Deactivates the Unity Window. /// </summary> private void DeactivateUnityWindow() { SendMessage(unityHWND,WA_INACTIVE,IntPtr.Zero); } private int WindowEnum(IntPtr hwnd,IntPtr lparam) { unityHWND = hwnd; ActivateUnityWindow(); return 0; } private void panel1_Resize(object sender,EventArgs e) { MoveWindow(unityHWND,splitContainer.Panel1.Width,splitContainer.Panel1.Height,true); ActivateUnityWindow(); } /// <summary> /// Called,when this Application is closed. Tries to close the Unity Application and the Named Pipe as well. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_FormClosed(object sender,FormClosedEventArgs e) { try { //Close Connection namedPipeServerStream.Close(); //Kill the Unity Application process.CloseMainWindow(); Thread.Sleep(1000); while (process.HasExited == false) { process.Kill(); } } catch (Exception ex) { throw ex; } } private void MainForm_Activated(object sender,EventArgs e) { ActivateUnityWindow(); } private void MainForm_Deactivate(object sender,EventArgs e) { DeactivateUnityWindow(); } /// <summary> /// A simple Background Worker,which sends Data to the Client via a Named Pipe and receives a Response afterwards. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundWorker_DoWork(object sender,DoWorkEventArgs e) { //Init UpdateLogCallback updateLog = new UpdateLogCallback(UpdateLog); string dataFromClient = null; try { //Don't pass until a Connection has been established while (namedPipeServerStream.IsConnected == false) { Thread.Sleep(100); } //Created stream for reading and writing StreamString serverStream = new StreamString(namedPipeServerStream); //Send to Client and receive Response (pause using Thread.Sleep for demonstration Purposes) Invoke(updateLog,new object[] { "Send Data to Client: " + serverStream.WriteString("A Message from Server.") + " Bytes." }); Thread.Sleep(1000); dataFromClient = serverStream.ReadString(); Invoke(updateLog,new object[] { "Received Data from Server: " + dataFromClient }); Thread.Sleep(1000); Invoke(updateLog,new object[] { "Send Data to Client: " + serverStream.WriteString("A small Message from Server.") + " Bytes." }); Thread.Sleep(1000); dataFromClient = serverStream.ReadString(); Invoke(updateLog,new object[] { "Send Data to Client: " + serverStream.WriteString("Another Message from Server.") + " Bytes." }); Thread.Sleep(1000); dataFromClient = serverStream.ReadString(); Invoke(updateLog,new object[] { "Send Data to Client: " + serverStream.WriteString("The final Message from Server.") + " Bytes." }); Thread.Sleep(1000); dataFromClient = serverStream.ReadString(); Invoke(updateLog,new object[] { "Received Data from Server: " + dataFromClient }); } catch(Exception ex) { //Handle usual Communication Exceptions here - just logging here for demonstration and debugging Purposes Invoke(updateLog,new object[] { ex.Message }); } } /// <summary> /// A simple Method,which writes Text into a Console / Log. Will be invoked by the Background Worker,since WinForms are not Thread-safe and will crash,if accessed directly by a non-main-Thread. /// </summary> /// <param name="text">The Text to log.</param> private void UpdateLog(string text) { lock (richTextBox_Console) { Console.WriteLine(text); richTextBox_Console.AppendText(Environment.NewLine + text); } } } }
将此代码附加到Unity应用程序中的GameObject.还要确保将带有TextMeshProUGUI组件的GameObject(TextMeshPro-Asset,你会在你的资产商店中找到它)引用到’textObject’成员,这样应用程序就不会崩溃,你可以看到一些调试信息.
另外(如上所述)确保构建并释放Unity应用程序,将其命名为“Child.exe”并将其放在与WinForms应用程序相同的文件夹中.
using UnityEngine; using System.Collections; using UnityEngine.UI; using System; using System.IO.Pipes; using System.Security.Principal; using Assets; using System.ComponentModel; using TMPro; /// <summary> /// A simple Example Project,which demonstrates Communication between WinForms-Applications and embedded Unity Engine Applications via Named Pipes. /// /// This Code (Unity) is considered as the Client,which will receive Data from the WinForms-Server and send a Response in Return. /// </summary> public class SendAndReceive : MonoBehavIoUr { /// <summary> /// A GameObject with an attached Text-Component,which serves as a simple Console. /// </summary> public GameObject textObject; /// <summary> /// The Background Worker,which will send and receive Data. /// </summary> private BackgroundWorker backgroundWorker; /// <summary> /// A Buffer needed to temporarely save Text,which will be shown in the Console. /// </summary> private string textBuffer = ""; /// <summary> /// Use this for initialization. /// </summary> void Start () { //Init the Background Worker to send and receive Data this.backgroundWorker = new BackgroundWorker(); this.backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork); this.backgroundWorker.WorkerReportsProgress = true; this.backgroundWorker.RunWorkerAsync(); } /// <summary> /// Update is called once per frame. /// </summary> void Update () { //Update the Console for debugging Purposes lock (textBuffer) { if (string.IsNullOrEmpty(textBuffer) == false) { textObject.GetComponent<TextMeshProUGUI>().text = textObject.GetComponent<TextMeshProUGUI>().text + Environment.NewLine + textBuffer; textBuffer = ""; } } } /// <summary> /// A simple Background Worker,which receives Data from the Server via a Named Pipe and sends a Response afterwards. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundWorker_DoWork(object sender,DoWorkEventArgs e) { try { //Init NamedPipeClientStream client = null; string dataFromServer = null; //Create Client Instance client = new NamedPipeClientStream(".","NamedPipeExample",PipeOptions.None,TokenImpersonationLevel.None); updateTextBuffer("Initialized Client"); //Connect to Server client.Connect(); updateTextBuffer("Connected to Server"); //Created stream for Reading and Writing StreamString clientStream = new StreamString(client); //Read from Server and send Response (flush in between to clear the Buffer and fix some strange Issues I Couldn't really explain,sorry) dataFromServer = clientStream.ReadString(); updateTextBuffer("Received Data from Server: " + dataFromServer); client.Flush(); updateTextBuffer("Sent Data back to Server: " + clientStream.WriteString("Some data from client.") + " Bytes."); dataFromServer = clientStream.ReadString(); updateTextBuffer("Received Data from Server: " + dataFromServer); client.Flush(); updateTextBuffer("Sent Data back to Server: " + clientStream.WriteString("Some more data from client.") + " Bytes."); dataFromServer = clientStream.ReadString(); updateTextBuffer("Received Data from Server: " + dataFromServer); client.Flush(); updateTextBuffer("Sent Data back to Server: " + clientStream.WriteString("A lot of more data from client.") + " Bytes."); dataFromServer = clientStream.ReadString(); updateTextBuffer("Received Data from Server: " + dataFromServer); client.Flush(); updateTextBuffer("Sent Data back to Server: " + clientStream.WriteString("Clients final message.") + " Bytes."); //Close client client.Close(); updateTextBuffer("Done"); } catch (Exception ex) { //Handle usual Communication Exceptions here - just logging here for demonstration and debugging Purposes updateTextBuffer(ex.Message + Environment.NewLine + ex.StackTrace.ToString() + Environment.NewLine + "Last Message was: " + textBuffer); } } /// <summary> /// A Buffer,which allows the Background Worker to save Texts,which may be written into a Log or Console by the Update-Loop /// </summary> /// <param name="text">The Text to save.</param> private void updateTextBuffer(string text) { lock (textBuffer) { if (string.IsNullOrEmpty(textBuffer)) { textBuffer = text; } else { textBuffer = textBuffer + Environment.NewLine + text; } } } }
此外,两个脚本都需要一个额外的类,它封装了管道流,因此发送和接收文本变得更加容易.
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace Assets { /// <summary> /// Simple Wrapper to write / read Data to / from a Named Pipe Stream. /// /// Code based on: /// https://stackoverflow.com/questions/43062782/send-message-from-one-program-to-another-in-unity /// </summary> public class StreamString { private Stream ioStream; private UnicodeEncoding streamEncoding; public StreamString(Stream ioStream) { this.ioStream = ioStream; streamEncoding = new UnicodeEncoding(); } public string ReadString() { int len = 0; len = ioStream.ReadByte() * 256; len += ioStream.ReadByte(); byte[] inBuffer = new byte[len]; ioStream.Read(inBuffer,len); return streamEncoding.GetString(inBuffer); } public int WriteString(string outString) { byte[] outBuffer = streamEncoding.GetBytes(outString); int len = outBuffer.Length; if (len > UInt16.MaxValue) { len = (int)UInt16.MaxValue; } ioStream.WriteByte((byte)(len / 256)); ioStream.WriteByte((byte)(len & 255)); ioStream.Write(outBuffer,len); ioStream.Flush(); return outBuffer.Length + 2; } } }
如果你读到这一点的帖子:谢谢:)我希望它能帮助你成功的开发者之旅!
我原型的最终结果:
解决方法
diffrence between UIApplication sharedApplication
First:
[[[[UIApplication sharedApplication] delegate] window] addSubview:UIView];
Second:
[[UIApplication sharedApplication].keyWindow addSubview:UIView];
它们是在IOS相同的,但在Mac OS它们可以是不同的,因为在IOS只有一个窗口,而在Mac OS可能多于一个更多。
从文档:
- For [[[UIApplication sharedApplication] delegate] window];
提出一个故事板时使用的窗口。此属性包含用于显示设备的主屏幕上的应用程序的可视内容的窗口。
i.e this is the property window
you have in your appDelegate.h
file
- for
[[UIApplication sharedApplication] keyWindow];
这个属性保存的窗户数组,它是最近发出的makeKeyAndVisible消息中的一个UIWindow对象。
最简单的设置是只具有一个的UIWindow。通常该窗口保持作为您的应用程序委托的属性。的keyWindow是指定接收键盘和其他非触摸相关的事件之一。一次仅一个窗口可能是关键窗口。所以,如果你添加第二个窗口,并使其成为keyWindow(通过[窗口makeKeyAndVisible]),您的线路返回不同的窗口!in iOS you sent makeKeyAndVisible
in your appDelegate.m
inside
application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
to window
, which what we have above, so they are the same. (This is done automatically if you are using storyboards)
对于大多数用途,它们将是相同的...,但并非总是如此。
[UIApplication sharedApplication].keyWindow
is the window which is currently being displayed on the device. This is normally your application''s window, but could be a system window.
[UIApplication sharedApplication].delegate.window
is the window your application is expected to use.
哪一个应该使用?那么这一切都取决于上下文。
如果要更新应用程序的一部分,那么你应该添加视图到应用程序的窗口。这几乎总是你想要做什么。
就个人而言,我总是用[UIApplication的sharedApplication].delegate.window addSubview:视图]或[self.view.window addSubView:视图(内UIViewController中),当我需要直接添加视图到窗口。
当你想提出一个观点,以目前所显示,如果不考虑窗口属于您的应用程序或者是一些系统窗口的窗口可能会有一些时间。我还没有遇到这种情况。
我们今天的关于使用Swift的UIApplication子类和swift uiview的分享就到这里,谢谢您的阅读,如果想了解更多关于6.10 Swift的懒加载(lazy initialization)使用解析 [Swift原创教程]、android.app.Application子类,onTerminate不被调用、c# – 在Winforms-Application中嵌入的Unity-Application上调用函数[复制]、diffrence between UIApplication sharedApplication的相关信息,可以在本站进行搜索。
本文标签: