Passing string causing crash sometimes in swift - ios

I run into strange thing I'm getting a crash it this function:
func addQuestion(text:String!)
{
if let txt=text
{
let question=PFObject(className: "questions")
question["text"]=txt
question["userAdding"]=PFUser.currentUser()
question["answeredCount"]=0
question.setObject([], forKey: "answers")
question.setObject(NSDate(), forKey: "dateAdded")
question.setObject(Int(arc4random()) % 10, forKey: "random")
if debug
{question.saveInBackgroundWithBlock(nil)}
else
{question.saveEventually()}
}
}
I'm getting a crash in "if let txt=text"
here is a back trace:
thread #1: tid = 0x241c0c, 0x00063470 pytajnik`pytajnik.ApiClient.addQuestion (text=Some, self=(ObjectiveC.NSObject = {}, debug = true))(Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> () + 10796 at ApiClient.swift:32, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xe7ffdefe)
frame #0: 0x00063470 pytajnik`pytajnik.ApiClient.addQuestion (text=Some, self=(ObjectiveC.NSObject = {}, debug = true))(Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> () + 10796 at ApiClient.swift:32
frame #1: 0x00035428 pytajnik`pytajnik.AddQuestionViewController.addQuestion (sender=AnyObject at 0x006ca054, self=0x17ef85d0)(Swift.AnyObject) -> () + 796 at AddQuestionViewController.swift:17
frame #2: 0x00035a6c pytajnik`#objc pytajnik.AddQuestionViewController.addQuestion (pytajnik.AddQuestionViewController)(Swift.AnyObject) -> () + 100 at AddQuestionViewController.swift:0
frame #3: 0x2a5fdc2a UIKit`-[UIApplication sendAction:to:from:forEvent:] + 70
frame #4: 0x2a5fdbd0 UIKit`-[UIControl sendAction:to:forEvent:] + 44
...
The thing is, the app is not crashing always. Sometime it works sometime it doesn't. And I could't find a pattern.
Could somebody help me understand what is wrong?
UPDATE
thread #1: tid = 0x243f69, 0x0005d478 pytajnik`pytajnik.ApiClient.addQuestion (text=Some, self=(ObjectiveC.NSObject = {}, debug = true))(Swift.Optional<Swift.String>) -> () + 9820 at ApiClient.swift:35, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xe7ffdefe)
frame #0: 0x0005d478 pytajnik`pytajnik.ApiClient.addQuestion (text=Some, self=(ObjectiveC.NSObject = {}, debug = true))(Swift.Optional<Swift.String>) -> () + 9820 at ApiClient.swift:35
frame #1: 0x0002f80c pytajnik`pytajnik.AddQuestionViewController.addQuestion (sender=AnyObject at 0x006c4054, self=0x166a5560)(Swift.AnyObject) -> () + 1760 at AddQuestionViewController.swift:17
frame #2: 0x0002fe40 pytajnik`#objc pytajnik.AddQuestionViewController.addQuestion (pytajnik.AddQuestionViewController)(Swift.AnyObject) -> () + 100 at AddQuestionViewController.swift:0
frame #3: 0x2a5fdc2a UIKit`-[UIApplication sendAction:to:from:forEvent:] + 70
frame #4: 0x2a5fdbd0 UIKit`-[UIControl sendAction:to:forEvent:] + 44
frame #5: 0x2a5e8862 UIKit`-[UIControl _sendActionsForEvents:withEvent:] + 582
frame #6: 0x2a5fd63c UIKit`-[UIControl touchesEnded:withEvent:] + 588
frame #7: 0x2a5fd316 UIKit`-[UIWindow _sendTouchesForEvent:] + 522
frame #8: 0x2a5f6be0 UIKit`-[UIWindow sendEvent:] + 544

You declared the function parameter as implicitly unwrapped optional !, meaning you are sure it will never be nil.
If its possible that this parameter can be nil declare it as optional:
func addQuestion(text: String?) {
if let txt = text {
...
}
}

You have declared the text parameter as an implicitly unwrapped optional, which causes the app to crash if text is nil, and this is what's happening in your case.
Unless you have a specific reason to use an implicitly unwrapped optional, it's always better to use an optional String?, or a non optional String if the parameter can never be nil.
So to fix the problem just change your function signature to this:
func addQuestion(text:String?)
Suggested reading: Implicitly Unwrapped Optionals

Related

Swift Static Array - pointer being freed was not allocated

I have a static array metricsTransactionData in ServiceRequest class. I am invoking multiple request continuously and sometimes I get this error "error for object 0x10b874cb0: pointer being freed was not allocated" on this line ServiceRequest.metricsTransactionData.append(samp). Pls help
public func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
for mem in metrics.transactionMetrics {
var samp = MetricsData()
samp.requestDate = mem.requestStartDate
samp.responseDate = mem.responseEndDate
samp.url = mem.request.url?.absoluteString
ServiceRequest.metricsTransactionData.append(samp)
}
}
Stack trace:
* thread #3, queue = 'NSOperationQueue 0x6000001edb20 (QOS: UNSPECIFIED)', stop reason = signal SIGABRT
frame #0: 0x0000000106897b66 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x00000001068d1080 libsystem_pthread.dylib`pthread_kill + 333
frame #2: 0x0000000106644c45 libsystem_c.dylib`abort + 127
frame #3: 0x00000001067986e4 libsystem_malloc.dylib`malloc_vreport + 545
frame #4: 0x00000001067988d5 libsystem_malloc.dylib`malloc_report + 152
frame #5: 0x00000001049bd910 libswiftCore.dylib`_swift_release_dealloc + 16
frame #6: 0x0000000104980017 libswiftCore.dylib`assignWithTake value witness for Swift.Array + 23
frame #7: 0x00000001046f3a5a libswiftCore.dylib`(extension in Swift):Swift._ArrayBufferProtocol._arrayOutOfPlaceUpdate<A where A1: Swift._PointerFunction, A.Element == A1.Element>(inout Swift._ContiguousArrayBuffer<A.Element>, Swift.Int, Swift.Int, A1) -> () + 1146
frame #8: 0x000000010470aa11 libswiftCore.dylib`Swift.Array._copyToNewBuffer(oldCount: Swift.Int) -> () + 209
frame #9: 0x000000010470aaf0 libswiftCore.dylib`Swift.Array._makeUniqueAndReserveCapacityIfNotUnique() -> () + 192
frame #10: 0x000000010470ad98 libswiftCore.dylib`Swift.Array.append(A) -> () + 24
The error tells you that it is a very bad idea to use a static/global array that will be updated from various background tasks. Swift arrays are not thread-safe.
Means that your array gets resized by one task while another might already do the same, resulting in a bad memory access. Likely calling (at least) append in a DispatchQueue.main.async would fix the problem if you really have to do it that way, but if you want to maintain the order, you would need to handle synchronization yourself.
But in any way i strongly recommend that you find another solution that prevents that kind of write access to the array directly. Globally writable arrays are bad.

CoreData: Object being released in block "error: Mutating a managed object after it has been removed from its context"

This code relies on the CoreData setup from an older forked version of Robbie Hanson's XMPPFramework.
I am retrofitting a data structure to be backed by a managed object CoreData and basically keep a reference to the NSManagedObjectID inside the data structure in question and then have accessors to get/set the data structure properties with the backing data in Core Data.
I am intermittently getting the following error (similar to):
CoreData: error: Mutating a managed object 0xd00000000014000a <x-coredata://90C02501-4756-44F0-ABA6-B725192772A6/ZZXMPPOneToOneInboxItemCoreDataObject/p5> (0x1742971b0) after it has been removed from its context.
I am getting the error both when setting and getting. Obviously the "getting" error is not a "mutating a managed object" error but the stack trace is the same with the release as a culprit.
Here is an example setter:
- (void)setMamUUID:(NSString *)mamUUID
{
ZZXMPPInboxCoreDataStorage *storage = [ZZXMPPInboxCoreDataStorage sharedInstance];
[storage executeBlock:^{
ZZXMPPOneToOneInboxItemCoreDataObject *backingObject = (ZZXMPPOneToOneInboxItemCoreDataObject *)[storage inboxItemInsideBlockWithObjectID:self.itemCoreDataObjectID];
backingObject.mamUUID = mamUUID;
}];
}
and a getter:
- (NSString *)mamUUID
{
ZZXMPPInboxCoreDataStorage *storage = [ZZXMPPInboxCoreDataStorage sharedInstance];
__block NSString *_mamUUID;
[storage executeBlock:^{
ZZXMPPOneToOneInboxItemCoreDataObject *backingObject = (ZZXMPPOneToOneInboxItemCoreDataObject *)[storage inboxItemInsideBlockWithObjectID:self.itemCoreDataObjectID];
_mamUUID = [backingObject mamUUID];
}];
return _mamUUID;
}
The inboxItemInsideBlockWithObjectID: is a helper routine meant to run inside an executeBlock: and looks like this
- (ZZXMPPInboxBaseMemberCoreDataObject *)inboxItemInsideBlockWithObjectID:(NSManagedObjectID *)objectID
{
ZZXMPPInboxBaseMemberCoreDataObject *inboxItem = nil;
inboxItem = [[self managedObjectContext] objectWithID:objectID];
if (nil == inboxItem) {
NSLog(#"..Unable to retrieve an Inbox Item with objectID %#.", objectID);
}
return inboxItem;
}
The "storage" object referenced in both is the XMPPCoreDataStorage object from the XMPPFramework and it's executeBlock: has this as the main code:
dispatch_sync(storageQueue, ^{ #autoreleasepool {
block();
// Since this is a synchronous request, we want to return as quickly as possible.
// So we delay the maybeSave operation til later.
dispatch_async(storageQueue, ^{ #autoreleasepool {
[self maybeSave:OSAtomicDecrement32(&pendingRequests)];
}});
}});
The error is an objc_object::release() (backtrace to follow) and is showing in the debugger at the end of the block in the "setter" code above.
Here is the complete backtrace:
(lldb) bt
* thread #1, queue = 'ZZXMPPRoomHybrid', stop reason = EXC_BAD_ACCESS (code=1, address=0x3a8e9bec8)
frame #0: 0x0000000180459704 libobjc.A.dylib`objc_object::release() + 8
* frame #1: 0x000000010009c1f4 MyApp`__29-[ZZConversation setMamUUID:]_block_invoke((null)=0x000000016fda6838) at ZZConversation.m:280
frame #2: 0x00000001003da11c MyApp`__36-[XMPPCoreDataStorage executeBlock:]_block_invoke((null)=0x000000016fda67b0) at XMPPCoreDataStorage.m:1063
frame #3: 0x0000000103c55218 libdispatch.dylib`_dispatch_client_callout + 16
frame #4: 0x0000000103c61dc8 libdispatch.dylib`_dispatch_barrier_sync_f_invoke + 156
frame #5: 0x0000000103c65adc libdispatch.dylib`_dispatch_barrier_sync_f_slow + 452
frame #6: 0x00000001003da098 MyApp`-[XMPPCoreDataStorage executeBlock:](self=0x00000001702e5100, _cmd="executeBlock:", block=0x000000010009c148) at XMPPCoreDataStorage.m:1061
frame #7: 0x000000010009c0d8 MyApp`-[ZZConversation setMamUUID:](self=0x0000000174223d60, _cmd="setMamUUID:", mamUUID=#"50a35939-f48c-4011-8cfe-b5edf3641e20") at ZZConversation.m:276
frame #8: 0x00000001000a3c80 MyApp`-[ZZConversation mamRequestWasSentWithUUID:](self=0x0000000174223d60, _cmd="mamRequestWasSentWithUUID:", uuid=#"50a35939-f48c-4011-8cfe-b5edf3641e20") at ZZConversation.m:886
frame #9: 0x00000001000af894 MyApp`__58-[ZZXMPPMAMCoreDataStorage requestMessageArchiveWithUser:]_block_invoke((null)=0x00000001742567a0) at ZZXMPPMAMCoreDataStorage.m:73
frame #10: 0x0000000103c55218 libdispatch.dylib`_dispatch_client_callout + 16
frame #11: 0x0000000103c61334 libdispatch.dylib`_dispatch_continuation_pop + 708
frame #12: 0x0000000103c6ff94 libdispatch.dylib`_dispatch_source_latch_and_call + 204
frame #13: 0x0000000103c57300 libdispatch.dylib`_dispatch_source_invoke + 836
frame #14: 0x0000000103c5a05c libdispatch.dylib`_dispatch_main_queue_callback_4CF + 652
frame #15: 0x00000001819b6810 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
frame #16: 0x00000001819b43fc CoreFoundation`__CFRunLoopRun + 1660
frame #17: 0x00000001818e22b8 CoreFoundation`CFRunLoopRunSpecific + 444
frame #18: 0x0000000183396198 GraphicsServices`GSEventRunModal + 180
frame #19: 0x00000001879297fc UIKit`-[UIApplication _run] + 684
frame #20: 0x0000000187924534 UIKit`UIApplicationMain + 208
frame #21: 0x000000010006a688 MyApp`main(argc=5, argv=0x000000016fda7a60) at main.m:16
frame #22: 0x00000001808c55b8 libdyld.dylib`start + 4
(lldb)
I am not sure why the managed object would be released mid-block. The #autoreleasepool surrounds the block and should not release anything while the "sync" block is running.
This happens intermittently and I can run the app several times before it will surface again. Usually, it appears on a "getter" and not a "setter", but since it happens on both and the code for both is similar I don't think that matters.
Why would this managed object instance be released at this point?

NSEntityDescription.insertNewObject Function Causing Crash in Swift 3

I'm following this introduction tutorial to this tutorial, and am completely new to Core Data.
Here is the class that produces the error (however the error sends me to the first line of AppDelegate with a sigabrt. The line that begins "let newUser" seems to produce the error, because the error dissappears when I comment it out.
#IBAction func btnSave(){
let appDel:AppDelegate = (UIApplication.shared().delegate as! AppDelegate)
let context:NSManagedObjectContext = appDel.persistentContainer.viewContext
let newUser = NSEntityDescription.insertNewObject(forEntityName: "Users", into: context) as NSManagedObject
do {
try context.save()
} catch {}
print("Object Saved.")
}
This problem looks similar, but the answer is confusing to me and seems a bit overcomplicated
Since no one has posted about this error on the above Youtube video's comment section yet, I assume this is an error due to a change in Swift 3 (there was another error due to a change in Swift 2 which is documented in the comments).
Any help is greatly appreciated!
frame #0: 0x00000001067cbf06 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x00000001068ec4ec libsystem_pthread.dylib`pthread_kill + 90
frame #2: 0x000000010651e0b3 libsystem_c.dylib`abort + 129
frame #3: 0x00000001067ea43a libc++abi.dylib`abort_message + 266
frame #4: 0x000000010680ea9f libc++abi.dylib`default_terminate_handler() + 267
frame #5: 0x00000001055be59f libobjc.A.dylib`_objc_terminate() + 103
frame #6: 0x000000010680bc09 libc++abi.dylib`std::__terminate(void (*)()) + 8
frame #7: 0x000000010680b894 libc++abi.dylib`__cxa_rethrow + 99
frame #8: 0x00000001055be4b7 libobjc.A.dylib`objc_exception_rethrow + 40
frame #9: 0x00000001030f7bf1 CoreFoundation`CFRunLoopRunSpecific + 433
frame #10: 0x000000010850ea48 GraphicsServices`GSEventRunModal + 161
frame #11: 0x0000000103b30e8b UIKit`UIApplicationMain + 159
* frame #12: 0x0000000102b5dc6f CoreDataYoutube`main + 111 at AppDelegate.swift:5
frame #13: 0x00000001064726bd libdyld.dylib`start + 1
I'm not 100% sure what solved this problem for me... but I think it may have been as simple as my .xcdatamodeld file was not saving the entity and attribute data I entered, and unlike everything else I've encountered in Xcode thusfar, it was required for me to explicitly save (CMD+S) before leaving the .xcdatamodeld file or else the data was immediately erased if I clicked on ViewController or anywhere else from Project navigator.
I'm not sure if this is an error only in the beta version of Xcode 8.0 I'm using, but it seems like it's time to update to 8.1...
After updating to 8.1, the above solution no longer works...
Final update... I'm not sure why the problem reappeared, but I solved it the same way, by deleting the .xcdatamodeld and making a new one. I also ran into trouble, because I changed the name of it from Model.xcdatamodeld to CoreDataYoutube.xcdatamodeld. If you do this, just remember you have to update the line in AppDelegate: let container = NSPersistentContainer(name: "Model") to match.

Failed Trying to use Extensions - Swift

I've recently read The Swift Programming Language document, which introduced to me Extensions, and so I tried to implement this code:
extension SKTexture{
var size: CGSize {
return self.size()
}
}
Later in the same code, I try to access a property of the SKTexture:
someTexture.size.width
However, when I run the app, I get a EXC_BAD_ACCESS
I have also noticed that even if I don't try to access the width property via my new computed property, implementing someTexture.size().width instead of someTexture.size.width , I get this error. Could someone explain me what I'm doing wrong?
Short answer:
For a class derived from NSObject, a Swift property
which has the same name as an existing Objective-C method replaces that method.
Therefore in your case,
var size: CGSize {
return self.size()
}
calls itself recursively until the program aborts with a stack overflow
(well, that's what this site is for :).
If you choose a different name for the property, e.g.
var theSize: CGSize {
return self.size()
}
then everything works nicely.
Long answer:
SKTexture is a subclass of NSObject. Therefore all Swift properties are
"Objective-C compatible". As a consequence, the compiler generates a getter
method that can be called from Objective-C code. The getter method for the
size property is a -size method. So you have now two -size methods:
The original one from SKTexture and a second one defined in your Swift code.
If you do the same with your own Objective-C class defined in the same project
then you will get a linker warning:
instance method 'size' in category from /Users/.../main.o overrides
method from class in /Users/.../MyClass.o
If the Objective-C class is defined in a external framework (as in your case)
the linker does not notice the conflict.
Now return self.size() calls the generated Objective-C getter method, which in turn
calls the extension method. This leads to "infinite" recursion and ultimately
to a stack overflow.
This is confirmed by the stack backtrace which you can get with the lldb bt
command when the program has crashed:
* thread #1: tid = 0x3d2ef, 0x000000010fb15e01 libobjc.A.dylib`objc::DenseMapBase, unsigned long, true, objc::DenseMapInfo > >, DisguisedPtr, unsigned long, objc::DenseMapInfo >, true>::FindAndConstruct(DisguisedPtr const&) + 21, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7fff51b9cfe8)
frame #0: 0x000000010fb15e01 libobjc.A.dylib`objc::DenseMapBase, unsigned long, true, objc::DenseMapInfo > >, DisguisedPtr, unsigned long, objc::DenseMapInfo >, true>::FindAndConstruct(DisguisedPtr const&) + 21
frame #1: 0x000000010fb13e14 libobjc.A.dylib`objc_object::sidetable_retain() + 94
* frame #2: 0x000000010d8674d9 cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 25 at AppDelegate.swift:19
frame #3: 0x000000010d867542 cdtest2`#objc ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize + 34 at AppDelegate.swift:0
frame #4: 0x000000010d8674ed cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 45 at AppDelegate.swift:19
frame #5: 0x000000010d867542 cdtest2`#objc ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize + 34 at AppDelegate.swift:0
frame #6: 0x000000010d8674ed cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 45 at AppDelegate.swift:19
frame #7: 0x000000010d867542 cdtest2`#objc ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize + 34 at AppDelegate.swift:0
frame #8: 0x000000010d8674ed cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 45 at AppDelegate.swift:19
...
frame #149556: 0x000000010d8674ed cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 45 at AppDelegate.swift:19
frame #149557: 0x000000010d867542 cdtest2`#objc ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize + 34 at AppDelegate.swift:0
frame #149558: 0x000000010d8694e0 cdtest2`cdtest2.AppDelegate.application (application=0x00007fccee8005a0, launchOptions=None, self=0x00007fccebc06410)(ObjectiveC.UIApplication, didFinishLaunchingWithOptions : Swift.Optional>) -> Swift.Bool + 112 at AppDelegate.swift:83
frame #149559: 0x000000010d8697b0 cdtest2`#objc cdtest2.AppDelegate.application (cdtest2.AppDelegate)(ObjectiveC.UIApplication, didFinishLaunchingWithOptions : Swift.Optional>) -> Swift.Bool + 560 at AppDelegate.swift:0
...
frame #149572: 0x000000010d86bcaa cdtest2`main + 42 at AppDelegate.swift:0
frame #149573: 0x00000001102f0145 libdyld.dylib`start + 1
This (hopefully) explains also why the problem occurs with both someTexture.size().width and someTexture.size.width:
In both cases, the custom extension method is called.

Why private(set) is not working in Swift?

From Apple docs:
“Each access-level modifier above optionally accepts a single
argument, which consists of the keyword set enclosed in parentheses
(for instance, private(set)). Use this form of an access-level
modifier when you want to specify an access level for the setter of a
variable or subscript that’s less than or equal to the access level of
the variable or subscript itself, as discussed in Getters and
Setters.”
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks.
https://itun.es/ru/jEUH0.l
An example which I try to test in Playground:
import UIKit
class A {
private(set) var name: String {
get { return "Hello, \(self.name)" }
set { self.name = "Unknown" }
}
init(_ name:String) {
self.name = name
}
}
let a = A("Andrew")
a.name = "Hello"
An error which I get in Console Output:
Playground execution failed: error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=2, address=0x7fff5056eff8).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
* thread #1: tid = 0xea721, 0x00000001104f308c libsystem_pthread.dylib`__mtx_droplock + 222, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7fff5056eff8)
* frame #0: 0x00000001104f308c libsystem_pthread.dylib`__mtx_droplock + 222
frame #1: 0x00000001104f2f07 libsystem_pthread.dylib`pthread_mutex_unlock + 68
frame #2: 0x000000010ffbd2b5 libc++.1.dylib`std::__1::mutex::unlock() + 9
frame #3: 0x000000010f040b94 libswift_stdlib_core.dylib`swift_getGenericMetadata + 260
frame #4: 0x000000010ef28a24 libswift_stdlib_core.dylib`Swift.IndexingGenerator.init <A : Swift._Collection>(Swift.IndexingGenerator<A>.Type)(A) -> Swift.IndexingGenerator<A> + 164
frame #5: 0x000000010ef55f1a libswift_stdlib_core.dylib`protocol witness for Swift._Sequence_.generate <A : Swift._Sequence_>(#inout Swift._Sequence_.Self)() -> Swift._Sequence_.Self.GeneratorType in conformance Swift._ContiguousArrayBuffer : Swift._Sequence_ + 154
frame #6: 0x000000010ef284d5 libswift_stdlib_core.dylib`Swift._copyCollectionToNativeArrayBuffer <A : protocol<Swift._Collection, Swift._Sequence_>>(A) -> Swift._ContiguousArrayBuffer<A.GeneratorType.Element> + 1061
frame #7: 0x000000010ef40281 libswift_stdlib_core.dylib`Swift.Array.convertFromArrayLiteral <A>(Swift.Array<A>.Type)(Swift.Array<A>...) -> Swift.Array<A> + 641
frame #8: 0x000000010f1eaae4 PlaygroundLogger`Swift.UInt64.toBytes (Swift.UInt64)() -> Swift.Array<Swift.UInt8> + 292
frame #9: 0x000000010f1eb6a4 PlaygroundLogger`protocol witness for PlaygroundLogger.ToBytes.toBytes <A : PlaygroundLogger.ToBytes>(#inout PlaygroundLogger.ToBytes.Self)() -> Swift.Array<Swift.UInt8> in conformance Swift.UInt64 : PlaygroundLogger.ToBytes + 20
frame #10: 0x000000010f1dbe3d PlaygroundLogger`PlaygroundLogger.BytesStream.write (PlaygroundLogger.BytesStream)(PlaygroundLogger.ToBytes) -> PlaygroundLogger.BytesStream + 77
frame #11: 0x000000010f1dbd74 PlaygroundLogger`PlaygroundLogger.BytesStream.write (PlaygroundLogger.BytesStream)(Swift.String) -> PlaygroundLogger.BytesStream + 164
frame #12: 0x000000010f20f04b PlaygroundLogger`PlaygroundLogger.PlaygroundWriter.encode_config_info (PlaygroundLogger.PlaygroundWriter)() -> () + 203
frame #13: 0x000000010f20f2bf PlaygroundLogger`PlaygroundLogger.PlaygroundWriter.encode_header (PlaygroundLogger.PlaygroundWriter)() -> () + 127
frame #14: 0x000000010f20ecda PlaygroundLogger`PlaygroundLogger.PlaygroundScopeWriter.encode_scope_event (PlaygroundLogger.PlaygroundScopeWriter)(PlaygroundLogger.ScopeEvent) -> () + 58
frame #15: 0x000000010f1eb997 PlaygroundLogger`playground_log_scope_entry + 87
frame #16: 0x000000011ae20771
What am I doing wrong? Am I missing something?
PS1
This example works fine:
struct TrackedString {
private(set) var numberOfEdits = 0
var value: String = "" {
didSet {
numberOfEdits++
}
}
}
var stringToEdit = TrackedString()
stringToEdit.value = "Hello"
stringToEdit
stringToEdit.numberOfEdits += 10
stringToEdit
More from docs:
“the access level for the numberOfEdits property is marked with a
private(set) modifier to indicate that the property should be settable
only from within the same source file as the TrackedString structure’s
definition.”
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks.
https://itun.es/ru/jEUH0.l
But thats not what I need. Is it possible to disallow to set variable numberOfEdits outside the struct/class?
Your problem lies here:
set { self.name = "Unknown" }
You're setting the value of a computed property within its own setter. This causes infinite recursion. Don't forget that this is a computed property: it doesn't actually have storage. You don't have a variable "self.name" to put anything in; you only have a couple of functions to calculate it. Computed properties like this should use other, non-computed variables for storage. (That's why your structure example works, by the way: you're using a real property with storage.)
You're not being helped in your debugging by fact of running in a Playground. Don't get me wrong: Playgrounds are great. However, in this case, it's taking many seconds to crash, so the crash probably isn't showing up when you expect after an edit. It's also not showing you a full stack trace (which is massive for the problem you're getting, having reproduced it in a "real" app, and might have made it rather more obvious that you'd blown the stack.) When I built and ran the above as a console app, it finally blew up with a stack trace 104,832 calls deep, all but two of which were ...private_cmd.A.name.setter.... Bit of a clue :)

Resources