v11: encode wiederhergestellt, Absturz-Melder, Methoden-Check

This commit is contained in:
serverlele30 committed 2026-10-23 15:46:07 +02:00
1 parent b85fe90c38
commit 98a94e765e
5 files changed
+89 -5

No files matched your search

-4
View File
@@ -28,7 +28,6 @@
65AABC92308B81050050A7AC /* GuidanceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AABC90308B81050050A7AC /* GuidanceManager.m */; };
65AABC98308B83BE0050A7AC /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AABC94308B83BE0050A7AC /* SettingsViewController.m */; };
65AABC99308B83BE0050A7AC /* BVGSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AABC95308B83BE0050A7AC /* BVGSettings.m */; };
65AABC9C308B87630050A7AC /* AppIcon.appiconset in Resources */ = {isa = PBXBuildFile; fileRef = 65AABC9B308B87630050A7AC /* AppIcon.appiconset */; };
65AABCA5308B87E00050A7AC /* CardCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AABC9E308B87E00050A7AC /* CardCell.m */; };
65AABCA6308B87E00050A7AC /* ChipBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AABCA1308B87E00050A7AC /* ChipBar.m */; };
65AABCA7308B87E00050A7AC /* BVGTheme.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AABCA3308B87E00050A7AC /* BVGTheme.m */; };
@@ -78,7 +77,6 @@
65AABC94308B83BE0050A7AC /* SettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsViewController.m; sourceTree = "<group>"; };
65AABC95308B83BE0050A7AC /* BVGSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BVGSettings.m; sourceTree = "<group>"; };
65AABC97308B83BE0050A7AC /* SettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsViewController.h; sourceTree = "<group>"; };
65AABC9B308B87630050A7AC /* AppIcon.appiconset */ = {isa = PBXFileReference; lastKnownFileType = folder; path = AppIcon.appiconset; sourceTree = "<group>"; };
65AABC9D308B87E00050A7AC /* CardCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CardCell.h; sourceTree = "<group>"; };
65AABC9E308B87E00050A7AC /* CardCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CardCell.m; sourceTree = "<group>"; };
65AABC9F308B87E00050A7AC /* ChipBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChipBar.h; sourceTree = "<group>"; };
@@ -137,7 +135,6 @@
65AABC74308B7A0E0050A7AC /* BVGAPI.h */,
65AABC93308B83BE0050A7AC /* BVGSettings.h */,
65AABC95308B83BE0050A7AC /* BVGSettings.m */,
65AABC9B308B87630050A7AC /* AppIcon.appiconset */,
65AABC97308B83BE0050A7AC /* SettingsViewController.h */,
65AABC94308B83BE0050A7AC /* SettingsViewController.m */,
65AABC76308B7A0E0050A7AC /* BVGAPI.m */,
@@ -235,7 +232,6 @@
buildActionMask = 2147483647;
files = (
65AABCAC308B91540050A7AC /* add_files.rb in Resources */,
65AABC9C308B87630050A7AC /* AppIcon.appiconset in Resources */,
659F88E3308B5CFA00D46649 /* LaunchScreen.storyboard in Resources */,
659F88E0308B5CFA00D46649 /* Assets.xcassets in Resources */,
65AABC8B308B7D8C0050A7AC /* LIESMICH.txt in Resources */,
+32
View File
@@ -16,9 +16,38 @@
@property (nonatomic, strong) UITabBarController *tabs;
@end
// Absturz-Melder: speichert Grund + Stack einer nicht abgefangenen Exception,
// beim naechsten Start wird beides angezeigt (iOS 9 schreibt den Grund nicht in den Crash-Report).
static NSString * const kLastCrashKey = @"lastCrash";
static void BVGUncaughtException(NSException *e) {
NSArray *stack = e.callStackSymbols ?: @[];
stack = [stack subarrayWithRange:NSMakeRange(0, MIN((NSUInteger)25, stack.count))];
NSString *report = [NSString stringWithFormat:@"%@\n%@\n\n%@", e.name, e.reason ?: @"(kein Grund)",
[stack componentsJoinedByString:@"\n"]];
[[NSUserDefaults standardUserDefaults] setObject:report forKey:kLastCrashKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
@implementation AppDelegate
- (void)showLastCrashIfAny {
NSString *report = [[NSUserDefaults standardUserDefaults] stringForKey:kLastCrashKey];
if (!report) return;
[[NSUserDefaults standardUserDefaults] removeObjectForKey:kLastCrashKey];
UIAlertController *a = [UIAlertController alertControllerWithTitle:@"Letzter Absturz"
message:report
preferredStyle:UIAlertControllerStyleAlert];
[a addAction:[UIAlertAction actionWithTitle:@"Kopieren" style:UIAlertActionStyleDefault handler:^(UIAlertAction *x) {
[UIPasteboard generalPasteboard].string = report;
}]];
[a addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]];
[self.window.rootViewController presentViewController:a animated:YES completion:nil];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSSetUncaughtExceptionHandler(&BVGUncaughtException);
[application registerUserNotificationSettings:
[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge)
categories:nil]];
@@ -48,6 +77,9 @@
self.window.tintColor = [BVGTheme textPrimary];
self.window.rootViewController = self.tabs;
[self.window makeKeyAndVisible];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.8 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self showLastCrashIfAny];
});
// Favoriten in die iOS-Suche aufnehmen (falls frisch installiert)
for (NSDictionary *f in [BVGAPI favorites]) [BVGAPI indexStopInSpotlight:f[@"id"] name:f[@"name"]];
+1 -1
View File
@@ -10,7 +10,7 @@ extern NSString * const BVGAlarmsChangedNotification;
// Netzwerk
+ (void)getJSON:(NSString *)path completion:(void (^)(id json, NSError *error))completion;
+ (NSString *)encode:(NSString *)s;
+ (NSString *)encode:(id)value; // NSString, NSNumber, nil/NSNull -> URL-kodiert
+ (NSString *)lastSource; // "serverlele" oder "transport.rest" - wer zuletzt geantwortet hat
// Zeit
+16
View File
@@ -87,6 +87,22 @@ NSString * const BVGAlarmsChangedNotification = @"BVGAlarmsChanged";
}] resume];
}
// Fuer URL-Pfade und -Parameter: nur ASCII-Buchstaben/Ziffern bleiben unkodiert
// (sonst liefert NSURL bei Umlauten nil). Nimmt auch NSNumber/NSNull entgegen.
+ (NSString *)encode:(id)value {
NSString *s = nil;
if ([value isKindOfClass:[NSString class]]) s = value;
else if (value && value != [NSNull null]) s = [value description];
if (!s.length) return @"";
static NSCharacterSet *allowed;
static dispatch_once_t once;
dispatch_once(&once, ^{
allowed = [NSCharacterSet characterSetWithCharactersInString:
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"];
});
return [s stringByAddingPercentEncodingWithAllowedCharacters:allowed] ?: @"";
}
#pragma mark - Zeit
+ (NSDateFormatter *)isoFormatter {
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env python3
"""Prueft, ob jede in einer .h deklarierte Methode in der passenden .m implementiert ist.
Hintergrund: Objective-C kompiliert auch dann, wenn eine Methode fehlt - die App stuerzt erst
zur Laufzeit mit "unrecognized selector" ab.
Aufruf (im Projektordner): python3 BVGNearby/check_methods.py BVGNearby
Rueckgabe: 0 = alles da, 1 = etwas fehlt (bricht z.B. deploy.sh ab)
"""
import glob
import os
import re
import sys
folder = sys.argv[1] if len(sys.argv) > 1 else "."
missing = []
for header in sorted(glob.glob(os.path.join(folder, "*.h"))):
impl_path = header[:-2] + ".m"
if not os.path.exists(impl_path):
continue
hdr = open(header, encoding="utf-8").read()
impl = open(impl_path, encoding="utf-8").read()
for decl in re.findall(r"^[+-]\s*\([^)]*\)\s*[^;]+;", hdr, re.M):
kind = decl[0]
parts = re.findall(r"(\w+)\s*:", decl)
if parts:
selector = "".join(p + ":" for p in parts)
pattern = (r"^" + re.escape(kind) + r"\s*\([^)]*\)\s*"
+ r".*?".join(re.escape(p) + r"\s*:" for p in parts) + r"[^;{]*\{")
else:
selector = re.match(r"^[+-]\s*\([^)]*\)\s*(\w+)", decl).group(1)
pattern = r"^" + re.escape(kind) + r"\s*\([^)]*\)\s*" + re.escape(selector) + r"\s*\{"
if not re.search(pattern, impl, re.M | re.S):
missing.append(f"{os.path.basename(impl_path)}: {kind}{selector}")
if missing:
print("FEHLENDE METHODEN (App würde abstürzen):")
print("\n".join(" " + m for m in missing))
sys.exit(1)
print("Methoden-Check: alle deklarierten Methoden sind implementiert.")