ios - Mutate inout function paramter inside async block -
i have following playground code:
import uikit import xcplayground class { var arr : [uiimage] = [] func additem(inout localarr: [uiimage]) { dispatch_after(dispatch_time(dispatch_time_now, (int64)(2 * nsec_per_sec)), dispatch_get_main_queue()) { () -> void in localarr.append(uiimage()) print("from inside function localarr: \(localarr)") print("form inside function: \(self.arr)") } } } let = a() a.additem(&a.arr) print("instant print :\(a.arr)") dispatch_after(dispatch_time(dispatch_time_now, (int64)(3 * nsec_per_sec)), dispatch_get_main_queue()) { () -> void in print("print after delay: \(a.arr)") } xcplaygroundpage.currentpage.needsindefiniteexecution = true
the output is:
instant print :[] inside function localarr: [<uiimage: 0x7f99e8706f10>, {0, 0}] form inside function: [] print after delay: []
my question is, why localarr
not same self.arr
inside additem
, not same a.arr
outside? expectation when pass parameter inout
should able operate on actual object, not copy, not happens.
edit: dfri answer know why doesn't work. inout
call-by-copy-restore, check answer here. now, suggestion on how make closure capture reference original object? or perhaps should use other technique achieve want?
for theory on inout
keyword, see following answer:
do not depend on behavioral differences between copy-in copy-out , call reference.
...
when function returns, changes original overwritten value of copy. not depend on implementation of call-by-reference optimization try keep changes being overwritten.
now, additem
function finish call , hence complete inout
copy-in/copy-out task prior delayed dispatch in function. makes inherently bad use delayed dispatches within method of inout
parameters, @ least if delay 1 tries mutate inout
parameter.
to see this, lets track references (rather tracking values) of array, , how possibly show mutation of array during runtime of our example.
func foo(inout bar: [int]) { var pbar : unsafepointer<int> = unsafepointer(bar) print("2: \(pbar)") dispatch_after(dispatch_time(dispatch_time_now, (int64)(2 * nsec_per_sec)), dispatch_get_main_queue()) { () -> void in pbar = unsafepointer(bar) print("3: \(pbar)") bar[0] = 2 pbar = unsafepointer(bar) print("4: \(pbar)") } } var : [int] = [1] var pa : unsafepointer<int> = unsafepointer(a) print("1: \(pa)") foo(&a) print("foo call finished, = \(a)") dispatch_after(dispatch_time(dispatch_time_now, (int64)(5 * nsec_per_sec)), dispatch_get_main_queue()) { () -> void in print("value of naturally not changed here = \(a)") pa = unsafepointer(a) print("5: \(pa)") } xcplaygroundpage.currentpage.needsindefiniteexecution = true
the output quite self-explanatory:
1: 0x00007fe19271e930 2: 0x00007fe19271e930 foo call finished, = [1] <-- call foo finished, 'inout' procedure complete 3: 0x00007fe19271e930 <-- dispatch in `foo` starts 4: 0x00007fe1927085e0 <-- mutates 'bar': 'bar' copied (and never "returned" step finished) value of naturally not changed here = [1] 5: 0x00007fe19271e930 <-- naturally 'a' wont see effect of delayed mutation in foo
Comments
Post a Comment