Проблема заключается не в методе push
для Array.prototype
, а в ваших привязках. Вы изменяете один и тот же объект s
на каждой итерации вашего блока async.foreach
, который на самом деле является тем же объектом, что и ранее определенный Subscriber
.
Сначала вы должны перенести объявление s
переменная к блоку foreach.
А также, если вы хотите создать объект со значениями по умолчанию, он должен быть function
, который возвращает новый объект:
function Subscriber() {
return {
'userID': '',
'email': '',
'name': '',
'stage': '',
'poster': false,
'canEmail': false,
'stage': ''
};
};
И тогда вы можете создать экземпляр объекта Subscriber
следующим образом:
var s = Subscriber();
Подробнее см. этот ответ или Закрытие на MDN .
Указатель объекта (т. е. экземпляр ссылочного типа ) можно преобразовать в UnsafePointer<Void>
(отображение Swift const void *
, UnsafeRawPointer
в Swift 3) и обратно. В Objective-C вы должны написать
void *voidPtr = (__bridge void*)self;
//
MyType *mySelf = (__bridge MyType *)voidPtr;
(см. 3.2.4 Модифицированные броски в документации Clang ARC для точного значения этих приведений.)
Для этой цели Swift имеет тип Unmanaged
. Это немного громоздко использовать, потому что он работает с COpaquePointer
вместо UnsafePointer<Void>
. Вот два вспомогательных метода (названных в честь создания Objective-C __bridge
):
func bridge<T : AnyObject>(obj : T) -> UnsafePointer<Void> {
return UnsafePointer(Unmanaged.passUnretained(obj).toOpaque())
// return unsafeAddressOf(obj) // ***
}
func bridge<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {
return Unmanaged<T>.fromOpaque(COpaquePointer(ptr)).takeUnretainedValue()
// return unsafeBitCast(ptr, T.self) // ***
}
«Сложное» выражение необходимо только для того, чтобы удовлетворить строгую систему Swifts. В скомпилированном коде это просто бросок между указателями. (Он может быть написан короче, как указано в комментариях ***
, если вы готовы использовать «небезопасные» методы, но скомпилированный код идентичен.)
Используя эти вспомогательные методы, вы можете передать self
к функции C как
let voidPtr = bridge(self)
(или UnsafeMutablePointer<Void>(bridge(self))
, если для функции C требуется изменяемый указатель) и преобразовать ее обратно в указатель объекта - например в функции обратного вызова - как
let mySelf : MyType = bridge(voidPtr)
Передача права собственности не выполняется, поэтому вы должны убедиться, что self
существует до тех пор, пока используется указатель void.
И для полноты, эквивалент Swift __bridge_retained
и __bridge_transfer
из Objective-C будет
func bridgeRetained<T : AnyObject>(obj : T) -> UnsafePointer<Void> {
return UnsafePointer(Unmanaged.passRetained(obj).toOpaque())
}
func bridgeTransfer<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {
return Unmanaged<T>.fromOpaque(COpaquePointer(ptr)).takeRetainedValue()
}
bridgeRetained()
, набрасывает указатель на указатель на пустоту и сохраняет объект , bridgeTransfer()
преобразует указатель void обратно в указатель объекта и потребляет сохранение.
Преимущество заключается в том, что объект не может быть освобожден между вызовами, потому что поддерживается сильная ссылка. Недостатком является то, что вызовы должны быть правильно сбалансированы и что он может легко вызвать циклы сохранения.
Обновление для Swift 3 (Xcode 8):
func bridge<T : AnyObject>(obj : T) -> UnsafeRawPointer {
return UnsafeRawPointer(Unmanaged.passUnretained(obj).toOpaque())
}
func bridge<T : AnyObject>(ptr : UnsafeRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
}
func bridgeRetained<T : AnyObject>(obj : T) -> UnsafeRawPointer {
return UnsafeRawPointer(Unmanaged.passRetained(obj).toOpaque())
}
func bridgeTransfer<T : AnyObject>(ptr : UnsafeRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()
}
соответствующие изменения в «небезопасных указателях» описаны в
Этот ответ не выглядит как конкретный для обратного вызова как ответ Мартина R , но может быть полезным ...
Обычно вы можете передать значение любого типа небезопасному указателю void с помощью оператора &
:
func baz(p: UnsafeMutablePointer<Void>) -> String {
return "\(p)"
}
var num = 5
print(baz(&num))
Однако, чтобы пройти self
, вам нужно сделать это в контексте, где self
является изменяемым. Это означает, что вам нужно сделать это в методе мутации (или init
) типа значения, а не в качестве ссылочного типа:
struct FooValue {
mutating func bar() {
print(baz(&self))
}
}
var myFooValue = FooValue()
myFooValue.bar()
Если вы хотите использовать ссылочный тип, вы 'нужно создать локальную копию ссылки и передать указатель на это:
class FooReference {
func bar() {
var localSelf = self
print(baz(&localSelf))
}
}
let myFooReference = FooReference()
myFooReference.bar()
Мне кажется, что это то, что withUnsafeMutablePointer
для - преобразовать произвольный указатель Swift в указатель C. По-видимому, вы могли бы это сделать (я не пробовал, но проверенный мной код работает безопасно):
var mself = self
withUnsafeMutablePointer(&mself) { v in
let v2 = UnsafeMutablePointer<Void>(v)
myStruct.inputProcRefCon = v2
}
var mself = self
нужно будет заменить постоянным глобальным.
– matt
23 October 2015 в 15:27
mself
функции C, а не адрес объекта. Как вы сказали, mself
должен быть глобальным, что я считаю довольно неэлегантным. - Код из stackoverflow.com/a/30788165/341994 выглядит сложным, но на самом деле ничего не делает. Он просто передает указатель объекта self
в изменяемый указатель. На самом деле его можно упростить let observer = unsafeAddressOf(self)
, сгенерированный код сборки, похоже, идентичен.
– Martin R
23 October 2015 в 17:44
unsafeBitCast()
...
– Martin R
23 October 2015 в 18:07
func bridge<T : AnyObject>(obj : T) -> UnsafePointer<Void> {
return UnsafePointer(Unmanaged.passUnretained(obj).toOpaque())
}
func bridge<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
}
func bridgeRetained<T : AnyObject>(obj : T) -> UnsafePointer<Void> {
return UnsafePointer( Unmanaged.passRetained(obj).toOpaque())}
func bridgeTransfer<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()}
Box
с переменнойweak
вself
. 2. Callback опционально указывает значение на сильное. 3. Если экземпляр освобожден иBox
содержит nil, обратный вызов потребляет сохранениеBox
? – Kirsteins 13 May 2016 в 09:21deinit
экземпляра. – Martin R 16 May 2016 в 10:23