7,Emulator Control  当此,可以套一些装备状态与行。 
Telephony
Status:改变电话语音以及数目方案的状态,模拟不同之大网快。 
TelePhony
Actions:发送模拟的电话呼叫和短信及模拟器。 
Location
Controls:发送虚拟的一贯数据到模拟器里,我们虽足以推行一定之类的操作。可以收工的于Manual里输入经度纬度发送至模拟器,也可经过
GPX和KML文件。 

题目讲述:

全局埋点,依赖让 runtime 机制, 所以换种问法就是: swift 中怎么样延续应用
objc 的runtime 机制.

3,当一个在运转的程序调用waitForDebugger()函数时,客户端名字旁边会显示一个红的icon,知道debugger连上针对
应的虚拟机,这是debugger会变成绿色。 

个体记录,仅供参考,不包严格意义及的不易。

6,Allocation Tracker  于这视图里,我们得跟每个选中的虚拟机的内存分配情况。点击”Start
Tracking”后点击”Get Allocations “就可以看到。 

swift 中,如何当函数内,声明 static 变量 ?

统计 1

缓解方案:

片段 D:

class Book{
    let name: String

    lazy var whoami:(()->String)? = {
        return self.name
    }

    init(name:String) {
        self.name = name
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

var aBook:Book? = Book(name: "风之影")

aBook?.whoami = {
    [aBook] in
    return aBook!.name + " new"
}

print(aBook!.whoami!())

aBook = nil

/*
输出:

风之影 new
*/

足看出,这样 aBook 就见面泄露了.片段 D 与 片段 C 的区别在于 closure
中的那么句 [aBook] in
.这个语法,是自我”杜撰”的,语义上接近于以高引用方式捕捉 aBook
对应的真实性对象.官方文档未遭连没有提到有这种语法.

除此以外,参考 objc 中block 的表现,我尝试寻找相关 swift 中 栈(stack) block
的系信息.如果 closure
也区分栈和堆,倒是还可以勉强解释.不了,并无有关的信息,而且 closure
本身为是勿支持 copy 操作的.

注意: 当前复现此问题用底凡 swift 4.0.3 版本,不同版本被的 closure
的行事恐怕未一致.

     开辟后的窗口也,

感觉到好为协调解释,也是一个多有趣之进程。这次,我还新增了“猜想”一苑,来品尝回答一些少没足够资料支撑的题目。

季,左边面板1,左边显示了有当前会找到的享有模拟器或设施列表和每个设备时正值运行的虚拟机列表。虚拟机是以顺序的包命来展示的。 

问题讲述:

精心观察以下两样代码有的例外输出:

片段A:

class Book{
    let name: String

    lazy var whoami:(()->String)? = {
        return self.name
    }

    init(name:String) {
        self.name = name
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

var aBook:Book? = Book(name: "风之影")
print(aBook!.whoami!())

aBook = nil

/*
输出:

风之影
*/

片段B:

class Book{
    let name: String

    lazy var whoami:(()->String)? = {
        return self.name
    }

    init(name:String) {
        self.name = name
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

var aBook:Book? = Book(name: "风之影")
print(aBook!.whoami!())

aBook?.whoami = nil
aBook = nil

/*
输出:

风之影
风之影 is being deinitialized
*/

片段C:

class Book{
    let name: String

    lazy var whoami:(()->String)? = {
        return self.name
    }

    init(name:String) {
        self.name = name
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

var aBook:Book? = Book(name: "风之影")

aBook?.whoami = {
    return aBook!.name + " new"
}

print(aBook!.whoami!())

aBook = nil

/*
输出:

风之影 new
风之影 is being deinitialized
*/

片段A, aBook 内存泄露,经典的 closure self 循环引用问题.

片段B,是 closure self 循环引用的一个可选解决方案,即 self 主动切断对
closure 的引用.

片段C,比较诡异. aBook 引用了一个初的 closure,新的 closure 内以引述了
aBook 一糟糕,但是 aBook
竟然要得以对释放,并从未预期面临的内存泄露问题.令人费解!?

实际可见http://developer.android.com/tools/debugging/ddms.html。
DDMS为IDE和emultor、真正的android设备架起来了同样所大桥。开发人员可以经DDMS看到目标机器上运行的长河/现成状态,可以
android的屏幕及支付机上,可以看经过的heap信息,可以查阅logcat信息,可以查看过程分配内存情况,可以像目标机发送少信与打电话,可
以像android开发发送地理位置信息。可以像gdb一样attach某一个历程调试。 SDK
tools目录下提供了ddms的圆版本,直接运行即可。下面为Eclipse的DDMS
perspective为例简单介绍DDMS的机能。

猜想:

内嵌类型的办法的顾级别,并无见面趁着项目我访问级别的不严更易得比较默认的
internal 更宽裕松.

  eclipse
adt时供的的ddms功能只是真的ddms的一律不怎么有,你
可以直接使用tools下面的ddms来使用所有力量。其中有一个查过程内存分配的效能于有因此。

Swift 版本是:4.0.3。不同版本的 Swift,可能无法复现问题。

六,其他1,File Explorer 
透过Device > File Explorer 就打开File
Explorer。这里可以浏览文件,上污染上充满删除文件,当然就是有对应权限限制的。 

缓解方案:

直白调用,会报错:

error: ‘InnerBook’ is inaccessible due to ‘private’ protection level

品味修改也:

 open class Book: NSObject {
    open class InnerBook{
        open class DeeperBook{

        }
    }
}

依然报错:

error: ‘Book.InnerBook.DeeperBook’ initializer is inaccessible due to
‘internal’ protection level

据悉提示,再修改下 DeeperBook 的初始化方法的访级别:

open class Book: NSObject {
    open class InnerBook{
        open class DeeperBook{
            public init() {

            }
        }
    }
}

统计 2

问题讲述:

模块A:

 open class Book: NSObject {
    private func funcA(){
        print("private funcA")
    }

    public func callFuncA(){
        funcA()
    }
}

模块B:

public extension Book {
    func funcA(){
        print("public funcA")
    }
}

问题:

模块B 中,以下代码的输出是?

let book = Book()
book.funcA()  // --> ?
book.callFuncA() // --> ?

 

疑点: 为什么函数定义外之 closure 不会见唤起作用域内其他变量引用计数的生成?

统计 3

swift 有没有来可以拓展全局埋点的伪魔法机制?

4,如果看叉icon,着象征DDMS用于不克打开虚拟机的端口而无能够建立debugger与虚拟机建立连接。如果见到有着的虚拟机是这么,
很可能是出另外一个DDSM实例在运作。 
五,右边面板1,info 
此地展示关于选中的VM的一般的信,包括过程ID,包名,和虚拟机版本。 

化解方案:

可以就此内嵌类型的 static 属性来缓解,如:

func add() -> Int {
    struct Temp{
        static var base = 0
    }

    Temp.base += 1
    return Temp.base
}

add() // --> 1
add() // --> 2
add() // --> 3

参考:https://stackoverflow.com/a/25354915

    
跟debug,java的perspective一样,安装好adt后会见发生一个DDMS得perspective,打开即可。

釜底抽薪方案:

好一直运行观察:

let book = Book()
book.funcA()  // --> public funcA
book.callFuncA() // --> private funcA

之所以: 通过 extension
覆盖任何模块open类的private方法,不会见来其它诡异的问题.两单实现,都对准互相透明.

再进一步: 模片B以 Optional 方式引入模块A. 如果是当模块B中,通过 extension
覆盖模块A的private 方法.然后在模块 C 中而且引入了模块 A 和
B,此时模块C中好像之函数调用,会是何人模块的章程实现生效?

let book = Book()
book.funcA()  // --> public funcA
book.callFuncA() // --> private funcA

好观看,仍然是模块B中的 public 级别之计生效.

再进一步,如果模块 A 中之艺术,由 private 改吗 public,即:

open class Book: NSObject {
    public func funcA(){
        print("original public funcA")
    }

    public func callFuncA(){
        funcA()
    }
}

这模块C 中的调用,会报错:

error: ambiguous use of ‘funcA()’
book.funcA()
^
A.Book:2:17: note: found this candidate
public func funcA()
^
B.Book:2:17: note: found this candidate
public func funcA()

只要模块 B 以 Required
方式引入模块A,模块C,只引入模块B,此时底调用结果,会不见面生啊两样? –>
然而,并不曾呀两样,依然是一律的 ambiguous 错误.

小结一下:

  • 可高枕无忧地以 extension 中覆盖任何模块中open/public类中定义之非
    public 方法.对于本来模块,会延续用自家之非 public
    的办法定义;定义其他模块,可以对利用 extension 版本中的模块代码.

  • 甭品味当 extension 中定义其他模块中 open/public类中定义的 public
    方法.虽然可定义,但是利用时,会唤起 ambiguous 错误.

  • 以动 extension
    扩展外模块中定义的切近时,最好要叫好壮大的办法加上一定前缀,不然第三方模块万同一露的同名方法,自己之代码就到底跪了.

2,Screen Capture  经Device > Screen Capture 就好截图。 

猜想:

dynamic 是于为此性换灵活性.生产条件下,未来重或者的方案,可能是:

通过商事,约定必须兑现的统计有关的办法 –>
通过单元测试,来担保遵循一定统计协议的门类,在特定的机会一定会调用协议规定的统计方法.

 

嵌套定义的色,如果外层类型是 private, 内层类型是 open,内层类型.那么内层类型有或于其它模块中为应用吗 ?

2,通过这些列表可以找到运行着想调试的activity的虚拟机。每个虚拟机旁边的凡“debugger
pass-through”端口,链接到其中一个端口就见面链接到设备上相应之虚拟机。不管哪,在于是DDMS时,只需要链接到8700端口,因为DDSM
转发所有的通信及手上增选的虚拟机。这样,就甭于历次切换虚拟机是重新配置debugger端口。 

extension 中覆盖某自定义的 framework 中之 open/public class 中之 private 方法,会时有发生什么事?

file
explorer非常有因此,他可以将公文及流传android手机,或者从手机下充斥下来,也足以进行删减操作。选中file
explorer选项卡后,按下三独按钮便只是实现对android手机文件系统的上传,下载,删除操作。

猜想:

扩充第三在模块类时,使用于定义之前缀,总是一个吓的习惯.

亚,DDMS怎样工作1,每一个Android应用还运行于一个Dalvik虚拟机实例里,而各个一个虚拟机实例都是一个单独的进程空间。虚拟机的
线程机制,内存分配和保管,Mutex等等都是因底层操作系统而实现的。所有Android应用之线程都对应一个Linux线程,虚拟机因而可更多之
依赖操作系统的线程调度和管理机制。 
2,DDMS在IDE与装备或者模拟器之间的由在中人之角色。 
3,DDMS启动时见面和ADB之间建立一个device
monitoring
service用于监控装置。当设备断开或链接时,这个service就会打招呼DDMS。 
4,当一个装置链接上时不时,DDSM和ADB之间以会起VM
monitoring service用于监控装置及之虚拟机。 
5,通过ADB
Deamon与设施上的虚拟机的debugger建立链接,这样DDMS就开跟虚拟机对话了。 

题目讲述:

 open class Book: NSObject {
    private class InnerBook{
        open class DeeperBook{

        }
    }
}

于其余一个 swift 模块中,能使用类似下面的种类初始化代码吗?

var book = Book.InnerBook.DeeperBook()

其三,端口1,对于设备上每个虚拟机的debugger,
DDMS都见面张开一个监听端口。端口从8600开。 
2,8700端口 

题目讲述:

以下语句,是编译不过的,提示:“static properties may only be declared on
a type”

func add() -> Int {
    static var base = 0
    base += 1
    return base
}
add()
add()
add()

device窗口罗列模拟器中持有的历程,右上比赛那无异免除按钮分别吗:调试某个进程,更新某个进程,更新过程堆栈信息,停止某个进程,最后一个图片按照
钮时抓取android目前之屏幕。

猜想:

或是 swift 中,只有其中有或直接运用 self 的
closure,才用专门考虑closure引起的内存泄露问题.

私家猜,可能是以 self 比较异常, closure 只能一直捕捉其真对象.

5,Stop a Virtual Machine  通过Actions > Halt VM ,停止一个虚拟机。 

猜想:

如出一辙作用域的同名内嵌类型,多次行,只会真定义一不好.

   emulator
control也是生主要之,通过她可以像手机发送短信,
打电话,已经更新手机位置信息。

釜底抽薪方案:

纯Swift类没有动态性,但每当方式、属性前补加dynamic修饰可以博动态性。

连续自NSObject的Swift类,其后续自父类的主意有动态性,其他自定义方法、属性需要加dynamic修饰才方可博得动态性。

假使方法的参数、属性类型也Swift特有、无法映射到Objective-C的种(如Character、Tuple),则这方、属性无法填补加dynamic修饰(会编译错误)

参考:
http://www.infoq.com/cn/articles/dynamic-analysis-of-runtime-swift

高效验证,可应用:

class A{
    @objc dynamic  func funcA(){
        print("funcA")
    }
}

func methodSwizze(cls: AnyClass, originalSelector: Selector, swizzledSelector:Selector){
    let originalMethod = class_getInstanceMethod(cls, originalSelector)
    let swizzledMethod = class_getInstanceMethod(cls, swizzledSelector)

    if let originalMethod = originalMethod, let swizzledMethod = swizzledMethod {
        method_exchangeImplementations(originalMethod, swizzledMethod)
    }
}

extension A{
    @objc dynamic  func funcB(){
        print("funcB")
    }
}

methodSwizze(cls: A.self, originalSelector: #selector(A.funcA), swizzledSelector: #selector(A.funcB))

let a = A()

a.funcB() // --> funcA
a.funcA() // --> funcB

留意: swift 4 中, 加 dynamic 的同时,也须加 @objc — 即非容许单独加
dynamic 标记.

2,Threads  线程视图列有了之过程的富有线程。 
ID:虚拟机分配的绝无仅有的线程ID,在Dalvik里,它们是打3方始之奇数。 
Tid:linux的线程ID,For the main thread in
a process, this will match the process ID. 
Stauts:线程状态, 
running:正在行程序代码 
sleeping:执行了Thread.sleep() 
monitor:等待接受一个监听锁。 
wait:Object.wait() 
native:正在履行native代码 
vmwait:等待虚拟机 
zombie:线程在垂危之经过 
init:线程在初始化(我们无可能看到) 
starting:线程正在启动(我们无可能看) 
utime:执行用户代码的总共时间 
stime:执行系统代码的共时间 
name:线程的讳 

总结:

 统计 4

统计 5

统计 6

DDMS全称:Dalvik Debug Monitor
Service
平等,DDMS的用意它提供截屏,查看线程和堆的信息,logcat,进程,广播状态信息,模拟来电呼叫和短信,虚拟地理坐标等等。 

   
当你选中某个进程,并随下调试进程按钮时,如果eclipse中来这进程的代码,那就好拓展源代码级别的调节。有点像gdb
attach。图片抓取按钮可以管目前android的显示桌面抓及您的机上,也是老实用。

4,VM Heap  显示一些积的状态,在垃圾回收其间更新。当选定一个虚拟机时, VM
Heap视图不克显得数据,可以点击右侧面包上的盈盈绿色的”Show heap
updates”按钮,然后以点击”Cause GC “实施垃圾回收更新堆的状态。 

好文统计收藏。。。。

   右边那个窗口中生threads, heap , file
explorer选项卡。分别显示线程统计信息,栈信息,以及android的文件系统。

3,Exploring Processes  通过Device  > Show process status ,这里的音讯是经shell命令”ps
-x”输出的。 
4,Examine Radio State 
透过Device > Dump
radio,检测广播状态。