ObjC class method is not called. GDB playing games? - ios

I have a custom UITableViewController that I am trying to use to manage a UITableView. The flow of my code in the main UIViewController that contains the UITableView goes like below:
_messagesTableVC = [[AllMessagesTableViewController alloc] init];
_allMessageTableView.dataSource = _messagesTableVC;
_allMessageTableView.delegate = _messagesTableVC;
[_allMessageTableView reloadData];
The AllMessagesTableViewController custom UITableViewController class is initialized, it does any processing needed and I set the _allMessageTableView (the UITableView)'s delegates to my custom class.
When I run this code, the program acts as if the custom class is not there but no errors occur. It seems as that NO methods in the custom class are called, no init, no initWithCoder, nothing (I have set breakpoints and checked ;)).
As you can see in the screenshot below, I have set a breakpoint after a custom method refreshData in the custom class that I set to return YES. I assign the return value of refreshData to a local variable test.
In the debugger:
_messagesTableVC custom class does not appear to be nil.
test does not appear to exist.
Not shown here, but when I try to run [_messagesTableVC refreshData] in the debugger it says error: Execution was interrupted, reason: Attempted to dereference an invalid ObjC Object or send it an unrecognized selector.
The process has been returned to the state before expression evaluation.. So is _messagesTableVC actually nil??
What could be causing these problems or is GDB playing games? This is a Messages app extension in case that makes any difference. Thanks.
Update: Here is the code for the custom class init and refreshData
- (instancetype)init {
self = [super init];
if (!self)
return nil;
return self;
}
- (BOOL)refreshData {
return YES;
}
Update2: I created a blank working project and copy pasted the exact files into my original project (because it is an iMessage extension to a big iOS app). It turns out the Xcode is running the older build of the app even after I cleaned the project and changed the UITableView delegate to supply a different text.

I created a Messages Extension for the same project in the past and deleted the target while keeping the files in the project. When I re-added the Messages Extension to the project, Xcode kept running the older build of the app.
I fixed the issue with Xcode running an older version of the app by:
Clean All
Delete Messages Extension target from project
Backup existing Message Extension code to a directory outside the project. Then delete the Messages app group and directory from the project.
Delete the Messages Extension build scheme from project.
Delete project Derived Data directory.
Restart Xcode, create new Messages Extension target in project, and import saved code.

Related

NSnotificationcenter addobserver not working in Release Mode, but works in Debug mode

I found an issue, I have a project which has both Swift and objective - C files. I have added NSnotificationcenter addobserver, which works fine in debug mode, but when I generate IPA (release mode) then it does not work. I have added observer in Objective-C class and posting it from Swift class.
Swift Class: On a button click
#IBAction func btnBackTapped(_ sender: Any) {
let testManager = TestManager.init(window: appdel?.window, andApplicationViewController: splitViewController!)
NotificationCenter.default.post(name: NSNotification.Name(rawValue:"test"), object: nil)}
> Objectice - Class:
-(id)initWithWindow:(UIWindow *)w andApplicationViewController:(UIViewController *)avc {
self = [super init];
if (self)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(testMethod:) name:#"test" object:nil];
}
return self;
}
-(void)testMethod:(NSNotification *)notification {
NSLog(#"testMethod called ");
}
Notes: I have noticed one more thing once I work with Xcode 11 version then it works in both cases. (Release and debug mode works fine). The issue only I faced in Xcode 12 versions, debug mode only. I found the issue and fixed now working fine even in debug mode.
Issue: I have created an object of class TestManager in the local method. So class destroys at the time notification fire. That's why the other class notification method does not call.
Fixes: I have created the object of class TestManager as Global instead of local method. And now working fine.
I have posted this question for two reasons: First one: if someone facing the same issue then can try, as I searched a couple of hours then I was not able to find the issue, because as this issue was only in debug mode, So I was not aware of how to run release mode in Xcode and set breakpoint. I found a way by which you can run from Xcode in release mode as well, no need to create IPA and install it every time. Go to edit scheme > Select run and info tab > Build confirmation > change it debug mode.
Second: May please someone tell me why it works in debug mode and why does not work in release mode when I created another class object in the local method instead of global. Any suggestion will be great, Thanks in advance. Happy coding.

Accessing a method from other target to Today Extension?

I have an iOS app with two targets: the main (the app), and a today extension widget. In the main target I have a class called "TimetablesInformation", and if I call a method of that class from the own target everything goes right. But if I tried to access to that class from the other target (the widget) with this:
TimetablesInformation *info = [[TimetablesInformation alloc] init];
[info getTimes:#"1" forLine:lineName];
it crashes with this code error:
2015-12-26 01:48:04.420 Closer Times[15689:307103] __extensionContextClass != nil -
/BuildRoot/Library/Caches/com.apple.xbs/Sources/libextension/libextension
82/libextension/Common/NSExtensionContext.m:164: Unable to find
NSExtensionContextClass (_NCWidgetExtensionContext) in extension bundle -
did you link the framework that declares the extension point?
TimetablesInformation is targeted to both targets on the right inspector of Xcode... So I have no clue about what can I be doing wrong... Could you help me, please?
EDIT:
The getTimes method:
-(NSArray *)getTimes:(NSString *)actualView forLine:(NSString *)lineName {
if ([actualView isEqual: #(1)]){
if ([lineName isEqual: #"Point A - Point B"]) {
self.workingDayTimesArray = #[#"07:00",#"07:30",#"08:00",#"08:30",#"09:00",#"09:30",#"10:00", #"10:30",#"11:00",#"11:30",#"12:00",#"12:30",#"13:00",#"13:30", #"14:00",#"14:30",#"15:00",#"15:30",#"16:00",#"16:30",#"17:00", #"17:30",#"18:00",#"18:30",#"19:00",#"19:30",#"20:00",#"20:30", #"21:00",#"21:30",#"22:00",#"22:30"];
}
}
I have tried with a void method, but I have the same error. If I call a method from the other target (main app) I haven't crashes, but if I do from my widget, yes I do. Have you an idea of the cause?
It means that you or somebody accidentally removed a framework or library from the target you're running.
In my case, I was getting this crash error when somebody removed NotificationCenter.framework from "Linked Frameworks and Libraries" in General tab or "Link Binary With Libraries" in Build Phases tab. Thus, to fix it, you just need to add it again and everything will work.
So when you re-created TodayExtension target it linked NotificationCenter.framework by default. That's why everything worked for you after this.

App stuck in splash screen on iOS 9 with no error

My app gets stuck on splash screen in iOS 9 both on iPhone and simulator. I can run it on iOS 8 or lower on device and simulator with no problem. My colleague working on the same app has exactly the same problem.
There is no error or anything, just hangs on splash screen. If I stop it on xcode and try to run it from the phone or simulator directly, it would run without any problem.
By the way, I don't see didFinishLaunchingWithOptions or willFinishLaunchingWithOptions getting called!
In your "answer" you include the code:
+(void)initialize
{
titles = #[NSLocalizedString(#"CODE", nil), NSLocalizedString(#"ERROR", nil), NSLocalizedString(#"TROUBLESHOOTING", nil)];
}
This is indeed the source of your issue. It's wise to be very careful when implementing +load or +initialize. #bbum has a great article on exactly that topic.
+initialize is invoked the first time the class (or category) is touched - when the class is initialized +initialize is called by the class loading mechanism. There is no guarantee of when in the class loading process this may happen, which is part of your problem.
In your case you are using NSLocalizedString - which under the hood can be fairly heavy. It has dependancies on several other classes (NSString, etc) and can potentially access the file system. As #bbum points out in his article, that can lead to serious trouble. In your case, this may be a nasty deadlock.
Move your titles = #[NSLocalizedString... line to a more appropriate place in your object, like an initializer, awakeAfterUsingCoder:, etc. and your immediate problem should be solved. After doing so you should check your entire codebase for instances where +initialize and +load are implemented and audit them to make sure those uses are in line with #bbum 's recommendations.
OK I found the problem. It sounds ridiculous though!!
I am using UITabBarController and inside the first controller I have a UITableViewController with a customised datasource class which would initiate a hard code table header and these headers are localised!!
+ (void)initialize {
titles = #[NSLocalizedString(#"CODE", nil), NSLocalizedString(#"ERROR", nil), NSLocalizedString(#"TROUBLESHOOTING", nil)];
}
After I traced the stacks, I realised the process gets stuck right there with no trace and error! I still don't know why!
So I came up with a workaround:
+ (void)initialize {
titles = #[#"Code",#"Error",#"Troubleshooting"];
}
And only retrieve the localised value when returning the text:
- (NSString *)titleAt:(NSInteger)index {
return NSLocalizedString(titles[index],nil);
}
I have both debug and release set to NO
You sure "any SDK" also has arm64?
Ok, I think I found the answer.
You have to specify arm64 in all "Valid Architectures".
If you don't specify arm64 or forget one the app won't start and stays on the splashscreen.
Just verified this.
Is this an Xcode 7 bug?

Initialising swift view controller with nib name in objc class

In my app I have a view controller written in Swift. I imported it in to app delegate which is written in objective c. I try to create an object of the swift view controller like this
ListAllSongsViewController *songListVC = [[ListAllSongsViewController alloc]initWithNibName:#"ListAllSongsViewController" bundle:nil];
The ListAllSongsViewController is written in swift. The project compile without any issue but when executing the above line the app crashes & stops at init method of ListAllSongsViewController
There is nothing in the log, it just stops. Zombie & All exception break points are enabled.
P.S. It only crashes in device (iOS 7.1), but works fine in simulator
Update :
Getting the same issue even if I use the default swift initialiser
ListAllSongsViewController(nibName: "ListAllSongsViewController", bundle: nil)
Usually occurs when you passed a wrong nibName. Considering it crashes only in device, I think you've made a mistake about the case of the string ListAllSongs, because the Mac/Simulator's file system is case insensitive while the device is not.

"dyld: Symbol not found:" for iOS 6-exclusive class in Static Library

NOTE: Yes, I know iOS 6 is under NDA. This question has nothing to do with iOS 6, expect for the fact that the class that I'm referencing is new in iOS 6.
I'm creating a static framework for use in several of my projects, which allows me to use a new API in iOS 6 if it's available, and if it's not it'll fall back to an iOS 5 equivalent. However, although I make sure to always check if a class is valid before using it like so:
if ([NewClass class]) {
NewClass *newClass = [[NewClass alloc] init];
// etc.
}
Whenever I launch my app in the iOS 5 Simulator, I get the following error:
dyld: Symbol not found: _OBJC_CLASS_$_NewClass
(where NewClass stands for the iOS 6 class).
This seems to be an issue just with using a static library, as if I include the certain files that reference the API directly in my project and reference them, it will launch with no issues. I've even tried weak-linking the static library, and it still crashes. The only option that works is weak-linking UIKit, but I would prefer to not have to do that due to UIKit being quite a large framework, and weak-linking takes extra time.
So basically, what can I do to weak link this class in the static library itself?
I guess your IPHONEOS_DEPLOYMENT_TARGET is not set to iOS 5? I just had the same error, because it was already on iOS 6. After setting it to iOS 5, everything was fine.
You can find the configuration both under Target->BuildSettings->IPHONEOS_DEPLOYMENT_TARGET and under Target->Summary->iOS Application Target.
Another approach to avoid this kind of error would be this:
Class myClass = NSClassFromString(#"NewClass")
if( myClass ) {
NSObject *myResult = [myClass aMethod:#"Hello World"];
}

Resources