Realm Swift

当前这个翻译,主要是方便我自己查阅api,有很多地方写的比较晦涩或者没有翻译,敬请谅解
version 0.98.7

官方文档
参考文献

Realm支持类型

  • String,Nsstring
  • Int
  • Int8,Int16,Int32,Int64
  • Float
  • Double
  • Bool
  • NSData
  • NSDate
  • RealmOptional
  • Object
  • List

Realm Object

Model Properties

属性声明方式

Class => T:Object

Type Non-optional Optional
声明类型 非可选类型声明方式 可选类型声明方式
Bool dynamic var value = false let value = RealmOptional()
Int dynamic var value = 0 let value = RealmOptional()
Float dynamic var value:Float = 0.0 let value = RealmOptional()
Double dynamic var value:Double = 0 let value = RealmOptional()
String dynamic var value = “” dynamic var value: String? = nil
Data dynamic var value = Data() dynamic var value: NSData? = nil
Date dynamic var value = Date() dynamic var value: Date? = nil
Object n/a: must be optional dynamic var value: Class?
List let value = List n/a: must be non-optional
注意事项:
  • Object只能声明成可选类型.
  • List和RealmOptional只能声明成非可选类型.
  • 使用var修饰变量,必须要使用dynamic.具体原因请查照)

Relationships

一对一(To-One Relationships)

class Dog: Object {
    // ... other property declarations
    dynamic var owner: Person? // to-one relationships must be optional
}

一对多(To-Many Relationships)

class Person: Object {
    // ... other property declarations
    let dogs = List<Dog>()
}
class Dog: Object {
    dynamic var name = ""
    dynamic var age = 0
    var owners: [Person] {
        // Realm 并不会存储这个属性,因为这个属性只定义了 getter
        // 定义“owners”,和 Person.dogs 建立反向关系
        return linkingObjects(Person.self,forProperty: "dogs")
    }
}

Indexed Properties

添加索引属性,加快查询速度.

class Book: Object {
  dynamic var price = 0
  dynamic var title = ""

  override static func indexedProperties() -> [String] {
    return ["title"]
  }
}

索引支持类型

  • strings
  • integers
  • booleans
  • NSDate
注意事项


Indexing a property will greatly speed up queries where the property is compared for equality (i.e. the = and IN operators),at the cost of slower insertions.


使用索引增加查询速度的代价是插入数据时速度会降低

Auto-Updating Objects

顾名思义当一个数据的内容改变时,它会自动更新该数据的所有实例化对象

let myDog = Dog()
myDog.name = "Fido"
myDog.age = 1

try! realm.write {
  realm.add(myDog)
}

let mypuppy = realm.objects(Dog).filter("age == 1").first
try! realm.write {
  mypuppy!.age = 2
}

print("age of my dog: \(myDog.age)") // => 2

当数据变化,需要更新界面时,需要配合 [Realm notifications](#Realm notifications) 或 [key-value observation](#key-value observation)实现,后续会详细描述这2个功能

Primary Keys

声明主键之后,对象将被允许查询,更新速度更加高效,并且要求每个对象保持唯一性。
一旦带有主键的对象被添加到 Realm 之后,该对象的主键将不可修改。

class Person: Object {
  dynamic var id = 0
  dynamic var name = ""

  override static func primaryKey() -> String? {
    return "id"
  }
}

Ignored Properties

重写 Object.ignoredProperties() 可以防止 Realm 存储数据模型的某个属性。Realm 将不会干涉这些属性的常规操作,它们将由成员变量(ivar)提供支持,并且您能够轻易重写它们的 setter 和 getter。

class Person: Object {
  dynamic var tmpID = 0
  var name: String { // read-only properties are automatically ignored
    return "\(firstName) \(lastName)"
  }
  dynamic var firstName = ""
  dynamic var lastName = ""

  override static func ignoredProperties() -> [String] {
    return ["tmpID"]
  }
}

Writes

所有写入操作(添加,修改,删除)都必须依托一个write transaction.

由于write transaction会占用一定的资源,所以尽量精简write transaction的个数.当队列写入时,只需要一个就write transaction

Creating Objects

数据赋值方式:

// (1) Create a Dog object and then set its properties var myDog = Dog() myDog.name = "Rex" myDog.age = 10 // (2) Create a Dog object from a dictionary let myOtherDog = Dog(value: ["name" : "Pluto","age": 3]) // (3) Create a Dog object from an array let myThirdDog = Dog(value: ["Fido",5])

nested Objects

嵌套赋值方式:

// Instead of using already existing dogs...
let aPerson = Person(value: ["Jane",30,[aDog,anotherDog]])

// ...we can create them inline
let anotherPerson = Person(value: ["Jane",[["Buster",5],["Buddy",6]]])

Adding Objects

write操作是阻塞操作,如果有一个写操作,那么其他线程的write操作都会被阻塞.

最好是将write操作放在一个单独的线程中.

// Create a Person object let author = Person() author.name = "David Foster Wallace" // Get the default Realm let realm = try! Realm() // You only need to do this once (per thread) // Add to the Realm inside a transaction try! realm.write { realm.add(author) }

Updating Objects

Typed Updates

// Update an object with a transaction
try! realm.write {
  author.name = "Thomas Pynchon"
}

Creating and Updating Objects With Primary Keys

update:true Object必须具有PrimaryKeys.否则会报错.

// Creating a book with the same primary key as a prevIoUsly saved book
let cheeseBook = Book()
cheeseBook.title = "Cheese recipes"
cheeseBook.price = 9000
cheeseBook.id = 1
 // Updating book with id = 1
try! realm.write {
  realm.add(cheeseBook,update: true)
}
 // Assuming a "Book" with a primary key of `1` already exists.
try! realm.write {
  realm.create(Book.self,value: ["id": 1,"price": 9000.0],update: true)
  // the book's `title` property will remain unchanged.
}

Key-Value Coding

let persons = realm.objects(Person)
try! realm.write {
  persons.first?.setValue(true,forKeyPath: "isFirst")
  // set each person's planet property to "Earth"
  persons.setValue("Earth",forKeyPath: "planet")
}

Deleting Objects

// let cheeseBook = ... Book stored in Realm
try! realm.write {
// Delete an object with a transaction
  realm.delete(cheeseBook)

  realm.delete(List<T:Object>)

  realm.delete(Results<T:Object>)

  // Delete all objects from the realm
  realm.deleteall()
}

Queries

通过查询操作,Realm 将会返回包含 Object 集合的Results实例。Results 的表现和 Array 十分相似,并且包含在 Results 中的对象能够通过索引下标进行访问。

所有的查询(包括查询和属性访问)在 Realm 中都是延迟加载的,只有当属性被访问时,才能够读取相应的数据。也就是说当没有使用数据前,进行多次排序或者过滤都是不需要额外cpu时间的

查询结构不是copy对象,而是引用对象.所以在Write操作中修改查询数据,是直接修改数据库中的数据.

基本查询语句

let dogs = realm.objects(Dog) // retrieves all Dogs from the default Realm

Filtering

条件查询

类似nspredicate,同时支持nspredicate.

// Query using a predicate string
var tanDogs = realm.objects(Dog).filter("color = 'tan' AND name BEGINSWITH 'B'")
 // Query using an nspredicate
let predicate = nspredicate(format: "color = %@ AND name BEGINSWITH %@","tan","B")
tanDogs = realm.objects(Dog).filter(predicate)

var tanDogs = realm.objects(Dog).filter("color = 'tan'").filter("name BEGINSWITH 'B'")

支持的断言类型

  • 比较操作数(comparison operand)可以是属性名称或者某个常量,但至少有一个操作数必须是属性名称;
  • 比较操作符 ==、<=、<、>=、>、!=,以及 BETWEEN 支持 int、long、long long、float、double 以及 NSDate 属性类型的比较,比如说 age == 45
  • 相等比较 ==以及!=,比如说Results().filter(“company == %@”,company)
  • 比较操作符 == and != 支持布尔属性
  • 对于 Nsstring 和 NSData 属性来说,我们支持 ==、!=、BEGINSWITH、CONTAINS 以及 ENDSWITH 操作符,比如说 name CONTAINS ‘Ja’
  • 字符串支持忽略大小写的比较方式,比如说 name CONTAINS[c] ‘Ja’ ,注意到其中字符的大小写将被忽略
  • **Realm 支持以下复合操作符:“AND”、“OR” 以及 “NOT”。比如说 name BEGINSWITH ‘J’ AND age >= 32;
    包含操作符 IN,比如说 name IN {‘Lisa’,‘Spike’,‘Hachi’}**
  • ==、!=支持与 nil 比较,比如说 Results().filter(“ceo == nil”)。注意到这只适用于有关系的对象,这里 ceo 是 Company 模型的一个属性
  • ANY 比较,比如说 ANY student.age < 21
  • 支持复合表达式类型@count,@min,@max,@sum and @avg.例如realm.objects(Company).filter(“employees.@count > 5”)
  • 子查询有如下限制
    • @count is the only operator that may be applied to the SUBQUERY expression
    • The SUBQUERY(…).@count expression must be compared with a constant
    • correlated subqueries are not yet supported

Sorting

// Sort tan dogs with names starting with "B" by name
let sortedDogs = realm.objects(Dog).filter("color = 'tan' AND name BEGINSWITH 'B'").sorted("name")
 //倒序
let sortedDogs = realm.objects(Dog).filter("color = 'tan' AND name BEGINSWITH 'B'").sorted("name",ascending:false)

Auto-Updating Results

结果会自动更新

let puppies = realm.objects(Dog).filter("age < 2")
puppies.count // => 0
try! realm.write {
  realm.create(Dog.self,value: ["name": "Fido","age": 1])
}
puppies.count // => 1

Limiting Results

// Loop through the first 5 Dog objects
// restricting the number of objects read from disk
let dogs = try! Realm().objects(Dog)
for i in 0..<5 {
  let dog = dogs[i]
  // ...
}

Realms

Realm Configuration

Realm.Configuration.defaultConfiguration = config.直接设置默认配置
假设需要快速切换账户,可以使用一下代码

func setDefaultRealmForUser(username: String) {
  var config = Realm.Configuration()

  // Use the default directory,but replace the filename with the username
  config.path = NSURL.fileURLWithPath(config.path!)
                  .URLByDeletingLastPathComponent?
                  .URLByAppendingPathComponent("\(username).realm")
                  .path

  // Set this as the configuration used for the default Realm
  Realm.Configuration.defaultConfiguration = config
}

Other Realms

指定BundleData中的Realm

let config = Realm.Configuration(
    // Get the path to the bundled file
    path: NSBundle.mainBundle().pathForResource("MyBundledData",ofType:"realm"),// Open the file in read-only mode as application bundles are not writeable
    readOnly: true)

// Open the Realm with the configuration
let realm = try! Realm(configuration: config)

// Read some data from the bundled Realm
let results = realm.objects(Dog).filter("age > 5")

注意

如果是初始化一个Realm,指定的路径必须是可写的

In-Memory Realms

内存中的Realms,没有保存在磁盘上.

优点:可以快速的访问数据,而不需要考虑数据持久化的性能开销.内存Realms只会在temp路径里存放几个文件,用来进行线程间数据同步,不会将Realms中任何数据写入磁盘中

注意

由于ARC的原因,内存Realms创建的数据必须要有一个强引用,否则会被回收

Error Handling

错误只会发生在第一次创建Realms.如果Realms已经创建,以后不会发生错误.

do {
  let realm = try Realm()
} catch let error as NSError {
  // handle error
}

copying Objects Between Realms

数据拷贝只能是不同Realms都在同一线程中创建的,否则无法实现数据拷贝

realm.create(MyObjectSubclass.self,value: originalObjectInstance) 

Auxiliary Realm Files

Realms内部处理的辅助文件,对于使用者来说,就是汇报bug的时候,需要一并提交这些文件

  • .realm.lock - A lock file for resource locks.
  • .realm.log_a,.realm.log_b - Log files for transaction logs.
  • .realm.note - A named pipe for notifications.

Class Subsets

Realms可以配置只保存特定的Class,除指定的Class外,其他Class一律不存储.

let config = Realm.Configuration(objectTypes: [MyClass.self,MyOtherClass.self])
let realm = try! Realm(configuration: config)

Deleting Realm Files

删除本地Realm

Realm在使用的时候,都是强引用,如果需要的话,就用autoreleasepool来包含

如果使用强引用,直接删除也不会有什么影响

autoreleasepool {
  // all Realm usage here
}
let manager = NSFileManager.defaultManager()
let realmPath = Realm.Configuration.defaultConfiguration.path as! Nsstring
let realmPaths = [
  realmPath as String,realmPath.stringByAppendingPathExtension("lock")!,realmPath.stringByAppendingPathExtension("log_a")!,realmPath.stringByAppendingPathExtension("log_b")!,realmPath.stringByAppendingPathExtension("note")!
]
for path in realmPaths {
  do {
    try manager.removeItemAtPath(path)
  } catch {
    // handle error
  }
}

Using Realm with Background App Refresh

这章主要是说如何使用IOS本地加密,详情查看官方文档.

Threading

这一章主要是讲多线程开发,大量写入事务最好是放在其他线程中,以防止UI线程被阻塞

只在一个线程中处理所有事情,不需要担心并发和多线程.(然并卵的话)

Realm在多线程处理上不需要使用线程锁,只需要注意写入操作需要在Write事件中.

Realm为了更好的支持多线程处理,它为每个线程都创建了一个视图(sql中的视图概念??).由于每个线程都有自己的snapshots,导致线程之间同步问题.

唯一需要记住的是:你不能在多个线程之间共享同一个Realm对象.如果这样的话,就会导致一个线程上修改了数据,其他线程无法同步数据.

Seeing Changes From Other Threads

在UI线程或者其他添加Runloop的线程上,Realm都会自动更新其他线程Runloop的操作结果.(这里是说其他线程有更新,UI线程或Runloop线程都不会更新数据)

在其他类型的线程上操作,都是基于Snapshots.

所以最好的处理方法是,保存唯一的一个视图,这样就不用担心多线程并发的问题.

UI线程或者其他添加Runloop的线程上,数据都会自动刷新,除非将Realm.autorefresh设置为NO

其他类型的线程,都是以最后一次修改成功的Realm为snapshot,除非是手动refresh

Realm.commitWrite后,Realm会刷新一次

最好是不要经常性的手动调用refresh(),当你正在刷新,其他线程有其他事务进行处理时,会导致数据”pinned”,进而增大Realm在磁盘上的空间

```

###Passing Instances Across Threads
继承于NSObject的类,是可以在线程之间传递的.<BR>
继承于Realm,Object,Results,or List的类,是无法在线程之间传递的.否则会引起崩溃.<BR>
多线程之间传递数据的解决方案:<BR>

* Object:可以通过primary key来实现.
* Results:可以filter或者nspredicate来实现.

**Realm一些可以多线程操作的属性和方法,如下**

* Realm: all properties,class methods,and initializers.
* Object: invalidated,objectSchema,realm,and initializers.
* Results: objectClassName and realm.
* List: invalidated,objectClassName,and realm.

###Using a Realm Across Threads
**想要在不同线程中,访问同一个Realm文件,就必须要在各自线程中获取相同配置的Realm实例.就是重新调用Realm.realm().**<BR>

let queue = dispatch_queue_create(“test”,disPATCH_QUEUE_CONCURRENT);
dispatch_async(queue) {
autoreleasepool {
// Get realm and table instances for this thread
let realm = try! Realm()

// Break up the writing blocks into smaller portions
// by starting a new transaction
for idx1 in 0..<1000 {
  realm.beginWrite()

  // Add row via dictionary. Property order is ignored.
  for idx2 in 0..<1000 {
    realm.create(Person.self,value: [
      "name": "\(idx1)","birthdate": NSDate(timeIntervalSince1970: NSTimeInterval(idx2))
    ])
  }

  // Commit the write transaction
  // to make this data available to other threads
  try! realm.commitWrite()
}

}
}

##JSON
不支持json数据直接导入,但是支持 NSJSONSerialization.JSONObjectWithData(_:options:)转换的导入.<BR>

// A Realm Object that represents a city
class City: Object {
dynamic var city = “”
dynamic var id = 0
// other properties left out …
}

// Insert from NSData containing JSON
try! realm.write {
let json = try! NSJSONSerialization.JSONObjectWithData(data,options: NSJSONReadingOptions())
realm.create(City.self,value: json,update: true)
}

######注意事项
* float properties should be initialized with float-backed NSNumbers(float类型需要使用NSNumber来声明)* * * * * * * * 
* NSDate and NSData properties cannot be automatically inferred from strings,but should be converted to the appropriate type before passing to Realm().create(_:value:update:).(**没理解**)
* If a JSON null (i.e. NSNull) is supplied for a required property,an exception will be thrown.(如果一个json对象为null,会抛出异常)
* If no property is supplied on insert for a required property,an exception will be thrown.(如果一个声明属性,没有对应的值,会抛出异常)
* Realm will ignore any properties in the JSON not defined by the Object.(当Json对象中有Object没有声明变量,会忽略)


##Notifications
多线程中对特定数据有修改时,会发送Notifications.<BR>
**需要注意的是,addNotificationBlock返回的Token是必须要被强引用的,否则无法回调**<BR>
支持的调用方式:

* Realm.addNotificationBlock(_:)
* AnyRealmCollection.addNotificationBlock(_:)
* Results.addNotificationBlock(_:)
* List.addNotificationBlock(_:)
* NotificationToken.stop()

// Observe Realm Notifications
let token = realm.addNotificationBlock { notification,realm in
viewController.updateUI()
}

// later
token.stop()

// Observe Results Notifications
let token = realm.objects(Person).filter(“age > 5”).addNotificationBlock { results,error in
// results is identical to ‘realm.objects(Person).filter(“age > 5”)’
viewController.updateUI()
}

// later
token.stop()

##Key-Value Observation
**这章略过,由于不熟悉KVO,所以先不学习这章**<BR>
Realm objects are Key-Value Observing compliant for most properties. All persisted (non-ignored) properties on your Object subclasses are KVO-compliant,along with the invalidated property on Object and List.

Observing properties of standalone instances of Object subclasses works just like with any other dynamic property,but note that you cannot add an object to a Realm (with realm.add(obj) or other similar methods) while it has any registered observers.

Observing properties of persisted objects works a little differently. With persisted objects,there are three times when the value of a property may change: when you directly assign to it; when you call realm.refresh() or the Realm is automatically refreshed after a write transaction is committed on a different thread; and when you call realm.beginWrite() after changes on a different thread which have not been picked up by a refresh on the current thread.

In the latter two cases,all of the changes made in the write transaction(s) on another thread will be applied at once,and KVO notifications will all be sent at once. Any intermediate steps are discarded,so if in the write transaction you incremented a property from one to ten,on the main thread you’ll get a single notification of a change directly from one to ten. Because properties can change in value when not in a write transaction or even as part of beginning a write transaction,trying to modify persisted Realm objects from within observeValueForKeyPath(_:ofObject:change:context:) is not recommended.

Unlike NSMutableArray properties,observing changes made to List properties does not require using mutableArrayValueForKey(_:),although that is supported for compatiblity with things not written for Realm. Instead,you can simply call the modification methods on List directly,and anyone observing the property it is stored in will be notified. List properties do not need to be marked as dynamic to be observable,unlike normal properties.

In our example apps you can find a short example of using Realm with ReactiveCocoa from Objective‑C,and ReactKit from Swift.

##Migrations
**数据迁移,版本迭代时,数据库常用**<BR>

###为什么要进行数据库迁移

class Person: Object {
dynamic var firstName = “”
dynamic var lastName = “”
dynamic var age = 0
}

在某个版本更新中,变成了下边这样

class Person: Object {
dynamic var fullName = “”
dynamic var age = 0
}

那么就需要用到数据迁移了.

###Performing a Migration

Realm.Configuration.defaultConfiguration.schemaVersion = 2;
Realm.Configuration.defaultConfiguration.migrationBlock = {migration,oldSchemaVersion in
if oldSchemaVersion < 1 {
migration.enumerate(Person.className(),{ (oldobject,newObject) in
let firstName = oldobject![“firstName”] as! String
let lastName = oldobject![“lastName”] as! String
newObject![“fullName”] = “(firstName) (lastName)”
})
}

};
###Adding more versions

Realm.Configuration.defaultConfiguration.schemaVersion = 2;
Realm.Configuration.defaultConfiguration.migrationBlock = {migration,oldSchemaVersion in
if oldSchemaVersion < 10 {
migration.enumerate(Person.className(),newObject) in
if oldSchemaVersion < 1 {
let firstName = oldobject![“firstName”] as! String
let lastName = oldobject![“lastName”] as! String
newObject![“fullName”] = “(firstName) (lastName)”
}

// Add the `email` property to Realms with a schema version of 0 or 1
                        if oldSchemaVersion < 2 {
                            newObject!["email"] = ""
                        }
            })
        }

    };
###Linear Migrations
需要考虑跨版本的数据库迁移,例如v0直接升级到v3版本,而不是只考虑v2升级到v3.

##Encryption
**Realm的加密只支持OS X,IOS,WatchKit.但是不支持watchOS**<BR> Realm的加密方式为:**key为64字节,AES-256+SHA2**<BR> **加密过的 Realm 只会带来很少的额外资源占用(通常最多只会比平常慢10%)**<BR> **注:如果数据库加密后,由于不知道加密方式,即使有原始key,也无法获取解密key,所以无法用Realm browser查看.**
**注:如果数据库加密,每次获取Realm实例时,必须使用encryptionKey.**
func getKey() -> NSData {
    // Identifier for our keychain entry - should be unique for your application
    let keychainIdentifier = "io.Realm.Test"
    let keychainIdentifierData = keychainIdentifier.dataUsingEncoding(NSUTF8StringEncoding,allowLossyConversion: false)!

    // First check in the keychain for an existing key
    var query: [Nsstring: AnyObject] = [
        kSecclass: kSecclassKey,kSecAttrApplicationTag: keychainIdentifierData,kSecAttrKeySizeInBits: 512,kSecReturnData: true
    ]

    // To avoid Swift optimization bug,should use withUnsafeMutablePointer() function to retrieve the keychain item
    // See also: http://stackoverflow.com/questions/24145838/querying-ios-keychain-using-swift/27721328#27721328
    var dataTypeRef: AnyObject?
    var status = withUnsafeMutablePointer(&dataTypeRef) { SecItemcopyMatching(query,UnsafeMutablePointer($0)) }
    if status == errSecSuccess {
        return dataTypeRef as! NSData
    }

    // No pre-existing key from this application,so generate a new one
    let keyData = NSMutableData(length: 64)!
    let result = SecRandomcopyBytes(kSecRandomDefault,64,UnsafeMutablePointer<UInt8>(keyData.mutableBytes))
    assert(result == 0,"Failed to get random bytes")

    // Store the key in the keychain
    query = [
        kSecclass: kSecclassKey,kSecValueData: keyData
    ]

    status = SecItemAdd(query,nil)
    assert(status == errSecSuccess,"Failed to insert the new key in the keychain")

    return keyData
}

“`

Realm Swift的更多相关文章

  1. ios – Realm:无法使用类型'(Object.Type)’的参数列表调用’对象’

    所以我在Realm中有一个非常简单的Book模型而我正在尝试在帮助程序类中检索所有书籍:这一行:抛出标题中的错误.我疯了还是这不是Realm文档告诉我们要做的?解决方法realm.objects()不会返回[Book]但会返回结果?.所以你必须改变userBookLibrary的类型:

  2. iOS:核心图像和多线程应用程序

    我试图以最有效的方式运行一些核心图像过滤器.试图避免内存警告和崩溃,这是我在渲染大图像时得到的.我正在看Apple的核心图像编程指南.关于多线程,它说:“每个线程必须创建自己的CIFilter对象.否则,你的应用程序可能会出现意外行为.”这是什么意思?我实际上是试图在后台线程上运行我的过滤器,所以我可以在主线程上运行HUD(见下文).这在coreImage的上下文中是否有意义?

  3. ios – 多个NSPersistentStoreCoordinator实例可以连接到同一个底层SQLite持久性存储吗?

    我读过的关于在多个线程上使用CoreData的所有内容都讨论了使用共享单个NSPersistentStoreCoordinator的多个NSManagedobjectContext实例.这是理解的,我已经使它在一个应用程序中工作,该应用程序在主线程上使用CoreData来支持UI,并且具有可能需要一段时间才能运行的后台获取操作.问题是NSPersistentStoreCoordinator会对基础

  4. ios – XCode断点应该只挂起当前线程

    我需要调试多线程错误.因此,为了获得生成崩溃的条件,我需要在代码中的特定点停止一个线程,并等待另一个线程到达第二个断点.我现在遇到的问题是,如果一个线程遇到断点,则所有其他线程都被挂起.有没有办法只停止一个线程,让其他线程运行,直到它们到达第二个断点?)其他更有趣的选择:当你点击第一个断点时,你可以进入控制台并写入这应该在该断点处暂停当前上下文中的线程一小时.然后在Xcode中恢复执行.

  5. ios – Swift 2.0中的动态可选属性

    我已经看过这篇文章OptionaldynamicpropertiesinSwift,但我不想在NSObject中包装该类.这只是关于Realm数据库我没有nil属性,但我认为这是一个很好的方式来建模我的数据库.在可以在https://realm.io/docs/swift/latest/中找到的Realm文档中,它表示支持选项.这是我的码这是我的错误我知道这是与上面的帖子相同的代码和错误,但我很好

  6. ios – 在后台线程中写入Realm后,主线程看不到更新的数据

    >清除数据库.>进行API调用以获取新数据.>将从API检索到的数据写入后台线程中的数据库中.>从主线程上的数据库中读取数据并渲染UI.在步骤4中,数据应该是最新数据,但我们没有看到任何数据.解决方法具有runloops的线程上的Realm实例,例如主线程,updatetothelatestversionofthedataintheRealmfile,因为通知被发布到其线程的runloop.在后台

  7. ios – 如何使用string中的参数创建Selector

    我正在使用Swift3.1和Xcode8.3.3编写程序.我想创建一个类,负责在键盘出现和消失时移动整个视图.但是我在使用字符串参数创建自定义选择器时遇到了困难.要显示或隐藏键盘我们需要功能:我正在尝试创建一个这样的选择器:它正在编译,但是当键盘出现时,它会崩溃.因为它是独立的类我不能使用这种结构:因为它将Swift函数转换为Objective-C函数.所以问题是:如何用参数字符串创建一个Selector表单?

  8. ios – 为什么,将nil作为参数从Objc C发送到swift类初始化器,用新对象替换nil参数

    除非属性本身被声明为nonnull:

  9. ios – RxSwift:返回一个带有错误的新observable

    我有一个函数返回BoolObservable,具体取决于它是否正常.解决方法返回包含单个元素的可观察序列.相反,你应该使用这样的东西:Create方法从指定的subscribe方法实现创建一个可观察的序列.在你的情况下:Anonymousdisposable是在您想要中断的情况下调用的操作.假设您离开视图控制器或应用程序需要完成该服务,您不再需要再调用此请求.它非常适合视频上传或更大的内容.您可以

  10. ios – 如何为NSNotification编写单元测试

    我在swift工作,我想刷新一个页面,所以我使用通知发送它,我在一个ViewController中发布通知并在另一个中添加观察者,它工作正常.我想要做的是在swift中添加单元测试.我查了很多网站但是没能做到.我是新手,不知道从哪里开始.基本上工作是,当我点击按钮通知被发布时,并且当加载下一个视图控制器时,添加通知观察者.我该怎么做单元测试提前致谢编辑:码并添加观察者解决方法一般的解决方案是:使用

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部